mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-06 16:32:16 +02:00
Merge branch 'beta' into fix-rng
This commit is contained in:
commit
73416b8665
@ -191,15 +191,15 @@ Now that the enemy Pokémon with the best matchup score is on the field (assumin
|
||||
|
||||
We then need to apply a 2x multiplier for the move's type effectiveness and a 1.5x multiplier since STAB applies. After applying these multipliers, the final score for this move is **75**.
|
||||
|
||||
- **Swords Dance**: As a non-attacking move, this move's benefit score is derived entirely from the sum of its attributes' benefit scores. Swords Dance's `StatChangeAttr` has a user benefit score of 0 and a target benefit score that, in this case, simplifies to
|
||||
- **Swords Dance**: As a non-attacking move, this move's benefit score is derived entirely from the sum of its attributes' benefit scores. Swords Dance's `StatStageChangeAttr` has a user benefit score of 0 and a target benefit score that, in this case, simplifies to
|
||||
|
||||
$\text{TBS}=4\times \text{levels} + (-2\times \text{sign(levels)})$
|
||||
|
||||
where `levels` is the number of stat stages added by the attribute (in this case, +2). The final score for this move is **6** (Note: because this move is self-targeted, we don't flip the sign of TBS when computing the target score).
|
||||
|
||||
- **Crush Claw**: This move is a 75-power Normal-type physical attack with a 50 percent chance to lower the target's Defense by one stage. The additional effect is implemented by the same `StatChangeAttr` as Swords Dance, so we can use the same formulas from before to compute the total TBS and base target score.
|
||||
- **Crush Claw**: This move is a 75-power Normal-type physical attack with a 50 percent chance to lower the target's Defense by one stage. The additional effect is implemented by the same `StatStageChangeAttr` as Swords Dance, so we can use the same formulas from before to compute the total TBS and base target score.
|
||||
|
||||
$\text{TBS}=\text{getTargetBenefitScore(StatChangeAttr)}-\text{attackScore}$
|
||||
$\text{TBS}=\text{getTargetBenefitScore(StatStageChangeAttr)}-\text{attackScore}$
|
||||
|
||||
$\text{TBS}=(-4 + 2)-(-2\times 2 + \lfloor \frac{75}{5} \rfloor)=-2-11=-13$
|
||||
|
||||
@ -221,4 +221,4 @@ When implementing a new move attribute, it's important to override `MoveAttr`'s
|
||||
- A move's **user benefit score (UBS)** incentivizes (or discourages) the move's usage in general. A positive UBS gives the move more incentive to be used, while a negative UBS gives the move less incentive.
|
||||
- A move's **target benefit score (TBS)** incentivizes (or discourages) the move's usage on a specific target. A positive TBS indicates the move is better used on the user or its allies, while a negative TBS indicates the move is better used on enemies.
|
||||
- **The total benefit score (UBS + TBS) of a move should never be 0.** The move selection algorithm assumes the move's benefit score is unimplemented if the total score is 0 and penalizes the move's usage as a result. With status moves especially, it's important to have some form of implementation among the move's attributes to avoid this scenario.
|
||||
- **Score functions that use formulas should include comments.** If your attribute requires complex logic or formulas to calculate benefit scores, please add comments to explain how the logic works and its intended effect on the enemy's decision making.
|
||||
- **Score functions that use formulas should include comments.** If your attribute requires complex logic or formulas to calculate benefit scores, please add comments to explain how the logic works and its intended effect on the enemy's decision making.
|
||||
|
11
index.css
11
index.css
@ -23,15 +23,6 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
#links {
|
||||
width: 90%;
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
#app {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@ -93,7 +84,7 @@ input:-internal-autofill-selected {
|
||||
|
||||
@media (orientation: landscape) {
|
||||
#touchControls {
|
||||
--controls-size: 20vh;
|
||||
--controls-size: 20vh;
|
||||
--text-shadow-size: 1.3vh;
|
||||
--small-button-offset: 4vh;
|
||||
}
|
||||
|
@ -39,7 +39,6 @@
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="./index.css" />
|
||||
<link rel="manifest" href="./manifest.webmanifest">
|
||||
<script type="text/javascript" src="https://app.termly.io/resource-blocker/c5dbfa2f-9723-4c0f-a84b-2895124e851f?autoBlock=on"></script>
|
||||
<script>
|
||||
if ("serviceWorker" in navigator) {
|
||||
window.addEventListener("load", function () {
|
||||
@ -144,13 +143,6 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id="tnc-links">
|
||||
<a href="#" class="termly-display-preferences" style="display: none;" target="_blank" rel="noreferrer noopener">Consent Preferences</a>
|
||||
<a href="https://app.termly.io/policy-viewer/policy.html?policyUUID=bc96778b-3f04-4d25-bafc-0deba53e8bec" target="_blank" rel="noreferrer noopener">Privacy Policy</a>
|
||||
<a href="https://app.termly.io/policy-viewer/policy.html?policyUUID=8b523c05-7ec2-4646-9534-5bd61b386e2a" target="_blank" rel="noreferrer noopener">Cookie Disclaimer</a>
|
||||
<a href="https://app.termly.io/policy-viewer/policy.html?policyUUID=b01e092a-9721-477f-8356-45576702ff9e" target="_blank" rel="noreferrer noopener">Terms & Conditions</a>
|
||||
<a href="https://app.termly.io/policy-viewer/policy.html?policyUUID=3b5d1928-3f5b-4ee1-b8df-2d6c276b0bcc" target="_blank" rel="noreferrer noopener">Acceptable Use Policy</a>
|
||||
</div>
|
||||
<script type="module" src="./src/main.ts"></script>
|
||||
<script src="./src/touch-controls.ts" type="module"></script>
|
||||
<script src="./src/debug.js" type="module"></script>
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.1 KiB |
BIN
public/images/ui/icon_lock.png
Normal file
BIN
public/images/ui/icon_lock.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 172 B |
BIN
public/images/ui/icon_stop.png
Normal file
BIN
public/images/ui/icon_stop.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 205 B |
BIN
public/images/ui/legacy/icon_lock.png
Normal file
BIN
public/images/ui/legacy/icon_lock.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 172 B |
BIN
public/images/ui/legacy/icon_stop.png
Normal file
BIN
public/images/ui/legacy/icon_stop.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 205 B |
@ -841,12 +841,13 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
addEnemyPokemon(species: PokemonSpecies, level: integer, trainerSlot: TrainerSlot, boss: boolean = false, dataSource?: PokemonData, postProcess?: (enemyPokemon: EnemyPokemon) => void): EnemyPokemon {
|
||||
if (Overrides.OPP_LEVEL_OVERRIDE > 0) {
|
||||
level = Overrides.OPP_LEVEL_OVERRIDE;
|
||||
}
|
||||
if (Overrides.OPP_SPECIES_OVERRIDE) {
|
||||
species = getPokemonSpecies(Overrides.OPP_SPECIES_OVERRIDE);
|
||||
}
|
||||
|
||||
if (Overrides.OPP_LEVEL_OVERRIDE !== 0) {
|
||||
level = Overrides.OPP_LEVEL_OVERRIDE;
|
||||
// The fact that a Pokemon is a boss or not can change based on its Species and level
|
||||
boss = this.getEncounterBossSegments(this.currentBattle.waveIndex, level, species) > 1;
|
||||
}
|
||||
|
||||
const pokemon = new EnemyPokemon(this, species, level, trainerSlot, boss, dataSource);
|
||||
@ -973,6 +974,7 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
this.setSeed(Overrides.SEED_OVERRIDE || Utils.randomString(24));
|
||||
console.log("Seed:", this.seed);
|
||||
this.resetSeed(); // Properly resets RNG after saving and quitting a session
|
||||
|
||||
this.disableMenu = false;
|
||||
|
||||
@ -1328,6 +1330,13 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
getEncounterBossSegments(waveIndex: integer, level: integer, species?: PokemonSpecies, forceBoss: boolean = false): integer {
|
||||
if (Overrides.OPP_HEALTH_SEGMENTS_OVERRIDE > 1) {
|
||||
return Overrides.OPP_HEALTH_SEGMENTS_OVERRIDE;
|
||||
} else if (Overrides.OPP_HEALTH_SEGMENTS_OVERRIDE === 1) {
|
||||
// The rest of the code expects to be returned 0 and not 1 if the enemy is not a boss
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this.gameMode.isDaily && this.gameMode.isWaveFinal(waveIndex)) {
|
||||
return 5;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,17 +7,17 @@ import Pokemon, { HitResult, PokemonMove } from "../field/pokemon";
|
||||
import { StatusEffect } from "./status-effect";
|
||||
import { BattlerIndex } from "../battle";
|
||||
import { BlockNonDirectDamageAbAttr, ChangeMovePriorityAbAttr, ProtectStatAbAttr, applyAbAttrs } from "./ability";
|
||||
import { BattleStat } from "./battle-stat";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { CommonAnim, CommonBattleAnim } from "./battle-anims";
|
||||
import i18next from "i18next";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { MoveEffectPhase } from "#app/phases/move-effect-phase.js";
|
||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase.js";
|
||||
import { ShowAbilityPhase } from "#app/phases/show-ability-phase.js";
|
||||
import { StatChangePhase } from "#app/phases/stat-change-phase.js";
|
||||
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
||||
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
|
||||
export enum ArenaTagSide {
|
||||
BOTH,
|
||||
@ -786,8 +786,8 @@ class StickyWebTag extends ArenaTrapTag {
|
||||
applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled);
|
||||
if (!cancelled.value) {
|
||||
pokemon.scene.queueMessage(i18next.t("arenaTag:stickyWebActivateTrap", { pokemonName: pokemon.getNameToRender() }));
|
||||
const statLevels = new Utils.NumberHolder(-1);
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [BattleStat.SPD], statLevels.value));
|
||||
const stages = new Utils.NumberHolder(-1);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [ Stat.SPD ], stages.value));
|
||||
}
|
||||
}
|
||||
|
||||
@ -875,7 +875,7 @@ class TailwindTag extends ArenaTag {
|
||||
// Raise attack by one stage if party member has WIND_RIDER ability
|
||||
if (pokemon.hasAbility(Abilities.WIND_RIDER)) {
|
||||
pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.getBattlerIndex()));
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.ATK], 1, true));
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ Stat.ATK ], 1, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,71 +0,0 @@
|
||||
import i18next, { ParseKeys } from "i18next";
|
||||
|
||||
export enum BattleStat {
|
||||
ATK,
|
||||
DEF,
|
||||
SPATK,
|
||||
SPDEF,
|
||||
SPD,
|
||||
ACC,
|
||||
EVA,
|
||||
RAND,
|
||||
HP
|
||||
}
|
||||
|
||||
export function getBattleStatName(stat: BattleStat) {
|
||||
switch (stat) {
|
||||
case BattleStat.ATK:
|
||||
return i18next.t("pokemonInfo:Stat.ATK");
|
||||
case BattleStat.DEF:
|
||||
return i18next.t("pokemonInfo:Stat.DEF");
|
||||
case BattleStat.SPATK:
|
||||
return i18next.t("pokemonInfo:Stat.SPATK");
|
||||
case BattleStat.SPDEF:
|
||||
return i18next.t("pokemonInfo:Stat.SPDEF");
|
||||
case BattleStat.SPD:
|
||||
return i18next.t("pokemonInfo:Stat.SPD");
|
||||
case BattleStat.ACC:
|
||||
return i18next.t("pokemonInfo:Stat.ACC");
|
||||
case BattleStat.EVA:
|
||||
return i18next.t("pokemonInfo:Stat.EVA");
|
||||
case BattleStat.HP:
|
||||
return i18next.t("pokemonInfo:Stat.HPStat");
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
export function getBattleStatLevelChangeDescription(pokemonNameWithAffix: string, stats: string, levels: integer, up: boolean, count: number = 1) {
|
||||
const stringKey = (() => {
|
||||
if (up) {
|
||||
switch (levels) {
|
||||
case 1:
|
||||
return "battle:statRose";
|
||||
case 2:
|
||||
return "battle:statSharplyRose";
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
return "battle:statRoseDrastically";
|
||||
default:
|
||||
return "battle:statWontGoAnyHigher";
|
||||
}
|
||||
} else {
|
||||
switch (levels) {
|
||||
case 1:
|
||||
return "battle:statFell";
|
||||
case 2:
|
||||
return "battle:statHarshlyFell";
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
return "battle:statSeverelyFell";
|
||||
default:
|
||||
return "battle:statWontGoAnyLower";
|
||||
}
|
||||
}
|
||||
})();
|
||||
return i18next.t(stringKey as ParseKeys, { pokemonNameWithAffix, stats, count });
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
import { ChargeAnim, CommonAnim, CommonBattleAnim, MoveChargeAnim } from "./battle-anims";
|
||||
import { getPokemonNameWithAffix } from "../messages";
|
||||
import Pokemon, { MoveResult, HitResult } from "../field/pokemon";
|
||||
import { Stat, getStatName } from "./pokemon-stat";
|
||||
import { StatusEffect } from "./status-effect";
|
||||
import * as Utils from "../utils";
|
||||
import { ChargeAttr, MoveFlags, allMoves } from "./move";
|
||||
@ -9,20 +8,20 @@ import { Type } from "./type";
|
||||
import { BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, ReverseDrainAbAttr, applyAbAttrs } from "./ability";
|
||||
import { TerrainType } from "./terrain";
|
||||
import { WeatherType } from "./weather";
|
||||
import { BattleStat } from "./battle-stat";
|
||||
import { allAbilities } from "./ability";
|
||||
import { SpeciesFormChangeManualTrigger } from "./pokemon-forms";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import i18next from "#app/plugins/i18n.js";
|
||||
import { CommonAnimPhase } from "#app/phases/common-anim-phase.js";
|
||||
import { MoveEffectPhase } from "#app/phases/move-effect-phase.js";
|
||||
import { MovePhase } from "#app/phases/move-phase.js";
|
||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase.js";
|
||||
import { ShowAbilityPhase } from "#app/phases/show-ability-phase.js";
|
||||
import { StatChangePhase, StatChangeCallback } from "#app/phases/stat-change-phase.js";
|
||||
import i18next from "#app/plugins/i18n";
|
||||
import { Stat, type BattleStat, type EffectiveStat, EFFECTIVE_STATS, getStatKey } from "#app/enums/stat";
|
||||
import { CommonAnimPhase } from "#app/phases/common-anim-phase";
|
||||
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
||||
import { MovePhase } from "#app/phases/move-phase";
|
||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
||||
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
||||
import { StatStageChangePhase, StatStageChangeCallback } from "#app/phases/stat-stage-change-phase";
|
||||
|
||||
export enum BattlerTagLapseType {
|
||||
FAINT,
|
||||
@ -362,8 +361,8 @@ export class ConfusedTag extends BattlerTag {
|
||||
|
||||
// 1/3 chance of hitting self with a 40 base power move
|
||||
if (pokemon.randSeedInt(3) === 0) {
|
||||
const atk = pokemon.getBattleStat(Stat.ATK);
|
||||
const def = pokemon.getBattleStat(Stat.DEF);
|
||||
const atk = pokemon.getEffectiveStat(Stat.ATK);
|
||||
const def = pokemon.getEffectiveStat(Stat.DEF);
|
||||
const damage = Utils.toDmgValue(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * (pokemon.randSeedIntRange(85, 100) / 100));
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:confusedLapseHurtItself"));
|
||||
pokemon.damageAndUpdate(damage);
|
||||
@ -767,7 +766,7 @@ export class OctolockTag extends TrappedTag {
|
||||
const shouldLapse = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
|
||||
|
||||
if (shouldLapse) {
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [BattleStat.DEF, BattleStat.SPDEF], -1));
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [ Stat.DEF, Stat.SPDEF ], -1));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1093,7 +1092,7 @@ export class ContactDamageProtectedTag extends ProtectedTag {
|
||||
}
|
||||
}
|
||||
|
||||
export class ContactStatChangeProtectedTag extends ProtectedTag {
|
||||
export class ContactStatStageChangeProtectedTag extends ProtectedTag {
|
||||
private stat: BattleStat;
|
||||
private levels: number;
|
||||
|
||||
@ -1110,7 +1109,7 @@ export class ContactStatChangeProtectedTag extends ProtectedTag {
|
||||
*/
|
||||
loadTag(source: BattlerTag | any): void {
|
||||
super.loadTag(source);
|
||||
this.stat = source.stat as BattleStat;
|
||||
this.stat = source.stat;
|
||||
this.levels = source.levels;
|
||||
}
|
||||
|
||||
@ -1121,7 +1120,7 @@ export class ContactStatChangeProtectedTag extends ProtectedTag {
|
||||
const effectPhase = pokemon.scene.getCurrentPhase();
|
||||
if (effectPhase instanceof MoveEffectPhase && effectPhase.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT)) {
|
||||
const attacker = effectPhase.getPokemon();
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, attacker.getBattlerIndex(), true, [ this.stat ], this.levels));
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, attacker.getBattlerIndex(), true, [ this.stat ], this.levels));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1348,11 +1347,10 @@ export class HighestStatBoostTag extends AbilityBattlerTag {
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
const stats = [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ];
|
||||
let highestStat: Stat;
|
||||
stats.map(s => pokemon.getBattleStat(s)).reduce((highestValue: number, value: number, i: number) => {
|
||||
let highestStat: EffectiveStat;
|
||||
EFFECTIVE_STATS.map(s => pokemon.getEffectiveStat(s)).reduce((highestValue: number, value: number, i: number) => {
|
||||
if (value > highestValue) {
|
||||
highestStat = stats[i];
|
||||
highestStat = EFFECTIVE_STATS[i];
|
||||
return value;
|
||||
}
|
||||
return highestValue;
|
||||
@ -1370,7 +1368,7 @@ export class HighestStatBoostTag extends AbilityBattlerTag {
|
||||
break;
|
||||
}
|
||||
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:highestStatBoostOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), statName: getStatName(highestStat) }), null, false, null, true);
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:highestStatBoostOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), statName: i18next.t(getStatKey(highestStat)) }), null, false, null, true);
|
||||
}
|
||||
|
||||
onRemove(pokemon: Pokemon): void {
|
||||
@ -1714,25 +1712,25 @@ export class IceFaceBlockDamageTag extends FormBlockDamageTag {
|
||||
*/
|
||||
export class StockpilingTag extends BattlerTag {
|
||||
public stockpiledCount: number = 0;
|
||||
public statChangeCounts: { [BattleStat.DEF]: number; [BattleStat.SPDEF]: number } = {
|
||||
[BattleStat.DEF]: 0,
|
||||
[BattleStat.SPDEF]: 0
|
||||
public statChangeCounts: { [Stat.DEF]: number; [Stat.SPDEF]: number } = {
|
||||
[Stat.DEF]: 0,
|
||||
[Stat.SPDEF]: 0
|
||||
};
|
||||
|
||||
constructor(sourceMove: Moves = Moves.NONE) {
|
||||
super(BattlerTagType.STOCKPILING, BattlerTagLapseType.CUSTOM, 1, sourceMove);
|
||||
}
|
||||
|
||||
private onStatsChanged: StatChangeCallback = (_, statsChanged, statChanges) => {
|
||||
const defChange = statChanges[statsChanged.indexOf(BattleStat.DEF)] ?? 0;
|
||||
const spDefChange = statChanges[statsChanged.indexOf(BattleStat.SPDEF)] ?? 0;
|
||||
private onStatStagesChanged: StatStageChangeCallback = (_, statsChanged, statChanges) => {
|
||||
const defChange = statChanges[statsChanged.indexOf(Stat.DEF)] ?? 0;
|
||||
const spDefChange = statChanges[statsChanged.indexOf(Stat.SPDEF)] ?? 0;
|
||||
|
||||
if (defChange) {
|
||||
this.statChangeCounts[BattleStat.DEF]++;
|
||||
this.statChangeCounts[Stat.DEF]++;
|
||||
}
|
||||
|
||||
if (spDefChange) {
|
||||
this.statChangeCounts[BattleStat.SPDEF]++;
|
||||
this.statChangeCounts[Stat.SPDEF]++;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1740,8 +1738,8 @@ export class StockpilingTag extends BattlerTag {
|
||||
super.loadTag(source);
|
||||
this.stockpiledCount = source.stockpiledCount || 0;
|
||||
this.statChangeCounts = {
|
||||
[ BattleStat.DEF ]: source.statChangeCounts?.[ BattleStat.DEF ] ?? 0,
|
||||
[ BattleStat.SPDEF ]: source.statChangeCounts?.[ BattleStat.SPDEF ] ?? 0,
|
||||
[ Stat.DEF ]: source.statChangeCounts?.[ Stat.DEF ] ?? 0,
|
||||
[ Stat.SPDEF ]: source.statChangeCounts?.[ Stat.SPDEF ] ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1761,9 +1759,9 @@ export class StockpilingTag extends BattlerTag {
|
||||
}));
|
||||
|
||||
// Attempt to increase DEF and SPDEF by one stage, keeping track of successful changes.
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(
|
||||
pokemon.scene, pokemon.getBattlerIndex(), true,
|
||||
[BattleStat.SPDEF, BattleStat.DEF], 1, true, false, true, this.onStatsChanged
|
||||
[Stat.SPDEF, Stat.DEF], 1, true, false, true, this.onStatStagesChanged
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -1777,15 +1775,15 @@ export class StockpilingTag extends BattlerTag {
|
||||
* one stage for each stack which had successfully changed that particular stat during onAdd.
|
||||
*/
|
||||
onRemove(pokemon: Pokemon): void {
|
||||
const defChange = this.statChangeCounts[BattleStat.DEF];
|
||||
const spDefChange = this.statChangeCounts[BattleStat.SPDEF];
|
||||
const defChange = this.statChangeCounts[Stat.DEF];
|
||||
const spDefChange = this.statChangeCounts[Stat.SPDEF];
|
||||
|
||||
if (defChange) {
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.DEF], -defChange, true, false, true));
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ Stat.DEF ], -defChange, true, false, true));
|
||||
}
|
||||
|
||||
if (spDefChange) {
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.SPDEF], -spDefChange, true, false, true));
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ Stat.SPDEF ], -spDefChange, true, false, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1927,11 +1925,11 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
||||
case BattlerTagType.SPIKY_SHIELD:
|
||||
return new ContactDamageProtectedTag(sourceMove, 8);
|
||||
case BattlerTagType.KINGS_SHIELD:
|
||||
return new ContactStatChangeProtectedTag(sourceMove, tagType, BattleStat.ATK, -1);
|
||||
return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.ATK, -1);
|
||||
case BattlerTagType.OBSTRUCT:
|
||||
return new ContactStatChangeProtectedTag(sourceMove, tagType, BattleStat.DEF, -2);
|
||||
return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.DEF, -2);
|
||||
case BattlerTagType.SILK_TRAP:
|
||||
return new ContactStatChangeProtectedTag(sourceMove, tagType, BattleStat.SPD, -1);
|
||||
return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.SPD, -1);
|
||||
case BattlerTagType.BANEFUL_BUNKER:
|
||||
return new ContactPoisonProtectedTag(sourceMove);
|
||||
case BattlerTagType.BURNING_BULWARK:
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { getPokemonNameWithAffix } from "../messages";
|
||||
import Pokemon, { HitResult } from "../field/pokemon";
|
||||
import { BattleStat } from "./battle-stat";
|
||||
import { getStatusEffectHealText } from "./status-effect";
|
||||
import * as Utils from "../utils";
|
||||
import { DoubleBerryEffectAbAttr, ReduceBerryUseThresholdAbAttr, applyAbAttrs } from "./ability";
|
||||
import i18next from "i18next";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase.js";
|
||||
import { StatChangePhase } from "#app/phases/stat-change-phase.js";
|
||||
import { Stat, type BattleStat } from "#app/enums/stat";
|
||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
|
||||
export function getBerryName(berryType: BerryType): string {
|
||||
return i18next.t(`berry:${BerryType[berryType]}.name`);
|
||||
@ -35,9 +35,10 @@ export function getBerryPredicate(berryType: BerryType): BerryPredicate {
|
||||
case BerryType.SALAC:
|
||||
return (pokemon: Pokemon) => {
|
||||
const threshold = new Utils.NumberHolder(0.25);
|
||||
const battleStat = (berryType - BerryType.LIECHI) as BattleStat;
|
||||
// Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth
|
||||
const stat: BattleStat = berryType - BerryType.ENIGMA;
|
||||
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
|
||||
return pokemon.getHpRatio() < threshold.value && pokemon.summonData.battleStats[battleStat] < 6;
|
||||
return pokemon.getHpRatio() < threshold.value && pokemon.getStatStage(stat) < 6;
|
||||
};
|
||||
case BerryType.LANSAT:
|
||||
return (pokemon: Pokemon) => {
|
||||
@ -95,10 +96,11 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
|
||||
if (pokemon.battleData) {
|
||||
pokemon.battleData.berriesEaten.push(berryType);
|
||||
}
|
||||
const battleStat = (berryType - BerryType.LIECHI) as BattleStat;
|
||||
const statLevels = new Utils.NumberHolder(1);
|
||||
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statLevels);
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ battleStat ], statLevels.value));
|
||||
// Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth
|
||||
const stat: BattleStat = berryType - BerryType.ENIGMA;
|
||||
const statStages = new Utils.NumberHolder(1);
|
||||
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statStages);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], statStages.value));
|
||||
};
|
||||
case BerryType.LANSAT:
|
||||
return (pokemon: Pokemon) => {
|
||||
@ -112,9 +114,10 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
|
||||
if (pokemon.battleData) {
|
||||
pokemon.battleData.berriesEaten.push(berryType);
|
||||
}
|
||||
const statLevels = new Utils.NumberHolder(2);
|
||||
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statLevels);
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ BattleStat.RAND ], statLevels.value));
|
||||
const randStat = Utils.randSeedInt(Stat.SPD, Stat.ATK);
|
||||
const stages = new Utils.NumberHolder(2);
|
||||
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, stages);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randStat ], stages.value));
|
||||
};
|
||||
case BerryType.LEPPA:
|
||||
return (pokemon: Pokemon) => {
|
||||
|
@ -13,7 +13,6 @@ import { TrainerType } from "#enums/trainer-type";
|
||||
import { Nature } from "./nature";
|
||||
import { Moves } from "#app/enums/moves.js";
|
||||
import { TypeColor, TypeShadow } from "#app/enums/color.js";
|
||||
import { Gender } from "./gender";
|
||||
import { pokemonEvolutions } from "./pokemon-evolutions";
|
||||
import { pokemonFormChanges } from "./pokemon-forms";
|
||||
|
||||
@ -659,7 +658,6 @@ export class FreshStartChallenge extends Challenge {
|
||||
pokemon.luck = 0; // No luck
|
||||
pokemon.shiny = false; // Not shiny
|
||||
pokemon.variant = 0; // Not shiny
|
||||
pokemon.gender = Gender.MALE; // Starters default to male
|
||||
pokemon.formIndex = 0; // Froakie should be base form
|
||||
pokemon.ivs = [10, 10, 10, 10, 10, 10]; // Default IVs of 10 for all stats
|
||||
return true;
|
||||
|
140
src/data/egg.ts
140
src/data/egg.ts
@ -139,46 +139,57 @@ export class Egg {
|
||||
////
|
||||
|
||||
constructor(eggOptions?: IEggOptions) {
|
||||
//if (eggOptions.tier && eggOptions.species) throw Error("Error egg can't have species and tier as option. only choose one of them.")
|
||||
const generateEggProperties = (eggOptions?: IEggOptions) => {
|
||||
//if (eggOptions.tier && eggOptions.species) throw Error("Error egg can't have species and tier as option. only choose one of them.")
|
||||
|
||||
this._sourceType = eggOptions?.sourceType!; // TODO: is this bang correct?
|
||||
// Ensure _sourceType is defined before invoking rollEggTier(), as it is referenced
|
||||
this._tier = eggOptions?.tier ?? (Overrides.EGG_TIER_OVERRIDE ?? this.rollEggTier());
|
||||
// If egg was pulled, check if egg pity needs to override the egg tier
|
||||
if (eggOptions?.pulled) {
|
||||
// Needs this._tier and this._sourceType to work
|
||||
this.checkForPityTierOverrides(eggOptions.scene!); // TODO: is this bang correct?
|
||||
}
|
||||
this._sourceType = eggOptions?.sourceType!; // TODO: is this bang correct?
|
||||
// Ensure _sourceType is defined before invoking rollEggTier(), as it is referenced
|
||||
this._tier = eggOptions?.tier ?? (Overrides.EGG_TIER_OVERRIDE ?? this.rollEggTier());
|
||||
// If egg was pulled, check if egg pity needs to override the egg tier
|
||||
if (eggOptions?.pulled) {
|
||||
// Needs this._tier and this._sourceType to work
|
||||
this.checkForPityTierOverrides(eggOptions.scene!); // TODO: is this bang correct?
|
||||
}
|
||||
|
||||
this._id = eggOptions?.id ?? Utils.randInt(EGG_SEED, EGG_SEED * this._tier);
|
||||
this._id = eggOptions?.id ?? Utils.randInt(EGG_SEED, EGG_SEED * this._tier);
|
||||
|
||||
this._sourceType = eggOptions?.sourceType ?? undefined;
|
||||
this._hatchWaves = eggOptions?.hatchWaves ?? this.getEggTierDefaultHatchWaves();
|
||||
this._timestamp = eggOptions?.timestamp ?? new Date().getTime();
|
||||
this._sourceType = eggOptions?.sourceType ?? undefined;
|
||||
this._hatchWaves = eggOptions?.hatchWaves ?? this.getEggTierDefaultHatchWaves();
|
||||
this._timestamp = eggOptions?.timestamp ?? new Date().getTime();
|
||||
|
||||
// First roll shiny and variant so we can filter if species with an variant exist
|
||||
this._isShiny = eggOptions?.isShiny ?? (Overrides.EGG_SHINY_OVERRIDE || this.rollShiny());
|
||||
this._variantTier = eggOptions?.variantTier ?? (Overrides.EGG_VARIANT_OVERRIDE ?? this.rollVariant());
|
||||
this._species = eggOptions?.species ?? this.rollSpecies(eggOptions!.scene!)!; // TODO: Are those bangs correct?
|
||||
// First roll shiny and variant so we can filter if species with an variant exist
|
||||
this._isShiny = eggOptions?.isShiny ?? (Overrides.EGG_SHINY_OVERRIDE || this.rollShiny());
|
||||
this._variantTier = eggOptions?.variantTier ?? (Overrides.EGG_VARIANT_OVERRIDE ?? this.rollVariant());
|
||||
this._species = eggOptions?.species ?? this.rollSpecies(eggOptions!.scene!)!; // TODO: Are those bangs correct?
|
||||
|
||||
this._overrideHiddenAbility = eggOptions?.overrideHiddenAbility ?? false;
|
||||
this._overrideHiddenAbility = eggOptions?.overrideHiddenAbility ?? false;
|
||||
|
||||
// Override egg tier and hatchwaves if species was given
|
||||
if (eggOptions?.species) {
|
||||
this._tier = this.getEggTierFromSpeciesStarterValue();
|
||||
this._hatchWaves = eggOptions.hatchWaves ?? this.getEggTierDefaultHatchWaves();
|
||||
}
|
||||
// If species has no variant, set variantTier to common. This needs to
|
||||
// be done because species with no variants get filtered at rollSpecies but if the
|
||||
// species is set via options or the legendary gacha pokemon gets choosen the check never happens
|
||||
if (this._species && !getPokemonSpecies(this._species).hasVariants()) {
|
||||
this._variantTier = VariantTier.COMMON;
|
||||
}
|
||||
// Needs this._tier so it needs to be generated afer the tier override if bought from same species
|
||||
this._eggMoveIndex = eggOptions?.eggMoveIndex ?? this.rollEggMoveIndex();
|
||||
if (eggOptions?.pulled) {
|
||||
this.increasePullStatistic(eggOptions.scene!); // TODO: is this bang correct?
|
||||
this.addEggToGameData(eggOptions.scene!); // TODO: is this bang correct?
|
||||
// Override egg tier and hatchwaves if species was given
|
||||
if (eggOptions?.species) {
|
||||
this._tier = this.getEggTierFromSpeciesStarterValue();
|
||||
this._hatchWaves = eggOptions.hatchWaves ?? this.getEggTierDefaultHatchWaves();
|
||||
}
|
||||
// If species has no variant, set variantTier to common. This needs to
|
||||
// be done because species with no variants get filtered at rollSpecies but if the
|
||||
// species is set via options or the legendary gacha pokemon gets choosen the check never happens
|
||||
if (this._species && !getPokemonSpecies(this._species).hasVariants()) {
|
||||
this._variantTier = VariantTier.COMMON;
|
||||
}
|
||||
// Needs this._tier so it needs to be generated afer the tier override if bought from same species
|
||||
this._eggMoveIndex = eggOptions?.eggMoveIndex ?? this.rollEggMoveIndex();
|
||||
if (eggOptions?.pulled) {
|
||||
this.increasePullStatistic(eggOptions.scene!); // TODO: is this bang correct?
|
||||
this.addEggToGameData(eggOptions.scene!); // TODO: is this bang correct?
|
||||
}
|
||||
};
|
||||
|
||||
if (eggOptions?.scene) {
|
||||
const seedOverride = Utils.randomString(24);
|
||||
eggOptions?.scene.executeWithSeedOffset(() => {
|
||||
generateEggProperties(eggOptions);
|
||||
}, 0, seedOverride);
|
||||
} else { // For legacy eggs without scene
|
||||
generateEggProperties(eggOptions);
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,37 +211,46 @@ export class Egg {
|
||||
|
||||
// Generates a PlayerPokemon from an egg
|
||||
public generatePlayerPokemon(scene: BattleScene): PlayerPokemon {
|
||||
// Legacy egg wants to hatch. Generate missing properties
|
||||
if (!this._species) {
|
||||
this._isShiny = this.rollShiny();
|
||||
this._species = this.rollSpecies(scene!)!; // TODO: are these bangs correct?
|
||||
}
|
||||
let ret: PlayerPokemon;
|
||||
|
||||
let pokemonSpecies = getPokemonSpecies(this._species);
|
||||
// Special condition to have Phione eggs also have a chance of generating Manaphy
|
||||
if (this._species === Species.PHIONE) {
|
||||
pokemonSpecies = getPokemonSpecies(Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) ? Species.PHIONE : Species.MANAPHY);
|
||||
}
|
||||
const generatePlayerPokemonHelper = (scene: BattleScene) => {
|
||||
// Legacy egg wants to hatch. Generate missing properties
|
||||
if (!this._species) {
|
||||
this._isShiny = this.rollShiny();
|
||||
this._species = this.rollSpecies(scene!)!; // TODO: are these bangs correct?
|
||||
}
|
||||
|
||||
// Sets the hidden ability if a hidden ability exists and
|
||||
// the override is set or the egg hits the chance
|
||||
let abilityIndex: number | undefined = undefined;
|
||||
const sameSpeciesEggHACheck = (this._sourceType === EggSourceType.SAME_SPECIES_EGG && !Utils.randSeedInt(SAME_SPECIES_EGG_HA_RATE));
|
||||
const gachaEggHACheck = (!(this._sourceType === EggSourceType.SAME_SPECIES_EGG) && !Utils.randSeedInt(GACHA_EGG_HA_RATE));
|
||||
if (pokemonSpecies.abilityHidden && (this._overrideHiddenAbility || sameSpeciesEggHACheck || gachaEggHACheck)) {
|
||||
abilityIndex = 2;
|
||||
}
|
||||
let pokemonSpecies = getPokemonSpecies(this._species);
|
||||
// Special condition to have Phione eggs also have a chance of generating Manaphy
|
||||
if (this._species === Species.PHIONE) {
|
||||
pokemonSpecies = getPokemonSpecies(Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) ? Species.PHIONE : Species.MANAPHY);
|
||||
}
|
||||
|
||||
// This function has way to many optional parameters
|
||||
const ret: PlayerPokemon = scene.addPlayerPokemon(pokemonSpecies, 1, abilityIndex, undefined, undefined, false);
|
||||
ret.shiny = this._isShiny;
|
||||
ret.variant = this._variantTier;
|
||||
// Sets the hidden ability if a hidden ability exists and
|
||||
// the override is set or the egg hits the chance
|
||||
let abilityIndex: number | undefined = undefined;
|
||||
const sameSpeciesEggHACheck = (this._sourceType === EggSourceType.SAME_SPECIES_EGG && !Utils.randSeedInt(SAME_SPECIES_EGG_HA_RATE));
|
||||
const gachaEggHACheck = (!(this._sourceType === EggSourceType.SAME_SPECIES_EGG) && !Utils.randSeedInt(GACHA_EGG_HA_RATE));
|
||||
if (pokemonSpecies.abilityHidden && (this._overrideHiddenAbility || sameSpeciesEggHACheck || gachaEggHACheck)) {
|
||||
abilityIndex = 2;
|
||||
}
|
||||
|
||||
const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967295));
|
||||
// This function has way to many optional parameters
|
||||
ret = scene.addPlayerPokemon(pokemonSpecies, 1, abilityIndex, undefined, undefined, false);
|
||||
ret.shiny = this._isShiny;
|
||||
ret.variant = this._variantTier;
|
||||
|
||||
for (let s = 0; s < ret.ivs.length; s++) {
|
||||
ret.ivs[s] = Math.max(ret.ivs[s], secondaryIvs[s]);
|
||||
}
|
||||
const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967295));
|
||||
|
||||
for (let s = 0; s < ret.ivs.length; s++) {
|
||||
ret.ivs[s] = Math.max(ret.ivs[s], secondaryIvs[s]);
|
||||
}
|
||||
};
|
||||
|
||||
ret = ret!; // Tell TS compiler it's defined now
|
||||
scene.executeWithSeedOffset(() => {
|
||||
generatePlayerPokemonHelper(scene);
|
||||
}, this._id, EGG_SEED.toString());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
748
src/data/move.ts
748
src/data/move.ts
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,9 @@
|
||||
import { Stat, getStatName } from "./pokemon-stat";
|
||||
import * as Utils from "../utils";
|
||||
import { TextStyle, getBBCodeFrag } from "../ui/text";
|
||||
import { Nature } from "#enums/nature";
|
||||
import { UiTheme } from "#enums/ui-theme";
|
||||
import i18next from "i18next";
|
||||
import { Stat, EFFECTIVE_STATS, getShortenedStatKey } from "#app/enums/stat";
|
||||
|
||||
export { Nature };
|
||||
|
||||
@ -14,10 +14,9 @@ export function getNatureName(nature: Nature, includeStatEffects: boolean = fals
|
||||
ret = i18next.t("nature:" + ret as any);
|
||||
}
|
||||
if (includeStatEffects) {
|
||||
const stats = Utils.getEnumValues(Stat).slice(1);
|
||||
let increasedStat: Stat | null = null;
|
||||
let decreasedStat: Stat | null = null;
|
||||
for (const stat of stats) {
|
||||
for (const stat of EFFECTIVE_STATS) {
|
||||
const multiplier = getNatureStatMultiplier(nature, stat);
|
||||
if (multiplier > 1) {
|
||||
increasedStat = stat;
|
||||
@ -28,7 +27,7 @@ export function getNatureName(nature: Nature, includeStatEffects: boolean = fals
|
||||
const textStyle = forStarterSelect ? TextStyle.SUMMARY_ALT : TextStyle.WINDOW;
|
||||
const getTextFrag = !ignoreBBCode ? (text: string, style: TextStyle) => getBBCodeFrag(text, style, uiTheme) : (text: string, style: TextStyle) => text;
|
||||
if (increasedStat && decreasedStat) {
|
||||
ret = `${getTextFrag(`${ret}${!forStarterSelect ? "\n" : " "}(`, textStyle)}${getTextFrag(`+${getStatName(increasedStat, true)}`, TextStyle.SUMMARY_PINK)}${getTextFrag("/", textStyle)}${getTextFrag(`-${getStatName(decreasedStat, true)}`, TextStyle.SUMMARY_BLUE)}${getTextFrag(")", textStyle)}`;
|
||||
ret = `${getTextFrag(`${ret}${!forStarterSelect ? "\n" : " "}(`, textStyle)}${getTextFrag(`+${i18next.t(getShortenedStatKey(increasedStat))}`, TextStyle.SUMMARY_PINK)}${getTextFrag("/", textStyle)}${getTextFrag(`-${i18next.t(getShortenedStatKey(decreasedStat))}`, TextStyle.SUMMARY_BLUE)}${getTextFrag(")", textStyle)}`;
|
||||
} else {
|
||||
ret = getTextFrag(`${ret}${!forStarterSelect ? "\n" : " "}(-)`, textStyle);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Gender } from "./gender";
|
||||
import { PokeballType } from "./pokeball";
|
||||
import Pokemon from "../field/pokemon";
|
||||
import { Stat } from "./pokemon-stat";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { Type } from "./type";
|
||||
import * as Utils from "../utils";
|
||||
import { SpeciesFormKey } from "./pokemon-species";
|
||||
|
@ -14,7 +14,7 @@ import { GrowthRate } from "./exp";
|
||||
import { EvolutionLevel, SpeciesWildEvolutionDelay, pokemonEvolutions, pokemonPrevolutions } from "./pokemon-evolutions";
|
||||
import { Type } from "./type";
|
||||
import { LevelMoves, pokemonFormLevelMoves, pokemonFormLevelMoves as pokemonSpeciesFormLevelMoves, pokemonSpeciesLevelMoves } from "./pokemon-level-moves";
|
||||
import { Stat } from "./pokemon-stat";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { Variant, VariantSet, variantColorCache, variantData } from "./variant";
|
||||
|
||||
export enum Region {
|
||||
|
@ -1,29 +0,0 @@
|
||||
import { Stat } from "#enums/stat";
|
||||
import i18next from "i18next";
|
||||
|
||||
export { Stat };
|
||||
|
||||
export function getStatName(stat: Stat, shorten: boolean = false) {
|
||||
let ret: string = "";
|
||||
switch (stat) {
|
||||
case Stat.HP:
|
||||
ret = !shorten ? i18next.t("pokemonInfo:Stat.HP") : i18next.t("pokemonInfo:Stat.HPshortened");
|
||||
break;
|
||||
case Stat.ATK:
|
||||
ret = !shorten ? i18next.t("pokemonInfo:Stat.ATK") : i18next.t("pokemonInfo:Stat.ATKshortened");
|
||||
break;
|
||||
case Stat.DEF:
|
||||
ret = !shorten ? i18next.t("pokemonInfo:Stat.DEF") : i18next.t("pokemonInfo:Stat.DEFshortened");
|
||||
break;
|
||||
case Stat.SPATK:
|
||||
ret = !shorten ? i18next.t("pokemonInfo:Stat.SPATK") : i18next.t("pokemonInfo:Stat.SPATKshortened");
|
||||
break;
|
||||
case Stat.SPDEF:
|
||||
ret = !shorten ? i18next.t("pokemonInfo:Stat.SPDEF") : i18next.t("pokemonInfo:Stat.SPDEFshortened");
|
||||
break;
|
||||
case Stat.SPD:
|
||||
ret = !shorten ? i18next.t("pokemonInfo:Stat.SPD") : i18next.t("pokemonInfo:Stat.SPDshortened");
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
import { BattleStat, getBattleStatName } from "./battle-stat";
|
||||
import i18next from "i18next";
|
||||
|
||||
export enum TempBattleStat {
|
||||
ATK,
|
||||
DEF,
|
||||
SPATK,
|
||||
SPDEF,
|
||||
SPD,
|
||||
ACC,
|
||||
CRIT
|
||||
}
|
||||
|
||||
export function getTempBattleStatName(tempBattleStat: TempBattleStat) {
|
||||
if (tempBattleStat === TempBattleStat.CRIT) {
|
||||
return i18next.t("modifierType:TempBattleStatBoosterStatName.CRIT");
|
||||
}
|
||||
return getBattleStatName(tempBattleStat as integer as BattleStat);
|
||||
}
|
||||
|
||||
export function getTempBattleStatBoosterItemName(tempBattleStat: TempBattleStat) {
|
||||
switch (tempBattleStat) {
|
||||
case TempBattleStat.ATK:
|
||||
return "X Attack";
|
||||
case TempBattleStat.DEF:
|
||||
return "X Defense";
|
||||
case TempBattleStat.SPATK:
|
||||
return "X Sp. Atk";
|
||||
case TempBattleStat.SPDEF:
|
||||
return "X Sp. Def";
|
||||
case TempBattleStat.SPD:
|
||||
return "X Speed";
|
||||
case TempBattleStat.ACC:
|
||||
return "X Accuracy";
|
||||
case TempBattleStat.CRIT:
|
||||
return "Dire Hit";
|
||||
}
|
||||
}
|
@ -1,8 +1,75 @@
|
||||
/** Enum that comprises all possible stat-related attributes, in-battle and permanent, of a Pokemon. */
|
||||
export enum Stat {
|
||||
/** Hit Points */
|
||||
HP = 0,
|
||||
/** Attack */
|
||||
ATK,
|
||||
/** Defense */
|
||||
DEF,
|
||||
/** Special Attack */
|
||||
SPATK,
|
||||
/** Special Defense */
|
||||
SPDEF,
|
||||
/** Speed */
|
||||
SPD,
|
||||
/** Accuracy */
|
||||
ACC,
|
||||
/** Evasiveness */
|
||||
EVA
|
||||
}
|
||||
|
||||
/** A constant array comprised of the {@linkcode Stat} values that make up {@linkcode PermanentStat}. */
|
||||
export const PERMANENT_STATS = [ Stat.HP, Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ] as const;
|
||||
/** Type used to describe the core, permanent stats of a Pokemon. */
|
||||
export type PermanentStat = typeof PERMANENT_STATS[number];
|
||||
|
||||
/** A constant array comprised of the {@linkcode Stat} values that make up {@linkcode EFfectiveStat}. */
|
||||
export const EFFECTIVE_STATS = [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ] as const;
|
||||
/** Type used to describe the intersection of core stats and stats that have stages in battle. */
|
||||
export type EffectiveStat = typeof EFFECTIVE_STATS[number];
|
||||
|
||||
/** A constant array comprised of {@linkcode Stat} the values that make up {@linkcode BattleStat}. */
|
||||
export const BATTLE_STATS = [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD, Stat.ACC, Stat.EVA ] as const;
|
||||
/** Type used to describe the stats that have stages which can be incremented and decremented in battle. */
|
||||
export type BattleStat = typeof BATTLE_STATS[number];
|
||||
|
||||
/** A constant array comprised of {@linkcode Stat} the values that make up {@linkcode TempBattleStat}. */
|
||||
export const TEMP_BATTLE_STATS = [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD, Stat.ACC ] as const;
|
||||
/** Type used to describe the stats that have X item (`TEMP_STAT_STAGE_BOOSTER`) equivalents. */
|
||||
export type TempBattleStat = typeof TEMP_BATTLE_STATS[number];
|
||||
|
||||
/**
|
||||
* Provides the translation key corresponding to the amount of stat stages and whether those stat stages
|
||||
* are positive or negative.
|
||||
* @param stages the amount of stages
|
||||
* @param isIncrease dictates a negative (`false`) or a positive (`true`) stat stage change
|
||||
* @returns the translation key fitting the conditions described by {@linkcode stages} and {@linkcode isIncrease}
|
||||
*/
|
||||
export function getStatStageChangeDescriptionKey(stages: number, isIncrease: boolean) {
|
||||
if (stages === 1) {
|
||||
return isIncrease ? "battle:statRose" : "battle:statFell";
|
||||
} else if (stages === 2) {
|
||||
return isIncrease ? "battle:statSharplyRose" : "battle:statHarshlyFell";
|
||||
} else if (stages <= 6) {
|
||||
return isIncrease ? "battle:statRoseDrastically" : "battle:statSeverelyFell";
|
||||
}
|
||||
return isIncrease ? "battle:statWontGoAnyHigher" : "battle:statWontGoAnyLower";
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the translation key corresponding to a given stat which can be translated into its full name.
|
||||
* @param stat the {@linkcode Stat} to be translated
|
||||
* @returns the translation key corresponding to the given {@linkcode Stat}
|
||||
*/
|
||||
export function getStatKey(stat: Stat) {
|
||||
return `pokemonInfo:Stat.${Stat[stat]}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the translation key corresponding to a given stat which can be translated into its shortened name.
|
||||
* @param stat the {@linkcode Stat} to be translated
|
||||
* @returns the translation key corresponding to the given {@linkcode Stat}
|
||||
*/
|
||||
export function getShortenedStatKey(stat: PermanentStat) {
|
||||
return `pokemonInfo:Stat.${Stat[stat]}shortened`;
|
||||
}
|
||||
|
@ -3,26 +3,24 @@ import BattleScene, { AnySound } from "../battle-scene";
|
||||
import { Variant, VariantSet, variantColorCache } from "#app/data/variant";
|
||||
import { variantData } from "#app/data/variant";
|
||||
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "../ui/battle-info";
|
||||
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr } from "../data/move";
|
||||
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr } from "../data/move";
|
||||
import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from "../data/pokemon-species";
|
||||
import { Constructor } from "#app/utils";
|
||||
import * as Utils from "../utils";
|
||||
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from "../data/type";
|
||||
import { getLevelTotalExp } from "../data/exp";
|
||||
import { Stat } from "../data/pokemon-stat";
|
||||
import { DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, StatBoosterModifier, CritBoosterModifier, TerastallizeModifier } from "../modifier/modifier";
|
||||
import { Stat, type PermanentStat, type BattleStat, type EffectiveStat, PERMANENT_STATS, BATTLE_STATS, EFFECTIVE_STATS } from "#enums/stat";
|
||||
import { DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, BaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempStatStageBoosterModifier, TempCritBoosterModifier, StatBoosterModifier, CritBoosterModifier, TerastallizeModifier } from "../modifier/modifier";
|
||||
import { PokeballType } from "../data/pokeball";
|
||||
import { Gender } from "../data/gender";
|
||||
import { initMoveAnim, loadMoveAnimAssets } from "../data/battle-anims";
|
||||
import { Status, StatusEffect, getRandomStatus } from "../data/status-effect";
|
||||
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "../data/pokemon-evolutions";
|
||||
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "../data/tms";
|
||||
import { BattleStat } from "../data/battle-stat";
|
||||
import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, ExposedTag, DragonCheerTag, CritBoostTag, TrappedTag } from "../data/battler-tags";
|
||||
import { WeatherType } from "../data/weather";
|
||||
import { TempBattleStat } from "../data/temp-battle-stat";
|
||||
import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "../data/arena-tag";
|
||||
import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldBattleStatMultiplierAbAttrs, FieldMultiplyBattleStatAbAttr, AddSecondStrikeAbAttr, IgnoreOpponentEvasionAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr } from "../data/ability";
|
||||
import { Ability, AbAttr, StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr } from "../data/ability";
|
||||
import PokemonData from "../system/pokemon-data";
|
||||
import { BattlerIndex } from "../battle";
|
||||
import { Mode } from "../ui/ui";
|
||||
@ -40,7 +38,7 @@ import Overrides from "#app/overrides";
|
||||
import i18next from "i18next";
|
||||
import { speciesEggMoves } from "../data/egg-moves";
|
||||
import { ModifierTier } from "../modifier/modifier-tier";
|
||||
import { applyChallenges, ChallengeType } from "#app/data/challenge.js";
|
||||
import { applyChallenges, ChallengeType } from "#app/data/challenge";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||
import { BattleSpec } from "#enums/battle-spec";
|
||||
@ -49,17 +47,17 @@ import { BerryType } from "#enums/berry-type";
|
||||
import { Biome } from "#enums/biome";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { DamagePhase } from "#app/phases/damage-phase";
|
||||
import { FaintPhase } from "#app/phases/faint-phase";
|
||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
||||
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
||||
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
||||
import { ObtainStatusEffectPhase } from "#app/phases/obtain-status-effect-phase";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
|
||||
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
import { getPokemonNameWithAffix } from "#app/messages.js";
|
||||
import { DamagePhase } from "#app/phases/damage-phase.js";
|
||||
import { FaintPhase } from "#app/phases/faint-phase.js";
|
||||
import { LearnMovePhase } from "#app/phases/learn-move-phase.js";
|
||||
import { MoveEffectPhase } from "#app/phases/move-effect-phase.js";
|
||||
import { MoveEndPhase } from "#app/phases/move-end-phase.js";
|
||||
import { ObtainStatusEffectPhase } from "#app/phases/obtain-status-effect-phase.js";
|
||||
import { StatChangePhase } from "#app/phases/stat-change-phase.js";
|
||||
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase.js";
|
||||
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase.js";
|
||||
|
||||
export enum FieldPosition {
|
||||
CENTER,
|
||||
@ -119,6 +117,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
public maskEnabled: boolean;
|
||||
public maskSprite: Phaser.GameObjects.Sprite | null;
|
||||
|
||||
public usedTMs: Moves[];
|
||||
|
||||
private shinySparkle: Phaser.GameObjects.Sprite;
|
||||
|
||||
constructor(scene: BattleScene, x: number, y: number, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData) {
|
||||
@ -195,6 +195,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.fusionVariant = dataSource.fusionVariant || 0;
|
||||
this.fusionGender = dataSource.fusionGender;
|
||||
this.fusionLuck = dataSource.fusionLuck;
|
||||
this.usedTMs = dataSource.usedTMs ?? [];
|
||||
} else {
|
||||
this.id = Utils.randSeedInt(4294967296);
|
||||
this.ivs = ivs || Utils.getIvsFromId(this.id);
|
||||
@ -673,49 +674,139 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
});
|
||||
}
|
||||
|
||||
getStat(stat: Stat): integer {
|
||||
/**
|
||||
* Retrieves the entire set of stats of the {@linkcode Pokemon}.
|
||||
* @param bypassSummonData prefer actual stats (`true` by default) or in-battle overriden stats (`false`)
|
||||
* @returns the numeric values of the {@linkcode Pokemon}'s stats
|
||||
*/
|
||||
getStats(bypassSummonData: boolean = true): number[] {
|
||||
if (!bypassSummonData && this.summonData?.stats) {
|
||||
return this.summonData.stats;
|
||||
}
|
||||
return this.stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the corresponding {@linkcode PermanentStat} of the {@linkcode Pokemon}.
|
||||
* @param stat the desired {@linkcode PermanentStat}
|
||||
* @param bypassSummonData prefer actual stats (`true` by default) or in-battle overridden stats (`false`)
|
||||
* @returns the numeric value of the desired {@linkcode Stat}
|
||||
*/
|
||||
getStat(stat: PermanentStat, bypassSummonData: boolean = true): number {
|
||||
if (!bypassSummonData && this.summonData && (this.summonData.stats[stat] !== 0)) {
|
||||
return this.summonData.stats[stat];
|
||||
}
|
||||
return this.stats[stat];
|
||||
}
|
||||
|
||||
getBattleStat(stat: Stat, opponent?: Pokemon, move?: Move, isCritical: boolean = false): integer {
|
||||
if (stat === Stat.HP) {
|
||||
return this.getStat(Stat.HP);
|
||||
}
|
||||
const battleStat = (stat - 1) as BattleStat;
|
||||
const statLevel = new Utils.IntegerHolder(this.summonData.battleStats[battleStat]);
|
||||
if (opponent) {
|
||||
if (isCritical) {
|
||||
switch (stat) {
|
||||
case Stat.ATK:
|
||||
case Stat.SPATK:
|
||||
statLevel.value = Math.max(statLevel.value, 0);
|
||||
break;
|
||||
case Stat.DEF:
|
||||
case Stat.SPDEF:
|
||||
statLevel.value = Math.min(statLevel.value, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, opponent, null, false, statLevel);
|
||||
if (move) {
|
||||
applyMoveAttrs(IgnoreOpponentStatChangesAttr, this, opponent, move, statLevel);
|
||||
/**
|
||||
* Writes the value to the corrseponding {@linkcode PermanentStat} of the {@linkcode Pokemon}.
|
||||
*
|
||||
* Note that this does nothing if {@linkcode value} is less than 0.
|
||||
* @param stat the desired {@linkcode PermanentStat} to be overwritten
|
||||
* @param value the desired numeric value
|
||||
* @param bypassSummonData write to actual stats (`true` by default) or in-battle overridden stats (`false`)
|
||||
*/
|
||||
setStat(stat: PermanentStat, value: number, bypassSummonData: boolean = true): void {
|
||||
if (value >= 0) {
|
||||
if (!bypassSummonData && this.summonData) {
|
||||
this.summonData.stats[stat] = value;
|
||||
} else {
|
||||
this.stats[stat] = value;
|
||||
}
|
||||
}
|
||||
if (this.isPlayer()) {
|
||||
this.scene.applyModifiers(TempBattleStatBoosterModifier, this.isPlayer(), battleStat as integer as TempBattleStat, statLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the entire set of in-battle stat stages of the {@linkcode Pokemon}.
|
||||
* @returns the numeric values of the {@linkcode Pokemon}'s in-battle stat stages if available, a fresh stat stage array otherwise
|
||||
*/
|
||||
getStatStages(): number[] {
|
||||
return this.summonData ? this.summonData.statStages : [ 0, 0, 0, 0, 0, 0, 0 ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the in-battle stage of the specified {@linkcode BattleStat}.
|
||||
* @param stat the {@linkcode BattleStat} whose stage is desired
|
||||
* @returns the stage of the desired {@linkcode BattleStat} if available, 0 otherwise
|
||||
*/
|
||||
getStatStage(stat: BattleStat): number {
|
||||
return this.summonData ? this.summonData.statStages[stat - 1] : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the value to the in-battle stage of the corresponding {@linkcode BattleStat} of the {@linkcode Pokemon}.
|
||||
*
|
||||
* Note that, if the value is not within a range of [-6, 6], it will be forced to the closest range bound.
|
||||
* @param stat the {@linkcode BattleStat} whose stage is to be overwritten
|
||||
* @param value the desired numeric value
|
||||
*/
|
||||
setStatStage(stat: BattleStat, value: number): void {
|
||||
if (this.summonData) {
|
||||
if (value >= -6) {
|
||||
this.summonData.statStages[stat - 1] = Math.min(value, 6);
|
||||
} else {
|
||||
this.summonData.statStages[stat - 1] = Math.max(value, -6);
|
||||
}
|
||||
}
|
||||
const statValue = new Utils.NumberHolder(this.getStat(stat));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the critical-hit stage considering the move used and the Pokemon
|
||||
* who used it.
|
||||
* @param source the {@linkcode Pokemon} who using the move
|
||||
* @param move the {@linkcode Move} being used
|
||||
* @returns the final critical-hit stage value
|
||||
*/
|
||||
getCritStage(source: Pokemon, move: Move): number {
|
||||
const critStage = new Utils.IntegerHolder(0);
|
||||
applyMoveAttrs(HighCritAttr, source, this, move, critStage);
|
||||
this.scene.applyModifiers(CritBoosterModifier, source.isPlayer(), source, critStage);
|
||||
this.scene.applyModifiers(TempCritBoosterModifier, source.isPlayer(), critStage);
|
||||
const bonusCrit = new Utils.BooleanHolder(false);
|
||||
//@ts-ignore
|
||||
if (applyAbAttrs(BonusCritAbAttr, source, null, false, bonusCrit)) { // TODO: resolve ts-ignore. This is a promise. Checking a promise is bogus.
|
||||
if (bonusCrit.value) {
|
||||
critStage.value += 1;
|
||||
}
|
||||
}
|
||||
const critBoostTag = source.getTag(CritBoostTag);
|
||||
if (critBoostTag) {
|
||||
if (critBoostTag instanceof DragonCheerTag) {
|
||||
critStage.value += critBoostTag.typesOnAdd.includes(Type.DRAGON) ? 2 : 1;
|
||||
} else {
|
||||
critStage.value += 2;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`crit stage: +${critStage.value}`);
|
||||
return critStage.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates and retrieves the final value of a stat considering any held
|
||||
* items, move effects, opponent abilities, and whether there was a critical
|
||||
* hit.
|
||||
* @param stat the desired {@linkcode EffectiveStat}
|
||||
* @param opponent the target {@linkcode Pokemon}
|
||||
* @param move the {@linkcode Move} being used
|
||||
* @param isCritical determines whether a critical hit has occurred or not (`false` by default)
|
||||
* @returns the final in-battle value of a stat
|
||||
*/
|
||||
getEffectiveStat(stat: EffectiveStat, opponent?: Pokemon, move?: Move, isCritical: boolean = false): integer {
|
||||
const statValue = new Utils.NumberHolder(this.getStat(stat, false));
|
||||
this.scene.applyModifiers(StatBoosterModifier, this.isPlayer(), this, stat, statValue);
|
||||
|
||||
const fieldApplied = new Utils.BooleanHolder(false);
|
||||
for (const pokemon of this.scene.getField(true)) {
|
||||
applyFieldBattleStatMultiplierAbAttrs(FieldMultiplyBattleStatAbAttr, pokemon, stat, statValue, this, fieldApplied);
|
||||
applyFieldStatMultiplierAbAttrs(FieldMultiplyStatAbAttr, pokemon, stat, statValue, this, fieldApplied);
|
||||
if (fieldApplied.value) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, this, battleStat, statValue);
|
||||
let ret = statValue.value * (Math.max(2, 2 + statLevel.value) / Math.max(2, 2 - statLevel.value));
|
||||
applyStatMultiplierAbAttrs(StatMultiplierAbAttr, this, stat, statValue);
|
||||
let ret = statValue.value * this.getStatStageMultiplier(stat, opponent, move, isCritical);
|
||||
|
||||
switch (stat) {
|
||||
case Stat.ATK:
|
||||
if (this.getTag(BattlerTagType.SLOW_START)) {
|
||||
@ -762,24 +853,25 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
if (!this.stats) {
|
||||
this.stats = [ 0, 0, 0, 0, 0, 0 ];
|
||||
}
|
||||
const baseStats = this.getSpeciesForm().baseStats.slice(0);
|
||||
if (this.fusionSpecies) {
|
||||
const fusionBaseStats = this.getFusionSpeciesForm().baseStats;
|
||||
for (let s = 0; s < this.stats.length; s++) {
|
||||
|
||||
// Get and manipulate base stats
|
||||
const baseStats = this.getSpeciesForm(true).baseStats.slice();
|
||||
if (this.isFusion()) {
|
||||
const fusionBaseStats = this.getFusionSpeciesForm(true).baseStats;
|
||||
for (const s of PERMANENT_STATS) {
|
||||
baseStats[s] = Math.ceil((baseStats[s] + fusionBaseStats[s]) / 2);
|
||||
}
|
||||
} else if (this.scene.gameMode.isSplicedOnly) {
|
||||
for (let s = 0; s < this.stats.length; s++) {
|
||||
for (const s of PERMANENT_STATS) {
|
||||
baseStats[s] = Math.ceil(baseStats[s] / 2);
|
||||
}
|
||||
}
|
||||
this.scene.applyModifiers(PokemonBaseStatModifier, this.isPlayer(), this, baseStats);
|
||||
const stats = Utils.getEnumValues(Stat);
|
||||
for (const s of stats) {
|
||||
const isHp = s === Stat.HP;
|
||||
const baseStat = baseStats[s];
|
||||
let value = Math.floor(((2 * baseStat + this.ivs[s]) * this.level) * 0.01);
|
||||
if (isHp) {
|
||||
this.scene.applyModifiers(BaseStatModifier, this.isPlayer(), this, baseStats);
|
||||
|
||||
// Using base stats, calculate and store stats one by one
|
||||
for (const s of PERMANENT_STATS) {
|
||||
let value = Math.floor(((2 * baseStats[s] + this.ivs[s]) * this.level) * 0.01);
|
||||
if (s === Stat.HP) {
|
||||
value = value + this.level + 10;
|
||||
if (this.hasAbility(Abilities.WONDER_GUARD, false, true)) {
|
||||
value = 1;
|
||||
@ -800,7 +892,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
value = Math.max(Math[natureStatMultiplier.value > 1 ? "ceil" : "floor"](value * natureStatMultiplier.value), 1);
|
||||
}
|
||||
}
|
||||
this.stats[s] = value;
|
||||
|
||||
this.setStat(s, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -935,7 +1028,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
if (this.metBiome === -1 && !this.scene.gameMode.isFreshStartChallenge() && !this.scene.gameMode.isDaily) {
|
||||
levelMoves = this.getUnlockedEggMoves().concat(levelMoves);
|
||||
}
|
||||
return levelMoves.filter(lm => !this.moveset.some(m => m?.moveId === lm));
|
||||
if (Array.isArray(this.usedTMs) && this.usedTMs.length > 0) {
|
||||
levelMoves = this.usedTMs.filter(m => !levelMoves.includes(m)).concat(levelMoves);
|
||||
}
|
||||
levelMoves = levelMoves.filter(lm => !this.moveset.some(m => m?.moveId === lm));
|
||||
return levelMoves;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1371,7 +1468,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
const types = this.getTypes(true);
|
||||
const enemyTypes = opponent.getTypes(true, true);
|
||||
/** Is this Pokemon faster than the opponent? */
|
||||
const outspeed = (this.isActive(true) ? this.getBattleStat(Stat.SPD, opponent) : this.getStat(Stat.SPD)) >= opponent.getBattleStat(Stat.SPD, this);
|
||||
const outspeed = (this.isActive(true) ? this.getEffectiveStat(Stat.SPD, opponent) : this.getStat(Stat.SPD, false)) >= opponent.getEffectiveStat(Stat.SPD, this);
|
||||
/**
|
||||
* Based on how effective this Pokemon's types are offensively against the opponent's types.
|
||||
* This score is increased by 25 percent if this Pokemon is faster than the opponent.
|
||||
@ -1750,7 +1847,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].hasAttr(SacrificialAttr) ? 0.5 : 1)]);
|
||||
movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].hasAttr(SacrificialAttrOnHit) ? 0.5 : 1)]);
|
||||
// Trainers get a weight bump to stat buffing moves
|
||||
movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].getAttrs(StatChangeAttr).some(a => a.levels > 1 && a.selfTarget) ? 1.25 : 1)]);
|
||||
movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].getAttrs(StatStageChangeAttr).some(a => a.stages > 1 && a.selfTarget) ? 1.25 : 1)]);
|
||||
// Trainers get a weight decrease to multiturn moves
|
||||
movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].hasAttr(ChargeAttr) || !!allMoves[m[0]].hasAttr(RechargeAttr) ? 0.7 : 1)]);
|
||||
}
|
||||
@ -1762,8 +1859,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].category === MoveCategory.STATUS ? 1 : Math.max(Math.min(allMoves[m[0]].power/maxPower, 1), 0.5))]);
|
||||
|
||||
// Weight damaging moves against the lower stat
|
||||
const worseCategory: MoveCategory = this.stats[Stat.ATK] > this.stats[Stat.SPATK] ? MoveCategory.SPECIAL : MoveCategory.PHYSICAL;
|
||||
const statRatio = worseCategory === MoveCategory.PHYSICAL ? this.stats[Stat.ATK]/this.stats[Stat.SPATK] : this.stats[Stat.SPATK]/this.stats[Stat.ATK];
|
||||
const atk = this.getStat(Stat.ATK);
|
||||
const spAtk = this.getStat(Stat.SPATK);
|
||||
const worseCategory: MoveCategory = atk > spAtk ? MoveCategory.SPECIAL : MoveCategory.PHYSICAL;
|
||||
const statRatio = worseCategory === MoveCategory.PHYSICAL ? atk / spAtk : spAtk / atk;
|
||||
movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].category === worseCategory ? statRatio : 1)]);
|
||||
|
||||
let weightMultiplier = 0.9; // The higher this is the more the game weights towards higher level moves. At 0 all moves are equal weight.
|
||||
@ -1949,6 +2048,48 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return this instanceof PlayerPokemon ? this.scene.getPlayerField() : this.scene.getEnemyField();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the stat stage multiplier of the user against an opponent.
|
||||
*
|
||||
* Note that this does not apply to evasion or accuracy
|
||||
* @see {@linkcode getAccuracyMultiplier}
|
||||
* @param stat the desired {@linkcode EffectiveStat}
|
||||
* @param opponent the target {@linkcode Pokemon}
|
||||
* @param move the {@linkcode Move} being used
|
||||
* @param isCritical determines whether a critical hit has occurred or not (`false` by default)
|
||||
* @return the stat stage multiplier to be used for effective stat calculation
|
||||
*/
|
||||
getStatStageMultiplier(stat: EffectiveStat, opponent?: Pokemon, move?: Move, isCritical: boolean = false): number {
|
||||
const statStage = new Utils.IntegerHolder(this.getStatStage(stat));
|
||||
const ignoreStatStage = new Utils.BooleanHolder(false);
|
||||
|
||||
if (opponent) {
|
||||
if (isCritical) {
|
||||
switch (stat) {
|
||||
case Stat.ATK:
|
||||
case Stat.SPATK:
|
||||
statStage.value = Math.max(statStage.value, 0);
|
||||
break;
|
||||
case Stat.DEF:
|
||||
case Stat.SPDEF:
|
||||
statStage.value = Math.min(statStage.value, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
applyAbAttrs(IgnoreOpponentStatStagesAbAttr, opponent, null, false, stat, ignoreStatStage);
|
||||
if (move) {
|
||||
applyMoveAttrs(IgnoreOpponentStatStagesAttr, this, opponent, move, ignoreStatStage);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignoreStatStage.value) {
|
||||
const statStageMultiplier = new Utils.NumberHolder(Math.max(2, 2 + statStage.value) / Math.max(2, 2 - statStage.value));
|
||||
this.scene.applyModifiers(TempStatStageBoosterModifier, this.isPlayer(), stat, statStageMultiplier);
|
||||
return Math.min(statStageMultiplier.value, 4);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the accuracy multiplier of the user against a target.
|
||||
*
|
||||
@ -1965,34 +2106,38 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const userAccuracyLevel = new Utils.IntegerHolder(this.summonData.battleStats[BattleStat.ACC]);
|
||||
const targetEvasionLevel = new Utils.IntegerHolder(target.summonData.battleStats[BattleStat.EVA]);
|
||||
const userAccStage = new Utils.IntegerHolder(this.getStatStage(Stat.ACC));
|
||||
const targetEvaStage = new Utils.IntegerHolder(target.getStatStage(Stat.EVA));
|
||||
|
||||
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, target, null, false, userAccuracyLevel);
|
||||
applyAbAttrs(IgnoreOpponentStatChangesAbAttr, this, null, false, targetEvasionLevel);
|
||||
applyAbAttrs(IgnoreOpponentEvasionAbAttr, this, null, false, targetEvasionLevel);
|
||||
applyMoveAttrs(IgnoreOpponentStatChangesAttr, this, target, sourceMove, targetEvasionLevel);
|
||||
this.scene.applyModifiers(TempBattleStatBoosterModifier, this.isPlayer(), TempBattleStat.ACC, userAccuracyLevel);
|
||||
const ignoreAccStatStage = new Utils.BooleanHolder(false);
|
||||
const ignoreEvaStatStage = new Utils.BooleanHolder(false);
|
||||
|
||||
applyAbAttrs(IgnoreOpponentStatStagesAbAttr, target, null, false, Stat.ACC, ignoreAccStatStage);
|
||||
applyAbAttrs(IgnoreOpponentStatStagesAbAttr, this, null, false, Stat.EVA, ignoreEvaStatStage);
|
||||
applyMoveAttrs(IgnoreOpponentStatStagesAttr, this, target, sourceMove, ignoreEvaStatStage);
|
||||
|
||||
this.scene.applyModifiers(TempStatStageBoosterModifier, this.isPlayer(), Stat.ACC, userAccStage);
|
||||
|
||||
userAccStage.value = ignoreAccStatStage.value ? 0 : Math.min(userAccStage.value, 6);
|
||||
targetEvaStage.value = ignoreEvaStatStage.value ? 0 : targetEvaStage.value;
|
||||
|
||||
if (target.findTag(t => t instanceof ExposedTag)) {
|
||||
targetEvasionLevel.value = Math.min(0, targetEvasionLevel.value);
|
||||
targetEvaStage.value = Math.min(0, targetEvaStage.value);
|
||||
}
|
||||
|
||||
const accuracyMultiplier = new Utils.NumberHolder(1);
|
||||
if (userAccuracyLevel.value !== targetEvasionLevel.value) {
|
||||
accuracyMultiplier.value = userAccuracyLevel.value > targetEvasionLevel.value
|
||||
? (3 + Math.min(userAccuracyLevel.value - targetEvasionLevel.value, 6)) / 3
|
||||
: 3 / (3 + Math.min(targetEvasionLevel.value - userAccuracyLevel.value, 6));
|
||||
if (userAccStage.value !== targetEvaStage.value) {
|
||||
accuracyMultiplier.value = userAccStage.value > targetEvaStage.value
|
||||
? (3 + Math.min(userAccStage.value - targetEvaStage.value, 6)) / 3
|
||||
: 3 / (3 + Math.min(targetEvaStage.value - userAccStage.value, 6));
|
||||
}
|
||||
|
||||
applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, this, BattleStat.ACC, accuracyMultiplier, false, sourceMove);
|
||||
applyStatMultiplierAbAttrs(StatMultiplierAbAttr, this, Stat.ACC, accuracyMultiplier, false, sourceMove);
|
||||
|
||||
const evasionMultiplier = new Utils.NumberHolder(1);
|
||||
applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, target, BattleStat.EVA, evasionMultiplier);
|
||||
applyStatMultiplierAbAttrs(StatMultiplierAbAttr, target, Stat.EVA, evasionMultiplier);
|
||||
|
||||
accuracyMultiplier.value /= evasionMultiplier.value;
|
||||
|
||||
return accuracyMultiplier.value;
|
||||
return accuracyMultiplier.value / evasionMultiplier.value;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2079,29 +2224,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
if (critOnly.value || critAlways) {
|
||||
isCritical = true;
|
||||
} else {
|
||||
const critLevel = new Utils.IntegerHolder(0);
|
||||
applyMoveAttrs(HighCritAttr, source, this, move, critLevel);
|
||||
this.scene.applyModifiers(CritBoosterModifier, source.isPlayer(), source, critLevel);
|
||||
this.scene.applyModifiers(TempBattleStatBoosterModifier, source.isPlayer(), TempBattleStat.CRIT, critLevel);
|
||||
const bonusCrit = new Utils.BooleanHolder(false);
|
||||
//@ts-ignore
|
||||
if (applyAbAttrs(BonusCritAbAttr, source, null, false, bonusCrit)) { // TODO: resolve ts-ignore. This is a promise. Checking a promise is bogus.
|
||||
if (bonusCrit.value) {
|
||||
critLevel.value += 1;
|
||||
}
|
||||
}
|
||||
|
||||
const critBoostTag = source.getTag(CritBoostTag);
|
||||
if (critBoostTag) {
|
||||
if (critBoostTag instanceof DragonCheerTag) {
|
||||
critLevel.value += critBoostTag.typesOnAdd.includes(Type.DRAGON) ? 2 : 1;
|
||||
} else {
|
||||
critLevel.value += 2;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`crit stage: +${critLevel.value}`);
|
||||
const critChance = [24, 8, 2, 1][Math.max(0, Math.min(critLevel.value, 3))];
|
||||
const critChance = [24, 8, 2, 1][Math.max(0, Math.min(this.getCritStage(source, move), 3))];
|
||||
isCritical = critChance === 1 || !this.scene.randBattleSeedInt(critChance);
|
||||
if (Overrides.NEVER_CRIT_OVERRIDE) {
|
||||
isCritical = false;
|
||||
@ -2115,8 +2238,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
isCritical = false;
|
||||
}
|
||||
}
|
||||
const sourceAtk = new Utils.IntegerHolder(source.getBattleStat(isPhysical ? Stat.ATK : Stat.SPATK, this, undefined, isCritical));
|
||||
const targetDef = new Utils.IntegerHolder(this.getBattleStat(isPhysical ? Stat.DEF : Stat.SPDEF, source, move, isCritical));
|
||||
const sourceAtk = new Utils.IntegerHolder(source.getEffectiveStat(isPhysical ? Stat.ATK : Stat.SPATK, this, undefined, isCritical));
|
||||
const targetDef = new Utils.IntegerHolder(this.getEffectiveStat(isPhysical ? Stat.DEF : Stat.SPDEF, source, move, isCritical));
|
||||
const criticalMultiplier = new Utils.NumberHolder(isCritical ? 1.5 : 1);
|
||||
applyAbAttrs(MultCritAbAttr, source, null, false, criticalMultiplier);
|
||||
const screenMultiplier = new Utils.NumberHolder(1);
|
||||
@ -2527,10 +2650,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* @param source {@linkcode Pokemon} the pokemon whose stats/Tags are to be passed on from, ie: the Pokemon using Baton Pass
|
||||
*/
|
||||
transferSummon(source: Pokemon): void {
|
||||
const battleStats = Utils.getEnumValues(BattleStat);
|
||||
for (const stat of battleStats) {
|
||||
this.summonData.battleStats[stat] = source.summonData.battleStats[stat];
|
||||
// Copy all stat stages
|
||||
for (const s of BATTLE_STATS) {
|
||||
const sourceStage = source.getStatStage(s);
|
||||
if ((this instanceof PlayerPokemon) && (sourceStage === 6)) {
|
||||
this.scene.validateAchv(achvs.TRANSFER_MAX_STAT_STAGE);
|
||||
}
|
||||
this.setStatStage(s, sourceStage);
|
||||
}
|
||||
|
||||
for (const tag of source.summonData.tags) {
|
||||
|
||||
// bypass those can not be passed via Baton Pass
|
||||
@ -2542,9 +2670,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
this.summonData.tags.push(tag);
|
||||
}
|
||||
if (this instanceof PlayerPokemon && source.summonData.battleStats.find(bs => bs === 6)) {
|
||||
this.scene.validateAchv(achvs.TRANSFER_MAX_BATTLE_STAT);
|
||||
}
|
||||
|
||||
this.updateInfo();
|
||||
}
|
||||
|
||||
@ -3357,6 +3483,7 @@ export default interface Pokemon {
|
||||
|
||||
export class PlayerPokemon extends Pokemon {
|
||||
public compatibleTms: Moves[];
|
||||
public usedTms: Moves[];
|
||||
|
||||
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData) {
|
||||
super(scene, 106, 148, species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource);
|
||||
@ -3380,6 +3507,7 @@ export class PlayerPokemon extends Pokemon {
|
||||
}
|
||||
}
|
||||
this.generateCompatibleTms();
|
||||
this.usedTms = [];
|
||||
}
|
||||
|
||||
initBattleInfo(): void {
|
||||
@ -3638,6 +3766,9 @@ export class PlayerPokemon extends Pokemon {
|
||||
newPokemon.moveset = this.moveset.slice();
|
||||
newPokemon.moveset = this.copyMoveset();
|
||||
newPokemon.luck = this.luck;
|
||||
newPokemon.metLevel = this.metLevel;
|
||||
newPokemon.metBiome = this.metBiome;
|
||||
newPokemon.metSpecies = this.metSpecies;
|
||||
newPokemon.fusionSpecies = this.fusionSpecies;
|
||||
newPokemon.fusionFormIndex = this.fusionFormIndex;
|
||||
newPokemon.fusionAbilityIndex = this.fusionAbilityIndex;
|
||||
@ -3717,16 +3848,17 @@ export class PlayerPokemon extends Pokemon {
|
||||
this.scene.gameData.gameStats.pokemonFused++;
|
||||
|
||||
// Store the average HP% that each Pokemon has
|
||||
const newHpPercent = ((pokemon.hp / pokemon.stats[Stat.HP]) + (this.hp / this.stats[Stat.HP])) / 2;
|
||||
const maxHp = this.getMaxHp();
|
||||
const newHpPercent = ((pokemon.hp / pokemon.getMaxHp()) + (this.hp / maxHp)) / 2;
|
||||
|
||||
this.generateName();
|
||||
this.calculateStats();
|
||||
|
||||
// Set this Pokemon's HP to the average % of both fusion components
|
||||
this.hp = Math.round(this.stats[Stat.HP] * newHpPercent);
|
||||
this.hp = Math.round(maxHp * newHpPercent);
|
||||
if (!this.isFainted()) {
|
||||
// If this Pokemon hasn't fainted, make sure the HP wasn't set over the new maximum
|
||||
this.hp = Math.min(this.hp, this.stats[Stat.HP]);
|
||||
this.hp = Math.min(this.hp, maxHp);
|
||||
this.status = getRandomStatus(this.status, pokemon.status); // Get a random valid status between the two
|
||||
} else if (!pokemon.isFainted()) {
|
||||
// If this Pokemon fainted but the other hasn't, make sure the HP wasn't set to zero
|
||||
@ -4176,7 +4308,7 @@ export class EnemyPokemon extends Pokemon {
|
||||
//console.log('damage', damage, 'segment', segmentsBypassed + 1, 'segment size', segmentSize, 'damage needed', Math.round(segmentSize * Math.pow(2, segmentsBypassed + 1)));
|
||||
}
|
||||
|
||||
damage = hpRemainder + Math.round(segmentSize * segmentsBypassed);
|
||||
damage = Utils.toDmgValue(this.hp - hpThreshold + segmentSize * segmentsBypassed);
|
||||
clearedBossSegmentIndex = s - segmentsBypassed;
|
||||
}
|
||||
break;
|
||||
@ -4219,43 +4351,40 @@ export class EnemyPokemon extends Pokemon {
|
||||
|
||||
handleBossSegmentCleared(segmentIndex: integer): void {
|
||||
while (segmentIndex - 1 < this.bossSegmentIndex) {
|
||||
let boostedStat = BattleStat.RAND;
|
||||
// Filter out already maxed out stat stages and weigh the rest based on existing stats
|
||||
const leftoverStats = EFFECTIVE_STATS.filter((s: EffectiveStat) => this.getStatStage(s) < 6);
|
||||
const statWeights = leftoverStats.map((s: EffectiveStat) => this.getStat(s, false));
|
||||
|
||||
const battleStats = Utils.getEnumValues(BattleStat).slice(0, -3);
|
||||
const statWeights = new Array().fill(battleStats.length).filter((bs: BattleStat) => this.summonData.battleStats[bs] < 6).map((bs: BattleStat) => this.getStat(bs + 1));
|
||||
const statThresholds: integer[] = [];
|
||||
let boostedStat: EffectiveStat;
|
||||
const statThresholds: number[] = [];
|
||||
let totalWeight = 0;
|
||||
for (const bs of battleStats) {
|
||||
totalWeight += statWeights[bs];
|
||||
|
||||
for (const i in statWeights) {
|
||||
totalWeight += statWeights[i];
|
||||
statThresholds.push(totalWeight);
|
||||
}
|
||||
|
||||
// Pick a random stat from the leftover stats to increase its stages
|
||||
const randInt = Utils.randSeedInt(totalWeight);
|
||||
|
||||
for (const bs of battleStats) {
|
||||
if (randInt < statThresholds[bs]) {
|
||||
boostedStat = bs;
|
||||
for (const i in statThresholds) {
|
||||
if (randInt < statThresholds[i]) {
|
||||
boostedStat = leftoverStats[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let statLevels = 1;
|
||||
let stages = 1;
|
||||
|
||||
switch (segmentIndex) {
|
||||
case 1:
|
||||
if (this.bossSegments >= 3) {
|
||||
statLevels++;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (this.bossSegments >= 5) {
|
||||
statLevels++;
|
||||
}
|
||||
break;
|
||||
// increase the boost if the boss has at least 3 segments and we passed last shield
|
||||
if (this.bossSegments >= 3 && this.bossSegmentIndex === 1) {
|
||||
stages++;
|
||||
}
|
||||
// increase the boost if the boss has at least 5 segments and we passed the second to last shield
|
||||
if (this.bossSegments >= 5 && this.bossSegmentIndex === 2) {
|
||||
stages++;
|
||||
}
|
||||
|
||||
this.scene.unshiftPhase(new StatChangePhase(this.scene, this.getBattlerIndex(), true, [ boostedStat ], statLevels, true, true));
|
||||
|
||||
this.scene.unshiftPhase(new StatStageChangePhase(this.scene, this.getBattlerIndex(), true, [ boostedStat! ], stages, true, true));
|
||||
this.bossSegmentIndex--;
|
||||
}
|
||||
}
|
||||
@ -4331,7 +4460,7 @@ export interface AttackMoveResult {
|
||||
}
|
||||
|
||||
export class PokemonSummonData {
|
||||
public battleStats: number[] = [ 0, 0, 0, 0, 0, 0, 0 ];
|
||||
public statStages: number[] = [ 0, 0, 0, 0, 0, 0, 0 ];
|
||||
public moveQueue: QueuedMove[] = [];
|
||||
public disabledMove: Moves = Moves.NONE;
|
||||
public disabledTurns: number = 0;
|
||||
@ -4344,7 +4473,7 @@ export class PokemonSummonData {
|
||||
public ability: Abilities = Abilities.NONE;
|
||||
public gender: Gender;
|
||||
public fusionGender: Gender;
|
||||
public stats: number[];
|
||||
public stats: number[] = [ 0, 0, 0, 0, 0, 0 ];
|
||||
public moveset: (PokemonMove | null)[];
|
||||
// If not initialized this value will not be populated from save data.
|
||||
public types: Type[] = [];
|
||||
@ -4375,8 +4504,8 @@ export class PokemonTurnData {
|
||||
public damageTaken: number = 0;
|
||||
public attacksReceived: AttackMoveResult[] = [];
|
||||
public order: number;
|
||||
public battleStatsIncreased: boolean = false;
|
||||
public battleStatsDecreased: boolean = false;
|
||||
public statStagesIncreased: boolean = false;
|
||||
public statStagesDecreased: boolean = false;
|
||||
}
|
||||
|
||||
export enum AiType {
|
||||
|
@ -37,8 +37,7 @@ export interface ModifierTypeTranslationEntries {
|
||||
ModifierType: { [key: string]: ModifierTypeTranslationEntry },
|
||||
SpeciesBoosterItem: { [key: string]: ModifierTypeTranslationEntry },
|
||||
AttackTypeBoosterItem: SimpleTranslationEntries,
|
||||
TempBattleStatBoosterItem: SimpleTranslationEntries,
|
||||
TempBattleStatBoosterStatName: SimpleTranslationEntries,
|
||||
TempStatStageBoosterItem: SimpleTranslationEntries,
|
||||
BaseStatBoosterItem: SimpleTranslationEntries,
|
||||
EvolutionItem: SimpleTranslationEntries,
|
||||
FormChangeItem: SimpleTranslationEntries,
|
||||
|
@ -98,6 +98,8 @@ export class LoadingScene extends SceneBase {
|
||||
this.loadImage("ha_capsule", "ui", "ha_capsule.png");
|
||||
this.loadImage("champion_ribbon", "ui", "champion_ribbon.png");
|
||||
this.loadImage("icon_spliced", "ui");
|
||||
this.loadImage("icon_lock", "ui", "icon_lock.png");
|
||||
this.loadImage("icon_stop", "ui", "icon_stop.png");
|
||||
this.loadImage("icon_tera", "ui");
|
||||
this.loadImage("type_tera", "ui");
|
||||
this.loadAtlas("type_bgs", "ui");
|
||||
|
@ -89,7 +89,7 @@
|
||||
"name": "Bänder-Meister",
|
||||
"name_female": "Bänder-Meisterin"
|
||||
},
|
||||
"TRANSFER_MAX_BATTLE_STAT": {
|
||||
"TRANSFER_MAX_STAT_STAGE": {
|
||||
"name": "Teamwork",
|
||||
"description": "Nutze Staffette, während der Anwender mindestens eines Statuswertes maximiert hat."
|
||||
},
|
||||
@ -274,4 +274,4 @@
|
||||
"name": "Spieglein, Spieglein an der Wand",
|
||||
"description": "Schließe die 'Umkehrkampf' Herausforderung ab"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"ending": "@c{smile}Oh? Du hast gewonnen?@d{96} @c{smile_eclosed}Ich schätze, das hätte ich wissen sollen.\n$Aber, du bist jetzt zurück.\n$@c{smile}Es ist vorbei.@d{64} Du hast die Schleife beendet.\n$@c{serious_smile_fists}Du hast auch deinen Traum erfüllt, nicht wahr?\nDu hast nicht einmal verloren.\n$@c{neutral}Ich bin der Einzige, der sich daran erinnern wird, was du getan hast.@d{96}\n$Ich schätze, das ist in Ordnung, oder?\n$@c{serious_smile_fists}Deine Legende wird immer in unseren Herzen weiterleben.\n$@c{smile_eclosed}Wie auch immer, ich habe genug von diesem Ort, oder nicht? Lass uns nach Hause gehen.\n$@c{serious_smile_fists}Vielleicht können wir, wenn wir zurück sind, noch einen Kampf haben?\n$Wenn du dazu bereit bist.",
|
||||
"ending_female": "@c{shock}Du bist zurück?@d{32} Bedeutet das…@d{96} du hast gewonnen?!\n$@c{smile_ehalf}Ich hätte wissen sollen, dass du es in dir hast.\n$@c{smile_eclosed}Natürlich… ich hatte immer dieses Gefühl.\n$@c{smile}Es ist jetzt vorbei, richtig? Du hast die Schleife beendet.\n$@c{smile_ehalf}Du hast auch deinen Traum erfüllt, nicht wahr?\n$Du hast nicht einmal verloren.\n$Ich werde die Einzige sein, die sich daran erinnert, was du getan hast.\n$@c{angry_mopen}Ich werde versuchen, es nicht zu vergessen!\n$@c{smile_wave_wink}Nur ein Scherz!@d{64} @c{smile}Ich würde es nie vergessen.@d{32}\n$Deine Legende wird in unseren Herzen weiterleben.\n$@c{smile_wave}Wie auch immer,@d{64} es wird spät…@d{96} denke ich?\nEs ist schwer zu sagen an diesem Ort.\n$Lass uns nach Hause gehen. \n$@c{smile_wave_wink}Vielleicht können wir morgen noch einen Kampf haben, der alten Zeiten willen?",
|
||||
"ending": "@c{shock}Du bist zurück?@d{32} Bedeutet das…@d{96} du hast gewonnen?!\n$@c{smile_ehalf}Ich hätte wissen sollen, dass du es in dir hast.\n$@c{smile_eclosed}Natürlich… ich hatte immer dieses Gefühl.\n$@c{smile}Es ist jetzt vorbei, richtig? Du hast die Schleife beendet.\n$@c{smile_ehalf}Du hast auch deinen Traum erfüllt, nicht wahr?\n$Du hast nicht einmal verloren.\n$Ich werde die Einzige sein, die sich daran erinnert, was du getan hast.\n$@c{angry_mopen}Ich werde versuchen, es nicht zu vergessen!\n$@c{smile_wave_wink}Nur ein Scherz!@d{64} @c{smile}Ich würde es nie vergessen.@d{32}\n$Deine Legende wird in unseren Herzen weiterleben.\n$@c{smile_wave}Wie auch immer,@d{64} es wird spät…@d{96} denke ich?\nEs ist schwer zu sagen an diesem Ort.\n$Lass uns nach Hause gehen. \n$@c{smile_wave_wink}Vielleicht können wir morgen noch einen Kampf haben, der alten Zeiten willen?",
|
||||
"ending_female": "@c{smile}Oh? Du hast gewonnen?@d{96} @c{smile_eclosed}Ich schätze, das hätte ich wissen sollen.\n$Aber, du bist jetzt zurück.\n$@c{smile}Es ist vorbei.@d{64} Du hast die Schleife beendet.\n$@c{serious_smile_fists}Du hast auch deinen Traum erfüllt, nicht wahr?\nDu hast nicht einmal verloren.\n$@c{neutral}Ich bin der Einzige, der sich daran erinnern wird, was du getan hast.@d{96}\n$Ich schätze, das ist in Ordnung, oder?\n$@c{serious_smile_fists}Deine Legende wird immer in unseren Herzen weiterleben.\n$@c{smile_eclosed}Wie auch immer, ich habe genug von diesem Ort, oder nicht? Lass uns nach Hause gehen.\n$@c{serious_smile_fists}Vielleicht können wir, wenn wir zurück sind, noch einen Kampf haben?\n$Wenn du dazu bereit bist.",
|
||||
"ending_endless": "Glückwunsch! Du hast das aktuelle Ende erreicht!\nWir arbeiten an mehr Spielinhalten.",
|
||||
"ending_name": "Entwickler"
|
||||
}
|
||||
|
@ -49,8 +49,8 @@
|
||||
"DoubleBattleChanceBoosterModifierType": {
|
||||
"description": "Verdoppelt die Wahrscheinlichkeit, dass die nächsten {{battleCount}} Begegnungen mit wilden Pokémon ein Doppelkampf sind."
|
||||
},
|
||||
"TempBattleStatBoosterModifierType": {
|
||||
"description": "Erhöht die {{tempBattleStatName}} aller Teammitglieder für 5 Kämpfe um eine Stufe."
|
||||
"TempStatStageBoosterModifierType": {
|
||||
"description": "Erhöht die {{stat}} aller Teammitglieder für 5 Kämpfe um eine Stufe."
|
||||
},
|
||||
"AttackTypeBoosterModifierType": {
|
||||
"description": "Erhöht die Stärke aller {{moveType}}-Attacken eines Pokémon um 20%."
|
||||
@ -61,8 +61,8 @@
|
||||
"AllPokemonLevelIncrementModifierType": {
|
||||
"description": "Erhöht das Level aller Teammitglieder um {{levels}}."
|
||||
},
|
||||
"PokemonBaseStatBoosterModifierType": {
|
||||
"description": "Erhöht den {{statName}} Basiswert des Trägers um 10%. Das Stapellimit erhöht sich, je höher dein IS-Wert ist."
|
||||
"BaseStatBoosterModifierType": {
|
||||
"description": "Erhöht den {{stat}} Basiswert des Trägers um 10%. Das Stapellimit erhöht sich, je höher dein IS-Wert ist."
|
||||
},
|
||||
"AllPokemonFullHpRestoreModifierType": {
|
||||
"description": "Stellt 100% der KP aller Pokémon her."
|
||||
@ -248,6 +248,12 @@
|
||||
"name": "Scope-Linse",
|
||||
"description": "Ein Item zum Tragen. Es erhöht die Volltrefferquote."
|
||||
},
|
||||
"DIRE_HIT": {
|
||||
"name": "X-Volltreffer",
|
||||
"extra": {
|
||||
"raises": "Volltrefferquote"
|
||||
}
|
||||
},
|
||||
"LEEK": {
|
||||
"name": "Lauchstange",
|
||||
"description": "Ein Item, das von Porenta getragen werden kann. Diese lange Lauchstange erhöht die Volltrefferquote stark."
|
||||
@ -411,25 +417,13 @@
|
||||
"description": "Ein Item, das Ditto zum Tragen gegeben werden kann. Fein und doch hart, erhöht dieses sonderbare Pulver die Initiative."
|
||||
}
|
||||
},
|
||||
"TempBattleStatBoosterItem": {
|
||||
"TempStatStageBoosterItem": {
|
||||
"x_attack": "X-Angriff",
|
||||
"x_defense": "X-Verteidigung",
|
||||
"x_sp_atk": "X-Sp.-Ang.",
|
||||
"x_sp_def": "X-Sp.-Vert.",
|
||||
"x_speed": "X-Tempo",
|
||||
"x_accuracy": "X-Treffer",
|
||||
"dire_hit": "X-Volltreffer"
|
||||
},
|
||||
"TempBattleStatBoosterStatName": {
|
||||
"ATK": "Angriff",
|
||||
"DEF": "Verteidigung",
|
||||
"SPATK": "Sp. Ang",
|
||||
"SPDEF": "Sp. Vert",
|
||||
"SPD": "Initiative",
|
||||
"ACC": "Genauigkeit",
|
||||
"CRIT": "Volltrefferquote",
|
||||
"EVA": "Fluchtwert",
|
||||
"DEFAULT": "???"
|
||||
"x_accuracy": "X-Treffer"
|
||||
},
|
||||
"AttackTypeBoosterItem": {
|
||||
"silk_scarf": "Seidenschal",
|
||||
@ -606,4 +600,4 @@
|
||||
"FAIRY_MEMORY": "Feen-Disc",
|
||||
"NORMAL_MEMORY": "Normal-Disc"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
"turnHealApply": "{{typeName}} von {{pokemonNameWithAffix}} füllt einige KP auf!",
|
||||
"hitHealApply": "{{typeName}} von {{pokemonNameWithAffix}} füllt einige KP auf!",
|
||||
"pokemonInstantReviveApply": "{{pokemonNameWithAffix}} wurde durch {{typeName}} wiederbelebt!",
|
||||
"pokemonResetNegativeStatStageApply": "Die negative Statuswertveränderung von {{pokemonNameWithAffix}} wurde durch {{typeName}} aufgehoben!",
|
||||
"resetNegativeStatStageApply": "Die negative Statuswertveränderung von {{pokemonNameWithAffix}} wurde durch {{typeName}} aufgehoben!",
|
||||
"moneyInterestApply": "Du erhählst {{moneyAmount}} ₽ durch das Item {{typeName}}!",
|
||||
"turnHeldItemTransferApply": "{{itemName}} von {{pokemonNameWithAffix}} wurde durch {{typeName}} von {{pokemonName}} absorbiert!",
|
||||
"contactHeldItemTransferApply": "{{itemName}} von {{pokemonNameWithAffix}} wurde durch {{typeName}} von {{pokemonName}} geklaut!",
|
||||
|
@ -3,6 +3,10 @@
|
||||
"cutHpPowerUpMove": "{{pokemonName}} nutzt seine KP um seine Attacke zu verstärken!",
|
||||
"absorbedElectricity": "{{pokemonName}} absorbiert elektrische Energie!",
|
||||
"switchedStatChanges": "{{pokemonName}} tauschte die Statuswerteveränderungen mit dem Ziel!",
|
||||
"switchedTwoStatChanges": "{{pokemonName}} tauscht Veränderungen an {{firstStat}} und {{secondStat}} mit dem Ziel!",
|
||||
"switchedStat": "{{pokemonName}} tauscht seinen {{stat}}-Wert mit dem des Zieles!",
|
||||
"sharedGuard": "{{pokemonName}} addiert seine Schutzkräfte mit jenen des Zieles und teilt sie gerecht auf!",
|
||||
"sharedPower": "{{pokemonName}} addiert seine Kräfte mit jenen des Zieles und teilt sie gerecht auf!",
|
||||
"goingAllOutForAttack": "{{pokemonName}} legt sich ins Zeug!",
|
||||
"regainedHealth": "{{pokemonName}} erholt sich!",
|
||||
"keptGoingAndCrashed": "{{pokemonName}} springt daneben und verletzt sich!",
|
||||
@ -63,4 +67,4 @@
|
||||
"swapArenaTags": "{{pokemonName}} hat die Effekte, die auf den beiden Seiten des Kampffeldes wirken, miteinander getauscht!",
|
||||
"exposedMove": "{{pokemonName}} erkennt {{targetPokemonName}}!",
|
||||
"safeguard": "{{targetName}} wird durch Bodyguard geschützt!"
|
||||
}
|
||||
}
|
||||
|
@ -10,5 +10,5 @@
|
||||
"eternamaxChange": "{{preName}} hat sich zu {{pokemonName}} unendynamaximiert!",
|
||||
"revertChange": "{{pokemonName}} hat seine ursprüngliche Form zurückerlangt!",
|
||||
"formChange": "{{preName}} hat seine Form geändert!",
|
||||
"disguiseChange": "Its disguise served it as a decoy!"
|
||||
"disguiseChange": "Sein Kostüm hat die Attacke absorbiert!"
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"Stat": {
|
||||
"HP": "KP",
|
||||
"HPStat": "KP",
|
||||
"HPshortened": "KP",
|
||||
"ATK": "Angriff",
|
||||
"ATKshortened": "Ang",
|
||||
|
@ -1,268 +0,0 @@
|
||||
{
|
||||
"Achievements": {
|
||||
"name": "Achievements"
|
||||
},
|
||||
"Locked": {
|
||||
"name": "Locked"
|
||||
},
|
||||
"MoneyAchv": {
|
||||
"description": "Accumulate a total of ₽{{moneyAmount}}"
|
||||
},
|
||||
"10K_MONEY": {
|
||||
"name": "Money Haver"
|
||||
},
|
||||
"100K_MONEY": {
|
||||
"name": "Rich"
|
||||
},
|
||||
"1M_MONEY": {
|
||||
"name": "Millionaire"
|
||||
},
|
||||
"10M_MONEY": {
|
||||
"name": "One Percenter"
|
||||
},
|
||||
"DamageAchv": {
|
||||
"description": "Inflict {{damageAmount}} damage in one hit"
|
||||
},
|
||||
"250_DMG": {
|
||||
"name": "Hard Hitter"
|
||||
},
|
||||
"1000_DMG": {
|
||||
"name": "Harder Hitter"
|
||||
},
|
||||
"2500_DMG": {
|
||||
"name": "That's a Lotta Damage!"
|
||||
},
|
||||
"10000_DMG": {
|
||||
"name": "One Punch Man"
|
||||
},
|
||||
"HealAchv": {
|
||||
"description": "Heal {{healAmount}} {{HP}} at once with a move, ability, or held item"
|
||||
},
|
||||
"250_HEAL": {
|
||||
"name": "Novice Healer"
|
||||
},
|
||||
"1000_HEAL": {
|
||||
"name": "Big Healer"
|
||||
},
|
||||
"2500_HEAL": {
|
||||
"name": "Cleric"
|
||||
},
|
||||
"10000_HEAL": {
|
||||
"name": "Recovery Master"
|
||||
},
|
||||
"LevelAchv": {
|
||||
"description": "Level up a Pokémon to Lv{{level}}"
|
||||
},
|
||||
"LV_100": {
|
||||
"name": "But Wait, There's More!"
|
||||
},
|
||||
"LV_250": {
|
||||
"name": "Elite"
|
||||
},
|
||||
"LV_1000": {
|
||||
"name": "To Go Even Further Beyond"
|
||||
},
|
||||
"RibbonAchv": {
|
||||
"description": "Accumulate a total of {{ribbonAmount}} Ribbons"
|
||||
},
|
||||
"10_RIBBONS": {
|
||||
"name": "Pokémon League Champion"
|
||||
},
|
||||
"25_RIBBONS": {
|
||||
"name": "Great League Champion"
|
||||
},
|
||||
"50_RIBBONS": {
|
||||
"name": "Ultra League Champion"
|
||||
},
|
||||
"75_RIBBONS": {
|
||||
"name": "Rogue League Champion"
|
||||
},
|
||||
"100_RIBBONS": {
|
||||
"name": "Master League Champion"
|
||||
},
|
||||
"TRANSFER_MAX_BATTLE_STAT": {
|
||||
"name": "Teamwork",
|
||||
"description": "Baton pass to another party member with at least one stat maxed out"
|
||||
},
|
||||
"MAX_FRIENDSHIP": {
|
||||
"name": "Friendmaxxing",
|
||||
"description": "Reach max friendship on a Pokémon"
|
||||
},
|
||||
"MEGA_EVOLVE": {
|
||||
"name": "Megamorph",
|
||||
"description": "Mega evolve a Pokémon"
|
||||
},
|
||||
"GIGANTAMAX": {
|
||||
"name": "Absolute Unit",
|
||||
"description": "Gigantamax a Pokémon"
|
||||
},
|
||||
"TERASTALLIZE": {
|
||||
"name": "STAB Enthusiast",
|
||||
"description": "Terastallize a Pokémon"
|
||||
},
|
||||
"STELLAR_TERASTALLIZE": {
|
||||
"name": "The Hidden Type",
|
||||
"description": "Stellar Terastallize a Pokémon"
|
||||
},
|
||||
"SPLICE": {
|
||||
"name": "Infinite Fusion",
|
||||
"description": "Splice two Pokémon together with DNA Splicers"
|
||||
},
|
||||
"MINI_BLACK_HOLE": {
|
||||
"name": "A Hole Lot of Items",
|
||||
"description": "Acquire a Mini Black Hole"
|
||||
},
|
||||
"CATCH_MYTHICAL": {
|
||||
"name": "Mythical",
|
||||
"description": "Catch a mythical Pokémon"
|
||||
},
|
||||
"CATCH_SUB_LEGENDARY": {
|
||||
"name": "(Sub-)Legendary",
|
||||
"description": "Catch a sub-legendary Pokémon"
|
||||
},
|
||||
"CATCH_LEGENDARY": {
|
||||
"name": "Legendary",
|
||||
"description": "Catch a legendary Pokémon"
|
||||
},
|
||||
"SEE_SHINY": {
|
||||
"name": "Shiny",
|
||||
"description": "Find a shiny Pokémon in the wild"
|
||||
},
|
||||
"SHINY_PARTY": {
|
||||
"name": "That's Dedication",
|
||||
"description": "Have a full party of shiny Pokémon"
|
||||
},
|
||||
"HATCH_MYTHICAL": {
|
||||
"name": "Mythical Egg",
|
||||
"description": "Hatch a mythical Pokémon from an egg"
|
||||
},
|
||||
"HATCH_SUB_LEGENDARY": {
|
||||
"name": "Sub-Legendary Egg",
|
||||
"description": "Hatch a sub-legendary Pokémon from an egg"
|
||||
},
|
||||
"HATCH_LEGENDARY": {
|
||||
"name": "Legendary Egg",
|
||||
"description": "Hatch a legendary Pokémon from an egg"
|
||||
},
|
||||
"HATCH_SHINY": {
|
||||
"name": "Shiny Egg",
|
||||
"description": "Hatch a shiny Pokémon from an egg"
|
||||
},
|
||||
"HIDDEN_ABILITY": {
|
||||
"name": "Hidden Potential",
|
||||
"description": "Catch a Pokémon with a hidden ability"
|
||||
},
|
||||
"PERFECT_IVS": {
|
||||
"name": "Certificate of Authenticity",
|
||||
"description": "Get perfect IVs on a Pokémon"
|
||||
},
|
||||
"CLASSIC_VICTORY": {
|
||||
"name": "Undefeated",
|
||||
"description": "Beat the game in classic mode"
|
||||
},
|
||||
"UNEVOLVED_CLASSIC_VICTORY": {
|
||||
"name": "Bring Your Child To Work Day",
|
||||
"description": "Beat the game in Classic Mode with at least one unevolved party member."
|
||||
},
|
||||
"MONO_GEN_ONE": {
|
||||
"name": "The Original Rival",
|
||||
"description": "Complete the generation one only challenge."
|
||||
},
|
||||
"MONO_GEN_TWO": {
|
||||
"name": "Generation 1.5",
|
||||
"description": "Complete the generation two only challenge."
|
||||
},
|
||||
"MONO_GEN_THREE": {
|
||||
"name": "Too much water?",
|
||||
"description": "Complete the generation three only challenge."
|
||||
},
|
||||
"MONO_GEN_FOUR": {
|
||||
"name": "Is she really the hardest?",
|
||||
"description": "Complete the generation four only challenge."
|
||||
},
|
||||
"MONO_GEN_FIVE": {
|
||||
"name": "All Original",
|
||||
"description": "Complete the generation five only challenge."
|
||||
},
|
||||
"MONO_GEN_SIX": {
|
||||
"name": "Almost Royalty",
|
||||
"description": "Complete the generation six only challenge."
|
||||
},
|
||||
"MONO_GEN_SEVEN": {
|
||||
"name": "Only Technically",
|
||||
"description": "Complete the generation seven only challenge."
|
||||
},
|
||||
"MONO_GEN_EIGHT": {
|
||||
"name": "A Champion Time!",
|
||||
"description": "Complete the generation eight only challenge."
|
||||
},
|
||||
"MONO_GEN_NINE": {
|
||||
"name": "She was going easy on you",
|
||||
"description": "Complete the generation nine only challenge."
|
||||
},
|
||||
"MonoType": {
|
||||
"description": "Complete the {{type}} monotype challenge."
|
||||
},
|
||||
"MONO_NORMAL": {
|
||||
"name": "Extra Ordinary"
|
||||
},
|
||||
"MONO_FIGHTING": {
|
||||
"name": "I Know Kung Fu"
|
||||
},
|
||||
"MONO_FLYING": {
|
||||
"name": "Angry Birds"
|
||||
},
|
||||
"MONO_POISON": {
|
||||
"name": "Kanto's Favourite"
|
||||
},
|
||||
"MONO_GROUND": {
|
||||
"name": "Forecast: Earthquakes"
|
||||
},
|
||||
"MONO_ROCK": {
|
||||
"name": "Brock Hard"
|
||||
},
|
||||
"MONO_BUG": {
|
||||
"name": "You Like Jazz?"
|
||||
},
|
||||
"MONO_GHOST": {
|
||||
"name": "Who You Gonna Call?"
|
||||
},
|
||||
"MONO_STEEL": {
|
||||
"name": "Iron Giant"
|
||||
},
|
||||
"MONO_FIRE": {
|
||||
"name": "I Cast Fireball!"
|
||||
},
|
||||
"MONO_WATER": {
|
||||
"name": "When It Rains, It Pours"
|
||||
},
|
||||
"MONO_GRASS": {
|
||||
"name": "Can't Touch This"
|
||||
},
|
||||
"MONO_ELECTRIC": {
|
||||
"name": "Aim For The Horn!"
|
||||
},
|
||||
"MONO_PSYCHIC": {
|
||||
"name": "Big Brain Energy"
|
||||
},
|
||||
"MONO_ICE": {
|
||||
"name": "Walking On Thin Ice"
|
||||
},
|
||||
"MONO_DRAGON": {
|
||||
"name": "Pseudo-Legend Club"
|
||||
},
|
||||
"MONO_DARK": {
|
||||
"name": "It's Just A Phase"
|
||||
},
|
||||
"MONO_FAIRY": {
|
||||
"name": "Hey! Listen!"
|
||||
},
|
||||
"FRESH_START": {
|
||||
"name": "First Try!",
|
||||
"description": "Complete the Fresh Start challenge."
|
||||
},
|
||||
"INVERSE_BATTLE": {
|
||||
"name": "Mirror rorriM",
|
||||
"description": "Complete the Inverse Battle challenge.\n.egnellahc elttaB esrevnI eht etelpmoC"
|
||||
}
|
||||
}
|
@ -97,9 +97,9 @@
|
||||
"name": "Master League Champion",
|
||||
"name_female": "Master League Champion"
|
||||
},
|
||||
"TRANSFER_MAX_BATTLE_STAT": {
|
||||
"TRANSFER_MAX_STAT_STAGE": {
|
||||
"name": "Teamwork",
|
||||
"description": "Baton pass to another party member with at least one stat maxed out"
|
||||
"description": "Baton pass to another party member with at least one stat stage maxed out"
|
||||
},
|
||||
"MAX_FRIENDSHIP": {
|
||||
"name": "Friendmaxxing",
|
||||
@ -284,4 +284,4 @@
|
||||
"name": "Mirror rorriM",
|
||||
"description": "Complete the Inverse Battle challenge.\n.egnellahc elttaB esrevnI eht etelpmoC"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"ending": "@c{smile}Oh? You won?@d{96} @c{smile_eclosed}I guess I should've known.\nBut, you're back now.\n$@c{smile}It's over.@d{64} You ended the loop.\n$@c{serious_smile_fists}You fulfilled your dream too, didn't you?\nYou didn't lose even once.\n$@c{neutral}I'm the only one who'll remember what you did.@d{96}\nI guess that's okay, isn't it?\n$@c{serious_smile_fists}Your legend will always live on in our hearts.\n$@c{smile_eclosed}Anyway, I've had about enough of this place, haven't you? Let's head home.\n$@c{serious_smile_fists}Maybe when we get back, we can have another battle?\nIf you're up to it.",
|
||||
"ending_female": "@c{shock}You're back?@d{32} Does that mean…@d{96} you won?!\n@c{smile_ehalf}I should have known you had it in you.\n$@c{smile_eclosed}Of course… I always had that feeling.\n@c{smile}It's over now, right? You ended the loop.\n$@c{smile_ehalf}You fulfilled your dream too, didn't you?\nYou didn't lose even once.\n$I'll be the only one to remember what you did.\n@c{angry_mopen}I'll try not to forget!\n$@c{smile_wave_wink}Just kidding!@d{64} @c{smile}I'd never forget.@d{32}\nYour legend will live on in our hearts.\n$@c{smile_wave}Anyway,@d{64} it's getting late…@d{96} I think?\nIt's hard to tell in this place.\n$Let's go home. @c{smile_wave_wink}Maybe tomorrow, we can have another battle, for old time's sake?",
|
||||
"ending": "@c{shock}You're back?@d{32} Does that mean…@d{96} you won?!\n@c{smile_ehalf}I should have known you had it in you.\n$@c{smile_eclosed}Of course… I always had that feeling.\n@c{smile}It's over now, right? You ended the loop.\n$@c{smile_ehalf}You fulfilled your dream too, didn't you?\nYou didn't lose even once.\n$I'll be the only one to remember what you did.\n@c{angry_mopen}I'll try not to forget!\n$@c{smile_wave_wink}Just kidding!@d{64} @c{smile}I'd never forget.@d{32}\nYour legend will live on in our hearts.\n$@c{smile_wave}Anyway,@d{64} it's getting late…@d{96} I think?\nIt's hard to tell in this place.\n$Let's go home. @c{smile_wave_wink}Maybe tomorrow, we can have another battle, for old time's sake?",
|
||||
"ending_female": "@c{smile}Oh? You won?@d{96} @c{smile_eclosed}I guess I should've known.\nBut, you're back now.\n$@c{smile}It's over.@d{64} You ended the loop.\n$@c{serious_smile_fists}You fulfilled your dream too, didn't you?\nYou didn't lose even once.\n$@c{neutral}I'm the only one who'll remember what you did.@d{96}\nI guess that's okay, isn't it?\n$@c{serious_smile_fists}Your legend will always live on in our hearts.\n$@c{smile_eclosed}Anyway, I've had about enough of this place, haven't you? Let's head home.\n$@c{serious_smile_fists}Maybe when we get back, we can have another battle?\nIf you're up to it.",
|
||||
"ending_endless": "Congratulations on reaching the current end!\nMore content is coming soon.",
|
||||
"ending_name": "Devs"
|
||||
}
|
||||
}
|
||||
|
@ -699,6 +699,7 @@
|
||||
"encounter": {
|
||||
"1": "I'll fight you with all I have to wipe you out!",
|
||||
"2": "I don't care if you're a kid or what. I'll send you flying if you threaten us!",
|
||||
"2_female": "I don't care if you're a kid or what. I'll send you flying if you threaten us!",
|
||||
"3": "I was told to turn away Trainers, whomever they might be!",
|
||||
"4": "I'll show you the power of Aether Paradise!",
|
||||
"5": "Now that you've learned of the darkness at the heart of Aether Paradise, we'll need you to conveniently disappear!"
|
||||
@ -715,11 +716,13 @@
|
||||
"encounter": {
|
||||
"1": "I, Branch Chief Faba, shall show you the harshness of the real world!",
|
||||
"2": "The man who is called Aether Paradise's last line of defense is to battle a mere child?",
|
||||
"2_female": "The man who is called Aether Paradise's last line of defense is to battle a mere child?",
|
||||
"3": "I, Faba, am the Aether Branch Chief. The only one in the world, I'm irreplaceable."
|
||||
},
|
||||
"victory": {
|
||||
"1": "Aiyee!",
|
||||
"2": "H-h-how can this be?! How could this child...",
|
||||
"2_female": "H-h-how can this be?! How could this child...",
|
||||
"3": "This is why... This is why I can't bring myself to like children."
|
||||
}
|
||||
},
|
||||
@ -727,9 +730,12 @@
|
||||
"encounter": {
|
||||
"1": "We're not bad-we're just hard!",
|
||||
"2": "You want some? That's how we say hello! Nice knowing you, punks!",
|
||||
"2_female": "You want some? That's how we say hello! Nice knowing you, punks!",
|
||||
"3": "We're just a bunch of guys and gals with a great interest in other people's Pokémon!",
|
||||
"4": "Why you trying to act hard when we're already hard as bones out here, homie?",
|
||||
"5": "Team Skull represent! We can't pay the rent! Had a lot of fun, but our youth was misspent!"
|
||||
"4_female": "Why you trying to act hard when we're already hard as bones out here, homie?",
|
||||
"5": "Team Skull represent! We can't pay the rent! Had a lot of fun, but our youth was misspent!",
|
||||
"5_female": "Team Skull represent! We can't pay the rent! Had a lot of fun, but our youth was misspent!"
|
||||
},
|
||||
"victory": {
|
||||
"1": "Huh? Is it over already?",
|
||||
@ -742,11 +748,13 @@
|
||||
"plumeria": {
|
||||
"encounter": {
|
||||
"1": " ...Hmph. You don't look like anything special to me.",
|
||||
"1_female": " ...Hmph. You don't look like anything special to me.",
|
||||
"2": "It takes these dumb Grunts way too long to deal with you kids...",
|
||||
"3": "Mess with anyone in Team Skull, and I'll show you how serious I can get."
|
||||
},
|
||||
"victory": {
|
||||
"1": "Hmmph! You're pretty strong. I'll give you that.",
|
||||
"1_female": "Hmmph! You're pretty strong. I'll give you that.",
|
||||
"2": "Hmmph. Guess you are pretty tough. Now I understand why my Grunts waste so much time battling kids.",
|
||||
"3": "Hmmph! I guess I just have to hold that loss."
|
||||
}
|
||||
@ -755,6 +763,7 @@
|
||||
"encounter": {
|
||||
"1": "It looks like this is the end of the line for you!",
|
||||
"2": "You are a trainer aren't you? I'm afraid that doesn't give you the right to interfere in our work.",
|
||||
"2_female": "You are a trainer aren't you? I'm afraid that doesn't give you the right to interfere in our work.",
|
||||
"3": "I'm from Macro Cosmos Insurance! Do you have a life insurance policy?"
|
||||
},
|
||||
"victory": {
|
||||
@ -772,6 +781,7 @@
|
||||
"victory": {
|
||||
"1": "*sigh* I wasn't able to win... Oleana...you really are a hopeless woman.",
|
||||
"2": "Arghhh! This is inexcusable... What was I thinking... Any trainer who's made it this far would be no pushover..",
|
||||
"2_female": "Arghhh! This is inexcusable... What was I thinking... Any trainer who's made it this far would be no pushover..",
|
||||
"3": "*sigh* I am one tired Oleana..."
|
||||
}
|
||||
},
|
||||
|
@ -24,6 +24,7 @@
|
||||
"linkGoogle": "Link Google",
|
||||
"unlinkGoogle": "Unlink Google",
|
||||
"cancel": "Cancel",
|
||||
"donate": "Donate",
|
||||
"losingProgressionWarning": "You will lose any progress since the beginning of the battle. Proceed?",
|
||||
"noEggs": "You are not hatching\nany eggs at the moment!"
|
||||
}
|
@ -49,8 +49,8 @@
|
||||
"DoubleBattleChanceBoosterModifierType": {
|
||||
"description": "Doubles the chance of an encounter being a double battle for {{battleCount}} battles."
|
||||
},
|
||||
"TempBattleStatBoosterModifierType": {
|
||||
"description": "Increases the {{tempBattleStatName}} of all party members by 1 stage for 5 battles."
|
||||
"TempStatStageBoosterModifierType": {
|
||||
"description": "Increases the {{stat}} of all party members by 1 stage for 5 battles."
|
||||
},
|
||||
"AttackTypeBoosterModifierType": {
|
||||
"description": "Increases the power of a Pokémon's {{moveType}}-type moves by 20%."
|
||||
@ -61,8 +61,8 @@
|
||||
"AllPokemonLevelIncrementModifierType": {
|
||||
"description": "Increases all party members' level by {{levels}}."
|
||||
},
|
||||
"PokemonBaseStatBoosterModifierType": {
|
||||
"description": "Increases the holder's base {{statName}} by 10%. The higher your IVs, the higher the stack limit."
|
||||
"BaseStatBoosterModifierType": {
|
||||
"description": "Increases the holder's base {{stat}} by 10%. The higher your IVs, the higher the stack limit."
|
||||
},
|
||||
"AllPokemonFullHpRestoreModifierType": {
|
||||
"description": "Restores 100% HP for all Pokémon."
|
||||
@ -183,6 +183,7 @@
|
||||
"SOOTHE_BELL": { "name": "Soothe Bell" },
|
||||
|
||||
"SCOPE_LENS": { "name": "Scope Lens", "description": "It's a lens for scoping out weak points. It boosts the holder's critical-hit ratio."},
|
||||
"DIRE_HIT": { "name": "Dire Hit", "extra": { "raises": "Critical Hit Ratio" } },
|
||||
"LEEK": { "name": "Leek", "description": "This very long and stiff stalk of leek boosts the critical-hit ratio of Farfetch'd's moves."},
|
||||
|
||||
"EVIOLITE": { "name": "Eviolite", "description": "This mysterious evolutionary lump boosts the Defense and Sp. Def stats when held by a Pokémon that can still evolve." },
|
||||
@ -250,28 +251,14 @@
|
||||
"METAL_POWDER": { "name": "Metal Powder", "description": "Extremely fine yet hard, this odd powder boosts Ditto's Defense stat." },
|
||||
"QUICK_POWDER": { "name": "Quick Powder", "description": "Extremely fine yet hard, this odd powder boosts Ditto's Speed stat." }
|
||||
},
|
||||
"TempBattleStatBoosterItem": {
|
||||
"TempStatStageBoosterItem": {
|
||||
"x_attack": "X Attack",
|
||||
"x_defense": "X Defense",
|
||||
"x_sp_atk": "X Sp. Atk",
|
||||
"x_sp_def": "X Sp. Def",
|
||||
"x_speed": "X Speed",
|
||||
"x_accuracy": "X Accuracy",
|
||||
"dire_hit": "Dire Hit"
|
||||
"x_accuracy": "X Accuracy"
|
||||
},
|
||||
|
||||
"TempBattleStatBoosterStatName": {
|
||||
"ATK": "Attack",
|
||||
"DEF": "Defense",
|
||||
"SPATK": "Sp. Atk",
|
||||
"SPDEF": "Sp. Def",
|
||||
"SPD": "Speed",
|
||||
"ACC": "Accuracy",
|
||||
"CRIT": "Critical Hit Ratio",
|
||||
"EVA": "Evasiveness",
|
||||
"DEFAULT": "???"
|
||||
},
|
||||
|
||||
"AttackTypeBoosterItem": {
|
||||
"silk_scarf": "Silk Scarf",
|
||||
"black_belt": "Black Belt",
|
||||
|
@ -3,7 +3,7 @@
|
||||
"turnHealApply": "{{pokemonNameWithAffix}} restored a little HP using\nits {{typeName}}!",
|
||||
"hitHealApply": "{{pokemonNameWithAffix}} restored a little HP using\nits {{typeName}}!",
|
||||
"pokemonInstantReviveApply": "{{pokemonNameWithAffix}} was revived\nby its {{typeName}}!",
|
||||
"pokemonResetNegativeStatStageApply": "{{pokemonNameWithAffix}}'s lowered stats were restored\nby its {{typeName}}!",
|
||||
"resetNegativeStatStageApply": "{{pokemonNameWithAffix}}'s lowered stats were restored\nby its {{typeName}}!",
|
||||
"moneyInterestApply": "You received interest of ₽{{moneyAmount}}\nfrom the {{typeName}}!",
|
||||
"turnHeldItemTransferApply": "{{pokemonNameWithAffix}}'s {{itemName}} was absorbed\nby {{pokemonName}}'s {{typeName}}!",
|
||||
"contactHeldItemTransferApply": "{{pokemonNameWithAffix}}'s {{itemName}} was snatched\nby {{pokemonName}}'s {{typeName}}!",
|
||||
|
@ -3,6 +3,10 @@
|
||||
"cutHpPowerUpMove": "{{pokemonName}} cut its own HP to power up its move!",
|
||||
"absorbedElectricity": "{{pokemonName}} absorbed electricity!",
|
||||
"switchedStatChanges": "{{pokemonName}} switched stat changes with the target!",
|
||||
"switchedTwoStatChanges": "{{pokemonName}} switched all changes to its {{firstStat}}\nand {{secondStat}} with its target!",
|
||||
"switchedStat": "{{pokemonName}} switched {{stat}} with its target!",
|
||||
"sharedGuard": "{{pokemonName}} shared its guard with the target!",
|
||||
"sharedPower": "{{pokemonName}} shared its power with the target!",
|
||||
"goingAllOutForAttack": "{{pokemonName}} is going all out for this attack!",
|
||||
"regainedHealth": "{{pokemonName}} regained\nhealth!",
|
||||
"keptGoingAndCrashed": "{{pokemonName}} kept going\nand crashed!",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"Stat": {
|
||||
"HP": "Max. HP",
|
||||
"HPshortened": "MaxHP",
|
||||
"HPshortened": "HP",
|
||||
"ATK": "Attack",
|
||||
"ATKshortened": "Atk",
|
||||
"DEF": "Defense",
|
||||
@ -13,8 +13,7 @@
|
||||
"SPD": "Speed",
|
||||
"SPDshortened": "Spd",
|
||||
"ACC": "Accuracy",
|
||||
"EVA": "Evasiveness",
|
||||
"HPStat": "HP"
|
||||
"EVA": "Evasiveness"
|
||||
},
|
||||
"Type": {
|
||||
"UNKNOWN": "Unknown",
|
||||
@ -38,4 +37,4 @@
|
||||
"FAIRY": "Fairy",
|
||||
"STELLAR": "Stellar"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,7 @@
|
||||
"name": "Campeón Liga Master",
|
||||
"name_female": "Campeona Liga Master"
|
||||
},
|
||||
"TRANSFER_MAX_BATTLE_STAT": {
|
||||
"TRANSFER_MAX_STAT_STAGE": {
|
||||
"name": "Trabajo en Equipo",
|
||||
"description": "Haz relevo a otro miembro del equipo con al menos una estadística al máximo."
|
||||
},
|
||||
@ -175,4 +175,4 @@
|
||||
"name": "Espejo ojepsE",
|
||||
"description": "Completa el reto de Combate Inverso.\n.osrevnI etabmoC ed oter le atelpmoC"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,8 +49,8 @@
|
||||
"DoubleBattleChanceBoosterModifierType": {
|
||||
"description": "Duplica la posibilidad de que un encuentro sea una combate doble durante {{battleCount}} combates."
|
||||
},
|
||||
"TempBattleStatBoosterModifierType": {
|
||||
"description": "Aumenta la est. {{tempBattleStatName}} de todos los miembros del equipo en 1 nivel durante 5 combates."
|
||||
"TempStatStageBoosterModifierType": {
|
||||
"description": "Aumenta la est. {{stat}} de todos los miembros del equipo en 1 nivel durante 5 combates."
|
||||
},
|
||||
"AttackTypeBoosterModifierType": {
|
||||
"description": "Aumenta la potencia de los movimientos de tipo {{moveType}} de un Pokémon en un 20%."
|
||||
@ -61,8 +61,8 @@
|
||||
"AllPokemonLevelIncrementModifierType": {
|
||||
"description": "Aumenta el nivel de todos los miembros del equipo en {{levels}}."
|
||||
},
|
||||
"PokemonBaseStatBoosterModifierType": {
|
||||
"description": "Aumenta la est. {{statName}} base del portador en un 10%.\nCuanto mayores sean tus IVs, mayor será el límite de acumulación."
|
||||
"BaseStatBoosterModifierType": {
|
||||
"description": "Aumenta la est. {{stat}} base del portador en un 10%.\nCuanto mayores sean tus IVs, mayor será el límite de acumulación."
|
||||
},
|
||||
"AllPokemonFullHpRestoreModifierType": {
|
||||
"description": "Restaura el 100% de los PS de todos los Pokémon."
|
||||
@ -248,6 +248,12 @@
|
||||
"name": "Periscopio",
|
||||
"description": "Aumenta la probabilidad de asestar un golpe crítico."
|
||||
},
|
||||
"DIRE_HIT": {
|
||||
"name": "Crítico X",
|
||||
"extra": {
|
||||
"raises": "Critical Hit Ratio"
|
||||
}
|
||||
},
|
||||
"LEEK": {
|
||||
"name": "Puerro",
|
||||
"description": "Puerro muy largo y duro que aumenta la probabilidad de asestar un golpe crítico. Debe llevarlo Farfetch'd."
|
||||
@ -411,25 +417,13 @@
|
||||
"description": "Polvo muy fino, pero a la vez poderoso, que aumenta la Velocidad. Debe llevarlo Ditto."
|
||||
}
|
||||
},
|
||||
"TempBattleStatBoosterItem": {
|
||||
"TempStatStageBoosterItem": {
|
||||
"x_attack": "Ataque X",
|
||||
"x_defense": "Defensa X",
|
||||
"x_sp_atk": "Ataq. Esp. X",
|
||||
"x_sp_def": "Def. Esp. X",
|
||||
"x_speed": "Velocidad X",
|
||||
"x_accuracy": "Precisión X",
|
||||
"dire_hit": "Crítico X"
|
||||
},
|
||||
"TempBattleStatBoosterStatName": {
|
||||
"ATK": "Ataque",
|
||||
"DEF": "Defensa",
|
||||
"SPATK": "Ataq. Esp.",
|
||||
"SPDEF": "Def. Esp.",
|
||||
"SPD": "Velocidad",
|
||||
"ACC": "Precisión",
|
||||
"CRIT": "Tasa de crítico",
|
||||
"EVA": "Evasión",
|
||||
"DEFAULT": "???"
|
||||
"x_accuracy": "Precisión X"
|
||||
},
|
||||
"AttackTypeBoosterItem": {
|
||||
"silk_scarf": "Pañuelo seda",
|
||||
|
@ -1,4 +1,8 @@
|
||||
{
|
||||
"switchedTwoStatChanges": "{{pokemonName}} ha intercambiado los cambios en {{firstStat}} y {{secondStat}} con los del objetivo!",
|
||||
"switchedStat": "{{pokemonName}} cambia su {{stat}} por la de su objetivo!",
|
||||
"sharedGuard": "{{pokemonName}} suma su capacidad defensiva a la del objetivo y la reparte equitativamente!",
|
||||
"sharedPower": "{{pokemonName}} suma su capacidad ofensiva a la del objetivo y la reparte equitativamente!",
|
||||
"isChargingPower": "¡{{pokemonName}} está acumulando energía!",
|
||||
"burnedItselfOut": "¡El fuego interior de {{pokemonName}} se ha extinguido!",
|
||||
"startedHeatingUpBeak": "¡{{pokemonName}} empieza\na calentar su pico!",
|
||||
@ -9,4 +13,4 @@
|
||||
"statEliminated": "¡Los cambios en estadísticas fueron eliminados!",
|
||||
"revivalBlessing": "¡{{pokemonName}} ha revivido!",
|
||||
"safeguard": "¡{{targetName}} está protegido por Velo Sagrado!"
|
||||
}
|
||||
}
|
||||
|
@ -10,5 +10,5 @@
|
||||
"eternamaxChange": "¡{{preName}} ha eternamaxizado a {{pokemonName}}!",
|
||||
"revertChange": "¡{{pokemonName}} ha revertido a su forma original!",
|
||||
"formChange": "¡{{preName}} ha cambiado de forma!",
|
||||
"disguiseChange": "¡El disfraz ha actuado como señuelo!\t"
|
||||
"disguiseChange": "¡El disfraz ha actuado como señuelo!"
|
||||
}
|
||||
|
@ -92,7 +92,7 @@
|
||||
"name": "Master Maitre de la Ligue",
|
||||
"name_female": "Master Maitresse de la Ligue"
|
||||
},
|
||||
"TRANSFER_MAX_BATTLE_STAT": {
|
||||
"TRANSFER_MAX_STAT_STAGE": {
|
||||
"name": "Travail d’équipe",
|
||||
"description": "Utiliser Relais avec au moins une statistique montée à fond."
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"ending": "@c{smile}Oh ? T’as gagné ?@d{96} @c{smile_eclosed}J’aurais dû le savoir.\nMais de voilà de retour.\n$@c{smile}C’est terminé.@d{64} T’as brisé ce cycle infernal.\n$@c{serious_smile_fists}T’as aussi accompli ton rêve non ?\nTu n’as pas connu la moindre défaite.\n$@c{neutral}Je suis le seul à me souvenir de ce que t’as fait.@d{96}\nJe pense que ça ira, non ?\n$@c{serious_smile_fists}Ta légende vivra à jamais dans nos cœurs.\n$@c{smile_eclosed}Bref, j’en ai un peu marre de ce endroit, pas toi ? Rentrons à la maison.\n$@c{serious_smile_fists}On se fera un p’tit combat une fois rentrés ?\nSi t’es d’accord.",
|
||||
"ending_female": "@c{shock}T’es revenu ?@d{32} Ça veut dire…@d{96} que t’as gagné ?!\n@c{smile_ehalf}J’aurais dû le savoir.\n$@c{smile_eclosed}Bien sûr… J’ai toujours eu ce sentiment.\n@c{smile}C’est fini maitenant hein ? T’as brisé ce cycle.\n$@c{smile_ehalf}T’as aussi accompli ton rêve non ?\nTu n’as pas connu la moindre défaite.\n$Je serai la seule à me souvenir de ce que t’as fait.\n@c{angry_mopen}Je tâcherai de ne pas oublier !\n$@c{smile_wave_wink}J’déconne !@d{64} @c{smile}Jamais j’oublierai.@d{32}\nTa légende vivra à jamais dans nos cœurs.\n$@c{smile_wave}Bon,@d{64} il se fait tard…@d{96} je crois ?\nDifficile à dire ici.\n$Rentrons, @c{smile_wave_wink}et demain on se fera un p’tit combat, comme au bon vieux temps ?",
|
||||
"ending": "@c{shock}T’es revenu ?@d{32} Ça veut dire…@d{96} que t’as gagné ?!\n@c{smile_ehalf}J’aurais dû m’en douter.\n$@c{smile_eclosed}Bien sûr… J’ai toujours eu ce sentiment.\n@c{smile}C’est fini maintenant hein ? T’as brisé ce cycle.\n$@c{smile_ehalf}T’as aussi accompli ton rêve non ?\nTu n’as pas connu la moindre défaite.\n$Je serai la seule à me souvenir de ce que t’as fait.\n@c{angry_mopen}Je tâcherai de ne pas oublier !\n$@c{smile_wave_wink}J’déconne !@d{64} @c{smile}Jamais j’oublierai.@d{32}\nTa légende vivra à jamais dans nos cœurs.\n$@c{smile_wave}Bon,@d{64} il se fait tard…@d{96} je crois ?\nDifficile à dire ici.\n$Rentrons, @c{smile_wave_wink}et demain on se fera un p’tit combat, comme au bon vieux temps ?",
|
||||
"ending_female": "@c{smile}Oh ? T’as gagné ?@d{96} @c{smile_eclosed}J’aurais dû m’en douter.\nMais te voilà enfin de retour.\n$@c{smile}C’est terminé.@d{64} T’as brisé ce cycle infernal.\n$@c{serious_smile_fists}T’as aussi accompli ton rêve non ?\nTu n’as pas connu la moindre défaite.\n$@c{neutral}Je suis le seul à me souvenir de ce que t’as fait.@d{96}\nJe pense que ça ira, non ?\n$@c{serious_smile_fists}Ta légende vivra à jamais dans nos cœurs.\n$@c{smile_eclosed}Bref, j’en ai un peu marre de ce endroit, pas toi ? Rentrons à la maison.\n$@c{serious_smile_fists}On se fera un p’tit combat une fois rentrés ?\nSi t’es d’accord.",
|
||||
"ending_endless": "Félicitations ! Vous avez atteint la fin actuelle.\nPlus de contenu à venir bientôt !",
|
||||
"ending_name": "Les devs"
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
"6": "Allez, c’est parti !",
|
||||
"7": "Attention, me voilà !\nTu vas voir comment j’suis fort !",
|
||||
"8": "Coucou… Tu veux voir mes bô Pokémon ?",
|
||||
"9": "Trève de mondanités. Ramène-toi quand tu le sens !",
|
||||
"9": "Trêve de mondanités. Ramène-toi quand tu le sens !",
|
||||
"10": "Baisse pas ta garde si tu veux pas pleurer d’avoir perdu face à un gamin.",
|
||||
"11": "J’ai tout donné pour élever mes Pokémon. Attention à toi si tu leur fait du mal !",
|
||||
"12": "Incroyable que t’y sois parvenu ! Mais la suite va pas être une partie de plaisir.",
|
||||
@ -68,7 +68,7 @@
|
||||
"3": "Hum, t’es pas trop laxiste avec tes Pokémon ?\nTrop les chouchouter n’est pas bon."
|
||||
},
|
||||
"victory": {
|
||||
"1": "Il est primordial de nourir et développer toutes les caractéristiques de chaque Pokémon.",
|
||||
"1": "Il est primordial de nourrir et développer toutes les caractéristiques de chaque Pokémon.",
|
||||
"2": "Contrairement à moi, ces Pokémon ont un bon fond.",
|
||||
"3": "Trop d’éloges peut ruiner les Pokémon et les gens."
|
||||
},
|
||||
@ -229,7 +229,7 @@
|
||||
"encounter": {
|
||||
"1": "Ne te mets pas en travers de la Team Galaxie !",
|
||||
"2": "Sois témoin de la puissance de notre technologie et du futur qui se profile !",
|
||||
"3": "Au nom de la Team Galaxie, j’éliminerai quiconque se mettera sur notre route !",
|
||||
"3": "Au nom de la Team Galaxie, j’éliminerai quiconque se mettra sur notre route !",
|
||||
"4": "Prépare ta défaite !",
|
||||
"5": "J’espère que t’es prêt à te prendre une raclée de l’espace !",
|
||||
"5_female": "J’espère que t’es prête à te prendre une raclée de l’espace !"
|
||||
@ -244,7 +244,7 @@
|
||||
},
|
||||
"plasma_grunt": {
|
||||
"encounter": {
|
||||
"1": "Pas de quatiers à ceux qui ne suivent pas notre idéal !",
|
||||
"1": "Pas de quartiers à quiconque ne suit pas notre idéal !",
|
||||
"2": "Si je gagne, tu relâches tous tes Pokémon !",
|
||||
"3": "Si tu te mets en travers de la Team Plasma, je m’occuperai de toi personnellement !",
|
||||
"4": "La Team Plasma va libérer les Pokémon de tous les humains égoïstes dans ton genre !",
|
||||
@ -275,6 +275,96 @@
|
||||
"5": "J’appelle pas ça perdre, j’appelle ça échouer avec panache !"
|
||||
}
|
||||
},
|
||||
"aether_grunt": {
|
||||
"encounter": {
|
||||
"1": "Je vais te mettre ta raclée !",
|
||||
"2": "J’en ai rien à faire que tu sois une gosse. Tu vas tutoyer les étoiles si tu nous menaces !",
|
||||
"2_female": "J’en ai rien à faire que tu sois une gosse. Tu vas tutoyer les étoiles si tu nous menaces !",
|
||||
"3": "J’ai pour ordre de ne laisser passer aucun Dresseur, peu importe qui c’est !",
|
||||
"4": "Je vais te montrer le pouvoir du Paradis Æther !",
|
||||
"5": "Maintenant que t’es au courant de ce qu’il se passe au cœur du Paradis Æther, fais-moi une faveur et disparait !"
|
||||
},
|
||||
"victory": {
|
||||
"1": "C’est plutôt toi qui devrait m’apprendre à en mettre…",
|
||||
"2": "Pardon ? J’ai pas compris…",
|
||||
"3": "Peu importe les ordres, jamais j’aurais pu te retenir en fait…",
|
||||
"4": "Mhh… Il semblerait que j’ai perdu.",
|
||||
"5": "C’est plutôt moi qui va disparaitre je crois."
|
||||
}
|
||||
},
|
||||
"faba": {
|
||||
"encounter": {
|
||||
"1": "Moi, Directeur Saubohne, je vais te montrer de quel bois je me chauffe !",
|
||||
"2": "Donc là, l’homme supposé être la dernière ligne défense du Paradis Æther doit affronter un mioche ?",
|
||||
"2_female": "Donc là, l’homme supposé être la dernière ligne défense du Paradis Æther doit affronter un mioche ?",
|
||||
"3": "S’il n’y a qu’un seul nom à retenir au sein de la Fondation Æther, c’est le mien : Saubohne !"
|
||||
},
|
||||
"victory": {
|
||||
"1": "Gloups !",
|
||||
"2": "Malheur ! J’ai perdu face à un simple enfant ?!",
|
||||
"2_female": "Malheur ! J’ai perdu face à une simple enfant ?!",
|
||||
"3": "J’ai HORREUR des enfants !"
|
||||
}
|
||||
},
|
||||
"skull_grunt": {
|
||||
"encounter": {
|
||||
"1": "Oush oush ! On est pas méchants, sauf si tu viens nous allumer la mèche-han !",
|
||||
"2": "Ce manque de respect, j’hallucine ! T’es allé trop loin, le mioche !",
|
||||
"2_female": "Ce manque de respect, j’hallucine ! T’es allée trop loin, la mioche !",
|
||||
"3": "On est juste des gars et des meufs normaux, on voit un Pokémon on le prend !",
|
||||
"4": "Pourquoi tu te la joue comme ça ? C'est avec tes dents que t’vas jouer frérot.",
|
||||
"4_female": "Pourquoi tu te la joue comme ça ? C'est avec tes dents que t’vas jouer ma reus.",
|
||||
"5": "Cousin, écoute-nous bien ! ♪\nSe taper dessus, ça sert à rien ! ♪\n$Tu t’incrustes chez nous, ça s’fait pas ! ♪\n$Mais on est sympa, on a un plan pour toi ! ♪",
|
||||
"5_female": "Cousine, écoute-nous bien ! ♪\nSe taper dessus, ça sert à rien ! ♪\n$Tu t’incrustes chez nous, ça s’fait pas ! ♪\n$Mais on est sympa, on a un plan pour toi ! ♪"
|
||||
},
|
||||
"victory": {
|
||||
"1": "Hein ? C’est déjà terminé ?",
|
||||
"2": "… Ça craint grave ! On s’tire !",
|
||||
"3": "Ouais de toute on en avait pas b’soin de ton Pokémon… Ah ah…",
|
||||
"4": "Ouh là, c’est bon, j’en demandais pas tant…",
|
||||
"5": "On pèse plus que des Pokémon, t’entends ?\nAlors tu vas nous respecter, oush !"
|
||||
}
|
||||
},
|
||||
"plumeria": {
|
||||
"encounter": {
|
||||
"1": "Tsk. T’es un gamin tout ce qu’il y a de plus banal, en fait.",
|
||||
"1_female": "Tsk. T’es une gamine tout ce qu’il y a de plus banal, en fait.",
|
||||
"2": "Abrutis de sbires. Trop incompétents pour arriver à se débarasser de gamins…",
|
||||
"3": "Si tu touches encore à un cheveu de mes lascars, tu vas pas comprendre c’qui t’arrive !"
|
||||
},
|
||||
"victory": {
|
||||
"1": "Tsk. T’es pas mauvais. J’te l’accorde.",
|
||||
"1_female": "Tsk. T’es pas mauvaise. J’te l’accorde.",
|
||||
"2": "Tsk. J’dois reconnaitre que t’en as dans le ventre.\n$Maintenant, j’comprends pourquoi mes gars n’arrêtent pas de se faire battre par toi.",
|
||||
"3": "Tsk. J’crois que j'ai plus qu’à assumer ma défaite."
|
||||
}
|
||||
},
|
||||
"macro_grunt": {
|
||||
"encounter": {
|
||||
"1": "Hop hop hop ! Terminus !",
|
||||
"2": "T’es un Dresseur n’est-ce pas ?\n$J’ai bien peur ce que ne soit pas une excuse suffisante pour nous interrompre dans notre travail.",
|
||||
"2_female": "T’es une Dresseuse n’est-ce pas ?\n$J’ai bien peur ce que ne soit pas une excuse suffisante pour nous interrompre dans notre travail.",
|
||||
"3": "Je travaille à Macro Cosmos Assurances !\nBesoin d’une assurance-vie ?"
|
||||
},
|
||||
"victory": {
|
||||
"1": "Je n’ai d’autre choix que respectueusement me retirer.",
|
||||
"2": "Mon argent de poche…\nPlus qu’à manger des pâtes pour la fin du mois…",
|
||||
"3": "Chez Macro Cosmos, rien n’est comparable à notre dévotion au travail !"
|
||||
}
|
||||
},
|
||||
"oleana": {
|
||||
"encounter": {
|
||||
"1": "Je ne laisserai personne interférer avec les projets du président Shehroz.",
|
||||
"2": "Je vois que vous avez su vous défaire de mes subalternes.\n$Mais assez joué. Il est temps de rentrer chez vous, maintenant.",
|
||||
"3": "Je gagnerai en votre nom, monsieur le président."
|
||||
},
|
||||
"victory": {
|
||||
"1": "*soupir* Comment ai-je fait pour perdre ainsi… ?\nJe ne suis vraiment pas à la hauteur…",
|
||||
"2": "Ah ! Quelle erreur… Je n’aurais pas dû sous-estimer un Dresseur de ton calibre…",
|
||||
"2_female": "Ah ! Quelle erreur… Je n’aurais pas dû sous-estimer une Dresseuse de ton calibre…",
|
||||
"3": "*soupir* Je suis fatiguée parton…"
|
||||
}
|
||||
},
|
||||
"rocket_boss_giovanni_1": {
|
||||
"encounter": {
|
||||
"1": "Bien. Je dois admettre que je suis impressionné de te voir ici !"
|
||||
@ -468,7 +558,7 @@
|
||||
"4": "Voir un tel jardin rempli de fleurs est si apaisant…"
|
||||
},
|
||||
"victory": {
|
||||
"1": "Bien joué, c’est mértié.",
|
||||
"1": "Bien joué, c’est mérité.",
|
||||
"2": "Dommage, on s’amusait si bien…",
|
||||
"3": "Oh non, le combat est terminé…",
|
||||
"4": "Aaah, ça fait du bien !\nMerci, j’en avais besoin."
|
||||
@ -505,15 +595,15 @@
|
||||
},
|
||||
"rival": {
|
||||
"encounter": {
|
||||
"1": "@c{smile}Ah, je te cherchais ! Je savais que t’étais pressé de partir, mais je m’attendais quand même à un au revoir…\n$@c{smile_eclosed}T’as finalement décidé de réaliser ton rêve ?\nJ’ai peine à y croire.\n$@c{serious_smile_fists}Vu que t’es là, ça te dis un petit combat ?\nJe voudrais quand même m’assurer que t’es prêt.\n$@c{serious_mopen_fists}Surtout ne te retiens pas et donne-moi tout ce que t’as !"
|
||||
"1": "@c{smile}Ah, je te cherchais ! Je savais que t’étais pressée de partir, mais je m’attendais quand même à un au revoir…\n$@c{smile_eclosed}T’as finalement décidé de réaliser ton rêve ?\nJ’ai peine à y croire.\n$@c{serious_smile_fists}Vu que t’es là, ça te dis un petit combat ?\nJe voudrais quand même m’assurer que t’es prête.\n$@c{serious_mopen_fists}Surtout ne te retiens pas et donne-moi tout ce que t’as !"
|
||||
},
|
||||
"victory": {
|
||||
"1": "@c{shock}Wah… Tu m’as vraiment lavé.\nT’es vraiment un débutant ?\n$@c{smile}T’as peut-être eu de la chance, mais…\nPeut-être que t’arriveras jusqu’au bout du chemin.\n$D’ailleurs, le prof m’a demandé de te filer ces objets.\nIls ont l’air sympas.\n$@c{serious_smile_fists}Bonne chance à toi !"
|
||||
"1": "@c{shock}Wah… Tu m’as vraiment lavé.\nT’es vraiment une débutante ?\n$@c{smile}T’as peut-être eu de la chance, mais…\nPeut-être que t’arriveras jusqu’au bout du chemin.\n$D’ailleurs, le prof m’a demandé de te filer ces objets.\nIls ont l’air sympas.\n$@c{serious_smile_fists}Bonne chance à toi !"
|
||||
}
|
||||
},
|
||||
"rival_female": {
|
||||
"encounter": {
|
||||
"1": "@c{smile_wave}Ah, te voilà ! Je t’ai cherché partout !\n@c{angry_mopen}On oublie de dire au revoir à sa meilleure amie ?\n$@c{smile_ehalf}T’as décidé de réaliser ton rêve, hein ?\nCe jour est donc vraiment arrivé…\n$@c{smile}Je veux bien te pardonner de m’avoir oubliée,\nà une conditon. @c{smile_wave_wink}Que tu m’affronte !\n$@c{angry_mopen}Donne tout ! Ce serait dommage que ton aventure finisse avant d’avoir commencé, hein ?"
|
||||
"1": "@c{smile_wave}Ah, te voilà ! Je t’ai cherché partout !\n@c{angry_mopen}On oublie de dire au revoir à sa meilleure amie ?\n$@c{smile_ehalf}T’as décidé de réaliser ton rêve, hein ?\nCe jour est donc vraiment arrivé…\n$@c{smile}Je veux bien te pardonner de m’avoir oubliée,\nà une condition. @c{smile_wave_wink}Que tu m’affronte !\n$@c{angry_mopen}Donne tout ! Ce serait dommage que ton aventure finisse avant d’avoir commencé, hein ?"
|
||||
},
|
||||
"victory": {
|
||||
"1": "@c{shock}Tu viens de commencer et t’es déjà si fort ?!@d{96}\n@c{angry}T’as triché non ? Avoue !\n$@c{smile_wave_wink}J’déconne !@d{64} @c{smile_eclosed}J’ai perdu dans les règles…\nJ’ai le sentiment que tu vas très bien t’en sortir.\n$@c{smile}D’ailleurs, le prof veut que je te donne ces quelques objets. Ils te seront utiles, pour sûr !\n$@c{smile_wave}Fais de ton mieux, comme toujours !\nJe crois fort en toi !"
|
||||
@ -521,10 +611,10 @@
|
||||
},
|
||||
"rival_2": {
|
||||
"encounter": {
|
||||
"1": "@c{smile}Hé, toi aussi t’es là ?\n@c{smile_eclosed}Toujours invaincu, hein… ?\n$@c{serious_mopen_fists}Je sais que j’ai l’air de t’avoir suivi ici, mais c’est pas complètement vrai.\n$@c{serious_smile_fists}Pour être honnête, ça me démangeait d’avoir une revanche depuis que tu m’as battu.\n$Je me suis beaucoup entrainé, alors sois sure que je vais pas retenir mes coups cette fois.\n$@c{serious_mopen_fists}Et comme la dernière fois, ne te retiens pas !\nC’est parti !"
|
||||
"1": "@c{smile}Hé, toi aussi t’es là ?\n@c{smile_eclosed}Toujours invaincue, hein… ?\n$@c{serious_mopen_fists}Je sais que j’ai l’air de t’avoir suivie ici, mais c’est pas complètement vrai.\n$@c{serious_smile_fists}Pour être honnête, ça me démangeait d’avoir une revanche depuis que tu m’as battu.\n$Je me suis beaucoup entrainé, alors sois sure que je vais pas retenir mes coups cette fois.\n$@c{serious_mopen_fists}Et comme la dernière fois, ne te retiens pas !\nC’est parti !"
|
||||
},
|
||||
"victory": {
|
||||
"1": "@c{neutral_eclosed}Oh. Je crois que j’ai trop pris la confiance.\n$@c{smile}Pas grave, c’est OK. Je me doutais que ça arriverait.\n@c{serious_mopen_fists}Je vais juste devoir encore plus m’entrainer !\n\n$@c{smile}Ah, et pas que t’aies réellement besoin d’aide, mais j’ai ça en trop sur moi qui pourrait t’intéresser.\n\n$@c{serious_smile_fists}Mais n’espère plus en avoir d’autres !\nJe peux pas passer mon temps à aider mon adversaire.\n$@c{smile}Bref, prends soin de toi et profite bien de l’évènement !"
|
||||
"1": "@c{neutral_eclosed}Oh. Je crois que j’ai trop pris la confiance.\n$@c{smile}Pas grave, c’est OK. Je me doutais que ça arriverait.\n@c{serious_mopen_fists}Je vais juste devoir encore plus m’entrainer !\n\n$@c{smile}Ah, et pas que t’aies réellement besoin d’aide, mais j’ai ça en trop sur moi qui pourrait t’intéresser.\n\n$@c{serious_smile_fists}Mais n’espère plus en avoir d’autres !\nJe peux pas passer mon temps à aider mon adversaire.\n$@c{smile}Bref, prends soin de toi !"
|
||||
}
|
||||
},
|
||||
"rival_2_female": {
|
||||
@ -532,7 +622,7 @@
|
||||
"1": "@c{smile_wave}Hé, sympa de te croiser ici. T’as toujours l’air invaincu. @c{angry_mopen}Eh… Pas mal !\n$@c{angry_mopen}Je sais à quoi tu penses et non, je t’espionne pas.\n@c{smile_eclosed}C’est juste que j’étais aussi dans le coin.\n$@c{smile_ehalf}Heureuse pour toi, mais je veux juste te rappeler que c’est pas grave de perdre parfois.\n$@c{smile}On apprend de nos erreurs, souvent plus que si on ne connaissait que le succès.\n$@c{angry_mopen}Dans tous les cas je me suis bien entrainée pour cette revanche, t’as intérêt à tout donner !"
|
||||
},
|
||||
"victory": {
|
||||
"1": "@c{neutral}Je… J’étais pas encore supposée perdre…\n$@c{smile}Bon. Ça veut juste dire que je vais devoir encore plus m’entrainer !\n$@c{smile_wave}J’ai aussi ça en rab pour toi !\n@c{smile_wave_wink}Inutile de me remercier ~.\n$@c{angry_mopen}C’étaient les derniers, terminé les cadeaux après ceux-là !\n$@c{smile_wave}Allez, tiens le coup et profite bien de l’évènement !"
|
||||
"1": "@c{neutral}Je… J’étais pas encore supposée perdre…\n$@c{smile}Bon. Ça veut juste dire que je vais devoir encore plus m’entrainer !\n$@c{smile_wave}J’ai aussi ça en rab pour toi !\n@c{smile_wave_wink}Inutile de me remercier ~.\n$@c{angry_mopen}C’étaient les derniers, terminé les cadeaux après ceux-là !\n$@c{smile_wave}Allez, tiens le coup !"
|
||||
},
|
||||
"defeat": {
|
||||
"1": "Je suppose que c’est parfois normal de perdre…"
|
||||
@ -540,7 +630,7 @@
|
||||
},
|
||||
"rival_3": {
|
||||
"encounter": {
|
||||
"1": "@c{smile}Hé, mais qui voilà ! Ça fait un bail.\n@c{neutral}T’es… toujours invaincu ? Incroyable.\n$@c{neutral_eclosed}Tout est devenu un peu… étrange.\nC’est plus pareil sans toi au village.\n$@c{serious}Je sais que c’est égoïste, mais j’ai besoin d’expier ça.\n@c{neutral_eclosed}Je crois que tout ça te dépasse.\n$@c{serious}Ne jamais perdre, c’est juste irréaliste.\nGrandir, c’est parfois aussi savoir perdre.\n$@c{neutral_eclosed}T’as un beau parcours, mais il y a encore tellement à venir et ça va pas s’arranger. @c{neutral}T’es prêt pour ça ?\n$@c{serious_mopen_fists}Si tu l’es, alors prouve-le."
|
||||
"1": "@c{smile}Hé, mais qui voilà ! Ça fait un bail.\n@c{neutral}T’es… toujours invaincue ? Incroyable.\n$@c{neutral_eclosed}Tout est devenu un peu… étrange.\nC’est plus pareil sans toi au village.\n$@c{serious}Je sais que c’est égoïste, mais j’ai besoin d’expier ça.\n@c{neutral_eclosed}Je crois que tout ça te dépasse.\n$@c{serious}Ne jamais perdre, c’est juste irréaliste.\nGrandir, c’est parfois aussi savoir perdre.\n$@c{neutral_eclosed}T’as un beau parcours, mais il y a encore tellement à venir et ça va pas s’arranger. @c{neutral}T’es prête pour ça ?\n$@c{serious_mopen_fists}Si tu l’es, alors prouve-le."
|
||||
},
|
||||
"victory": {
|
||||
"1": "@c{angry_mhalf}C’est lunaire… J’ai presque fait que m’entrainer…\nAlors pourquoi il y a encore un tel écart entre nous ?"
|
||||
@ -559,7 +649,7 @@
|
||||
},
|
||||
"rival_4": {
|
||||
"encounter": {
|
||||
"1": "@c{neutral}Hé.\n$Je vais pas y aller par quatre chemins avec toi.\n@c{neutral_eclosed}Je suis là pour gagner. Simple, basique.\n$@c{serious_mhalf_fists}J’ai appris à maximiser tout mon potentiel en m’entrainant d’arrachepied.\n$@c{smile}C’est fou tout le temps que tu peux te dégager si tu dors pas en sacrifiant ta vie sociale.\n$@c{serious_mopen_fists}Plus rien n’a d’importance désormais, pas tant que j’aurai pas gagné.\n$@c{neutral_eclosed}J’ai atteint un stade où je ne peux plus perdre.\n@c{smile_eclosed}Je présume que ta philosophie était pas si fausse finalement.\n$@c{angry_mhalf}La défaite, c’est pour les faibles, et je ne suis plus un faible.\n$@c{serious_mopen_fists}Tiens-toi prêt."
|
||||
"1": "@c{neutral}Hé.\n$Je vais pas y aller par quatre chemins avec toi.\n@c{neutral_eclosed}Je suis là pour gagner. Simple, basique.\n$@c{serious_mhalf_fists}J’ai appris à maximiser tout mon potentiel en m’entrainant d’arrachepied.\n$@c{smile}C’est fou tout le temps que tu peux te dégager si tu dors pas en sacrifiant ta vie sociale.\n$@c{serious_mopen_fists}Plus rien n’a d’importance désormais, pas tant que j’aurai pas gagné.\n$@c{neutral_eclosed}J’ai atteint un stade où je ne peux plus perdre.\n@c{smile_eclosed}Je présume que ta philosophie était pas si fausse finalement.\n$@c{angry_mhalf}La défaite, c’est pour les faibles, et je ne suis plus un faible.\n$@c{serious_mopen_fists}Tiens-toi prête."
|
||||
},
|
||||
"victory": {
|
||||
"1": "@c{neutral}Que…@d{64} Qui es-tu ?"
|
||||
@ -597,7 +687,7 @@
|
||||
},
|
||||
"rival_6": {
|
||||
"encounter": {
|
||||
"1": "@c{smile_eclosed}Nous y revoilà.\n$@c{neutral}J’ai eu du temps pour réfléchir à tout ça.\nIl y a une raison à pourquoi tout semble étrange.\n$@c{neutral_eclosed}Ton rêve, ma volonté de te battre…\nFont partie de quelque chose de plus grand.\n$@c{serious}C’est même pas à propos de moi, ni de toi… Mais du monde, @c{serious_mhalf_fists}et te repousser dans tes limites est ma mission.\n$@c{neutral_eclosed}J’ignore si je serai capable de l’accomplir, mais je ferai tout ce qui est en mon pouvoir.\n$@c{neutral}Cet endroit est terrifiant… Et pourtant il m’a l’air familier, comme si j’y avais déjà mis les pieds.\n$@c{serious_mhalf_fists}Tu ressens la même chose, pas vrai ?\n$@c{serious}… et c’est comme si quelque chose ici me parlait.\n$Comme si c’était tout ce que ce monde avait toujours connu.\n$Ces précieux moments ensemble semblent si proches ne sont rien de plus qu’un lointain souvenir.\n$@c{neutral_eclosed}D’ailleurs, qui peut dire aujourd’hui qu’ils ont pu être réels ?\n$@c{serious_mopen_fists}Il faut que tu persévères. Si tu t’arrêtes, ça n’aura jamais de fin et t’es le seul à en être capable.\n$@c{serious_smile_fists}Difficile de comprendre le sens de tout ça, je sais juste que c’est la réalité.\n$@c{serious_mopen_fists}Si tu ne parviens pas à me battre ici et maintenant, tu n’as aucune chance."
|
||||
"1": "@c{smile_eclosed}Nous y revoilà.\n$@c{neutral}J’ai eu du temps pour réfléchir à tout ça.\nIl y a une raison à pourquoi tout semble étrange.\n$@c{neutral_eclosed}Ton rêve, ma volonté de te battre…\nFont partie de quelque chose de plus grand.\n$@c{serious}C’est même pas à propos de moi, ni de toi… Mais du monde, @c{serious_mhalf_fists}et te repousser dans tes limites est ma mission.\n$@c{neutral_eclosed}J’ignore si je serai capable de l’accomplir, mais je ferai tout ce qui est en mon pouvoir.\n$@c{neutral}Cet endroit est terrifiant… Et pourtant il m’a l’air familier, comme si j’y avais déjà mis les pieds.\n$@c{serious_mhalf_fists}Tu ressens la même chose, pas vrai ?\n$@c{serious}… et c’est comme si quelque chose ici me parlait.\n$Comme si c’était tout ce que ce monde avait toujours connu.\n$Ces précieux moments ensemble semblent si proches ne sont rien de plus qu’un lointain souvenir.\n$@c{neutral_eclosed}D’ailleurs, qui peut dire aujourd’hui qu’ils ont pu être réels ?\n$@c{serious_mopen_fists}Il faut que tu persévères. Si tu t’arrêtes, ça n’aura jamais de fin et t’es la seule à en être capable.\n$@c{serious_smile_fists}Difficile de comprendre le sens de tout ça, je sais juste que c’est la réalité.\n$@c{serious_mopen_fists}Si tu ne parviens pas à me battre ici et maintenant, tu n’as aucune chance."
|
||||
},
|
||||
"victory": {
|
||||
"1": "@c{smile_eclosed}J’ai fait ce que j’avais à faire.\n$Promets-moi juste une chose.\n@c{smile}Après avoir réparé ce monde… Rentre à la maison."
|
||||
|
@ -49,8 +49,8 @@
|
||||
"DoubleBattleChanceBoosterModifierType": {
|
||||
"description": "Double les chances de tomber sur un combat double pendant {{battleCount}} combats."
|
||||
},
|
||||
"TempBattleStatBoosterModifierType": {
|
||||
"description": "Augmente d’un cran {{tempBattleStatName}} pour toute l’équipe pendant 5 combats."
|
||||
"TempStatStageBoosterModifierType": {
|
||||
"description": "Augmente d’un cran {{stat}} pour toute l’équipe pendant 5 combats."
|
||||
},
|
||||
"AttackTypeBoosterModifierType": {
|
||||
"description": "Augmente de 20% la puissance des capacités de type {{moveType}} d’un Pokémon."
|
||||
@ -61,8 +61,8 @@
|
||||
"AllPokemonLevelIncrementModifierType": {
|
||||
"description": "Fait monter toute l’équipe de {{levels}} niveau·x."
|
||||
},
|
||||
"PokemonBaseStatBoosterModifierType": {
|
||||
"description": "Augmente de 10% {{statName}} de base de son porteur. Plus les IV sont hauts, plus il peut en porter."
|
||||
"BaseStatBoosterModifierType": {
|
||||
"description": "Augmente de 10% {{stat}} de base de son porteur. Plus les IV sont hauts, plus il peut en porter."
|
||||
},
|
||||
"AllPokemonFullHpRestoreModifierType": {
|
||||
"description": "Restaure tous les PV de toute l’équipe."
|
||||
@ -183,6 +183,7 @@
|
||||
"SOOTHE_BELL": { "name": "Grelot Zen" },
|
||||
|
||||
"SCOPE_LENS": { "name": "Lentilscope", "description": "Une lentille qui augmente d’un cran le taux de critiques du porteur." },
|
||||
"DIRE_HIT": { "name": "Muscle +", "extra": { "raises": "Taux de critique" } },
|
||||
"LEEK": { "name": "Poireau", "description": "À faire tenir à Canarticho ou Palarticho. Un poireau très long et solide qui augmente de 2 crans le taux de critiques." },
|
||||
|
||||
"EVIOLITE": { "name": "Évoluroc", "description": "Augmente de 50% la Défense et Déf. Spé. si le porteur peut évoluer, 25% aux fusions dont une moitié le peut encore." },
|
||||
@ -250,28 +251,14 @@
|
||||
"METAL_POWDER": { "name": "Poudre Métal", "description": "À faire tenir à Métamorph. Cette poudre étrange, très fine mais résistante, double sa Défense." },
|
||||
"QUICK_POWDER": { "name": "Poudre Vite", "description": "À faire tenir à Métamorph. Cette poudre étrange, très fine mais résistante, double sa Vitesse." }
|
||||
},
|
||||
"TempBattleStatBoosterItem": {
|
||||
"TempStatStageBoosterItem": {
|
||||
"x_attack": "Attaque +",
|
||||
"x_defense": "Défense +",
|
||||
"x_sp_atk": "Atq. Spé. +",
|
||||
"x_sp_def": "Déf. Spé. +",
|
||||
"x_speed": "Vitesse +",
|
||||
"x_accuracy": "Précision +",
|
||||
"dire_hit": "Muscle +"
|
||||
"x_accuracy": "Précision +"
|
||||
},
|
||||
|
||||
"TempBattleStatBoosterStatName": {
|
||||
"ATK": "l’Attaque",
|
||||
"DEF": "la Défense",
|
||||
"SPATK": "l’Atq. Spé.",
|
||||
"SPDEF": "la Déf. Spé.",
|
||||
"SPD": "la Vitesse",
|
||||
"ACC": "la précision",
|
||||
"CRIT": "le taux de critique",
|
||||
"EVA": "l’esquive",
|
||||
"DEFAULT": "???"
|
||||
},
|
||||
|
||||
"AttackTypeBoosterItem": {
|
||||
"silk_scarf": "Mouchoir Soie",
|
||||
"black_belt": "Ceinture Noire",
|
||||
|
@ -3,7 +3,7 @@
|
||||
"turnHealApply": "Les PV de {{pokemonNameWithAffix}}\nsont un peu restaurés par les {{typeName}} !",
|
||||
"hitHealApply": "Les PV de {{pokemonNameWithAffix}}\nsont un peu restaurés par le {{typeName}} !",
|
||||
"pokemonInstantReviveApply": "{{pokemonNameWithAffix}} a repris connaissance\navec sa {{typeName}} et est prêt à se battre de nouveau !",
|
||||
"pokemonResetNegativeStatStageApply": "Les stats baissées de {{pokemonNameWithAffix}}\nsont restaurées par l’{{typeName}} !",
|
||||
"resetNegativeStatStageApply": "Les stats baissées de {{pokemonNameWithAffix}}\nsont restaurées par l’{{typeName}} !",
|
||||
"moneyInterestApply": "La {{typeName}} vous rapporte\n{{moneyAmount}} ₽ d’intérêts !",
|
||||
"turnHeldItemTransferApply": "{{itemName}} de {{pokemonNameWithAffix}} est absorbé·e\npar le {{typeName}} de {{pokemonName}} !",
|
||||
"contactHeldItemTransferApply": "{{itemName}} de {{pokemonNameWithAffix}} est volé·e\npar l’{{typeName}} de {{pokemonName}} !",
|
||||
|
@ -3,6 +3,10 @@
|
||||
"cutHpPowerUpMove": "{{pokemonName}} sacrifie des PV\net augmente la puissance ses capacités !",
|
||||
"absorbedElectricity": "{{pokemonName}} absorbe de l’électricité !",
|
||||
"switchedStatChanges": "{{pokemonName}} permute\nles changements de stats avec ceux de sa cible !",
|
||||
"switchedTwoStatChanges": "{{pokemonName}} permute les changements de {{firstStat} et de {{secondStat}} avec ceux de sa cible !",
|
||||
"switchedStat": "{{pokemonName}} et sa cible échangent leur {{stat}} !",
|
||||
"sharedGuard": "{{pokemonName}} additionne sa garde à celle de sa cible et redistribue le tout équitablement !",
|
||||
"sharedPower": "{{pokemonName}} additionne sa force à celle de sa cible et redistribue le tout équitablement !",
|
||||
"goingAllOutForAttack": "{{pokemonName}} a pris\ncette capacité au sérieux !",
|
||||
"regainedHealth": "{{pokemonName}}\nrécupère des PV !",
|
||||
"keptGoingAndCrashed": "{{pokemonName}}\ns’écrase au sol !",
|
||||
|
@ -80,7 +80,7 @@
|
||||
"100_RIBBONS": {
|
||||
"name": "Campione Lega Assoluta"
|
||||
},
|
||||
"TRANSFER_MAX_BATTLE_STAT": {
|
||||
"TRANSFER_MAX_STAT_STAGE": {
|
||||
"name": "Lavoro di Squadra",
|
||||
"description": "Trasferisci almeno sei bonus statistiche tramite staffetta"
|
||||
},
|
||||
@ -261,4 +261,4 @@
|
||||
"name": "Buona la prima!",
|
||||
"description": "Completa la modalità sfida 'Un nuovo inizio'."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,8 +49,8 @@
|
||||
"DoubleBattleChanceBoosterModifierType": {
|
||||
"description": "Raddoppia la possibilità di imbattersi in doppie battaglie per {{battleCount}} battaglie."
|
||||
},
|
||||
"TempBattleStatBoosterModifierType": {
|
||||
"description": "Aumenta {{tempBattleStatName}} di un livello a tutti i Pokémon nel gruppo per 5 battaglie."
|
||||
"TempStatStageBoosterModifierType": {
|
||||
"description": "Aumenta la statistica {{stat}} di un livello\na tutti i Pokémon nel gruppo per 5 battaglie."
|
||||
},
|
||||
"AttackTypeBoosterModifierType": {
|
||||
"description": "Aumenta la potenza delle mosse di tipo {{moveType}} del 20% per un Pokémon."
|
||||
@ -59,10 +59,10 @@
|
||||
"description": "Aumenta il livello di un Pokémon di {{levels}}."
|
||||
},
|
||||
"AllPokemonLevelIncrementModifierType": {
|
||||
"description": "Aumenta i livell di tutti i Pokémon della squadra di {{levels}}."
|
||||
"description": "Aumenta il livello di tutti i Pokémon della squadra di {{levels}}."
|
||||
},
|
||||
"PokemonBaseStatBoosterModifierType": {
|
||||
"description": "Aumenta {{statName}} di base del possessore del 10%."
|
||||
"BaseStatBoosterModifierType": {
|
||||
"description": "Aumenta l'/la {{stat}} di base del possessore del 10%."
|
||||
},
|
||||
"AllPokemonFullHpRestoreModifierType": {
|
||||
"description": "Restituisce il 100% dei PS a tutti i Pokémon."
|
||||
@ -248,6 +248,12 @@
|
||||
"name": "Mirino",
|
||||
"description": "Lente che aumenta la probabilità di sferrare brutti colpi."
|
||||
},
|
||||
"DIRE_HIT": {
|
||||
"name": "Supercolpo",
|
||||
"extra": {
|
||||
"raises": "Tasso di brutti colpi"
|
||||
}
|
||||
},
|
||||
"LEEK": {
|
||||
"name": "Porro",
|
||||
"description": "Strumento da dare a Farfetch'd. Lungo gambo di porro che aumenta la probabilità di sferrare brutti colpi."
|
||||
@ -411,25 +417,13 @@
|
||||
"description": "Strumento da dare a Ditto. Questa strana polvere, fine e al contempo dura, aumenta la Velocità."
|
||||
}
|
||||
},
|
||||
"TempBattleStatBoosterItem": {
|
||||
"TempStatStageBoosterItem": {
|
||||
"x_attack": "Attacco X",
|
||||
"x_defense": "Difesa X",
|
||||
"x_sp_atk": "Att. Speciale X",
|
||||
"x_sp_def": "Dif. Speciale X",
|
||||
"x_speed": "Velocità X",
|
||||
"x_accuracy": "Precisione X",
|
||||
"dire_hit": "Supercolpo"
|
||||
},
|
||||
"TempBattleStatBoosterStatName": {
|
||||
"ATK": "Attacco",
|
||||
"DEF": "Difesa",
|
||||
"SPATK": "Att. Speciale",
|
||||
"SPDEF": "Dif. Speciale",
|
||||
"SPD": "Velocità",
|
||||
"ACC": "Precisione",
|
||||
"CRIT": "Tasso di brutti colpi",
|
||||
"EVA": "Elusione",
|
||||
"DEFAULT": "???"
|
||||
"x_accuracy": "Precisione X"
|
||||
},
|
||||
"AttackTypeBoosterItem": {
|
||||
"silk_scarf": "Sciarpa seta",
|
||||
@ -606,4 +600,4 @@
|
||||
"FAIRY_MEMORY": "ROM Folletto",
|
||||
"NORMAL_MEMORY": "ROM Normale"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
"turnHealApply": "{{pokemonNameWithAffix}} recupera alcuni PS con\nil/la suo/a {{typeName}}!",
|
||||
"hitHealApply": "{{pokemonNameWithAffix}} recupera alcuni PS con\nil/la suo/a {{typeName}}!",
|
||||
"pokemonInstantReviveApply": "{{pokemonNameWithAffix}} torna in forze\ngrazie al/alla suo/a {{typeName}}!",
|
||||
"pokemonResetNegativeStatStageApply": "La riduzione alle statistiche di {{pokemonNameWithAffix}}\nviene annullata grazie al/alla suo/a {{typeName}}!",
|
||||
"resetNegativeStatStageApply": "La riduzione alle statistiche di {{pokemonNameWithAffix}}\nviene annullata grazie al/alla suo/a {{typeName}}!",
|
||||
"moneyInterestApply": "Ricevi un interesse pari a {{moneyAmount}}₽\ngrazie al/allo/a {{typeName}}!",
|
||||
"turnHeldItemTransferApply": "Il/l'/lo/la {{itemName}} di {{pokemonNameWithAffix}} è stato assorbito\ndal {{typeName}} di {{pokemonName}}!",
|
||||
"contactHeldItemTransferApply": "Il/l'/lo/la {{itemName}} di {{pokemonNameWithAffix}} è stato rubato\nda {{pokemonName}} con {{typeName}}!",
|
||||
|
@ -3,6 +3,10 @@
|
||||
"cutHpPowerUpMove": "{{pokemonName}} riduce i suoi PS per potenziare la sua mossa!",
|
||||
"absorbedElectricity": "{{pokemonName}} assorbe elettricità!",
|
||||
"switchedStatChanges": "{{pokemonName}} scambia con il bersaglio le modifiche alle statistiche!",
|
||||
"switchedTwoStatChanges": "{{pokemonName}} scambia con il bersaglio le modifiche a {{firstStat}} e {{secondStat}}!",
|
||||
"switchedStat": "{{pokemonName}} scambia la sua {{stat}} con quella del bersaglio!",
|
||||
"sharedGuard": "{{pokemonName}} somma le sue capacità difensive con quelle del bersaglio e le ripartisce equamente!",
|
||||
"sharedPower": "{{pokemonName}} somma le sue capacità offensive con quelle del bersaglio e le ripartisce equamente!",
|
||||
"goingAllOutForAttack": "{{pokemonName}} fa sul serio!",
|
||||
"regainedHealth": "{{pokemonName}} s'è\nripreso!",
|
||||
"keptGoingAndCrashed": "{{pokemonName}} si sbilancia e\nsi schianta!",
|
||||
|
@ -81,7 +81,7 @@
|
||||
"100_RIBBONS": {
|
||||
"name": "マスターリーグチャンピオン"
|
||||
},
|
||||
"TRANSFER_MAX_BATTLE_STAT": {
|
||||
"TRANSFER_MAX_STAT_STAGE": {
|
||||
"name": "同力",
|
||||
"description": "少なくとも 一つの 能力を 最大まで あげて\n他の 手持ちポケモンに バトンタッチする"
|
||||
},
|
||||
|
@ -49,8 +49,8 @@
|
||||
"DoubleBattleChanceBoosterModifierType": {
|
||||
"description": "バトル{{battleCount}}かいのあいだ ダブルバトルになるかくりつを2ばいにする"
|
||||
},
|
||||
"TempBattleStatBoosterModifierType": {
|
||||
"description": "すべてのパーティメンバーの {{tempBattleStatName}}を5かいのバトルのあいだ 1だんかいあげる"
|
||||
"TempStatStageBoosterModifierType": {
|
||||
"description": "すべてのパーティメンバーの {{stat}}を5かいのバトルのあいだ 1だんかいあげる"
|
||||
},
|
||||
"AttackTypeBoosterModifierType": {
|
||||
"description": "ポケモンの {{moveType}}タイプのわざのいりょくを20パーセントあげる"
|
||||
@ -61,8 +61,8 @@
|
||||
"AllPokemonLevelIncrementModifierType": {
|
||||
"description": "すべてのパーティメンバーのレベルを1あげる"
|
||||
},
|
||||
"PokemonBaseStatBoosterModifierType": {
|
||||
"description": "ポケモンの{{statName}}のきほんステータスを10パーセントあげる。こたいちがたかいほどスタックのげんかいもたかくなる。"
|
||||
"BaseStatBoosterModifierType": {
|
||||
"description": "ポケモンの{{stat}}のきほんステータスを10パーセントあげる。こたいちがたかいほどスタックのげんかいもたかくなる。"
|
||||
},
|
||||
"AllPokemonFullHpRestoreModifierType": {
|
||||
"description": "すべてのポケモンのHPを100パーセントかいふくする"
|
||||
@ -248,6 +248,12 @@
|
||||
"name": "ピントレンズ",
|
||||
"description": "弱点が 見える レンズ。持たせた ポケモンの技が 急所に 当たりやすくなる。"
|
||||
},
|
||||
"DIRE_HIT": {
|
||||
"name": "クリティカット",
|
||||
"extra": {
|
||||
"raises": "きゅうしょりつ"
|
||||
}
|
||||
},
|
||||
"LEEK": {
|
||||
"name": "ながねぎ",
|
||||
"description": "とても長くて 硬いクキ。カモネギに 持たせると 技が 急所に 当たりやすくなる。"
|
||||
@ -411,25 +417,13 @@
|
||||
"description": "メタモンに 持たせると 素早さが あがる 不思議 粉。とても こまかくて 硬い。"
|
||||
}
|
||||
},
|
||||
"TempBattleStatBoosterItem": {
|
||||
"TempStatStageBoosterItem": {
|
||||
"x_attack": "プラスパワー",
|
||||
"x_defense": "ディフェンダー",
|
||||
"x_sp_atk": "スペシャルアップ",
|
||||
"x_sp_def": "スペシャルガード",
|
||||
"x_speed": "スピーダー",
|
||||
"x_accuracy": "ヨクアタール",
|
||||
"dire_hit": "クリティカット"
|
||||
},
|
||||
"TempBattleStatBoosterStatName": {
|
||||
"ATK": "こうげき",
|
||||
"DEF": "ぼうぎょ",
|
||||
"SPATK": "とくこう",
|
||||
"SPDEF": "とくぼう",
|
||||
"SPD": "すばやさ",
|
||||
"ACC": "めいちゅう",
|
||||
"CRIT": "きゅうしょりつ",
|
||||
"EVA": "かいひ",
|
||||
"DEFAULT": "???"
|
||||
"x_accuracy": "ヨクアタール"
|
||||
},
|
||||
"AttackTypeBoosterItem": {
|
||||
"silk_scarf": "シルクのスカーフ",
|
||||
@ -569,4 +563,4 @@
|
||||
"DOUSE_DRIVE": "アクアカセット",
|
||||
"ULTRANECROZIUM_Z": "ウルトラネクロZ"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
"turnHealApply": "{{pokemonNameWithAffix}}は\n{{typeName}}で 少し 回復!",
|
||||
"hitHealApply": "{{pokemonNameWithAffix}}は\n{{typeName}}で 少し 回復!",
|
||||
"pokemonInstantReviveApply": "{{pokemonNameWithAffix}}は\n{{typeName}}で 復活した!",
|
||||
"pokemonResetNegativeStatStageApply": "{{pokemonNameWithAffix}}は {{typeName}}で\n下がった能力が 元に戻った!",
|
||||
"resetNegativeStatStageApply": "{{pokemonNameWithAffix}}は {{typeName}}で\n下がった能力が 元に戻った!",
|
||||
"moneyInterestApply": "{{typeName}}から {{moneyAmount}}円 取得した!",
|
||||
"turnHeldItemTransferApply": "{{pokemonName}}の {{typeName}}が\n{{pokemonNameWithAffix}}の {{itemName}}を 吸い取った!",
|
||||
"contactHeldItemTransferApply": "{{pokemonName}}の {{typeName}}が\n{{pokemonNameWithAffix}}の {{itemName}}を うばい取った!",
|
||||
|
@ -2,7 +2,9 @@
|
||||
"hitWithRecoil": "{{pokemonName}}は\nはんどうによる ダメージを うけた!",
|
||||
"cutHpPowerUpMove": "{{pokemonName}}は\nたいりょくを けずって パワーぜんかい!",
|
||||
"absorbedElectricity": "{{pokemonName}}は\n でんきを きゅうしゅうした!",
|
||||
"switchedStatChanges": "{{pokemonName}}は あいてと じぶんのn\nのうりょくへんかを いれかえた!",
|
||||
"switchedStatChanges": "{{pokemonName}}は あいてと じぶんの\nのうりょくへんかを いれかえた!",
|
||||
"sharedGuard": "{{pokemonName}}は\nおたがいのガードを シェアした!",
|
||||
"sharedPower": "{{pokemonName}}は\nおたがいのパワーを シェアした!",
|
||||
"goingAllOutForAttack": "{{pokemonName}}は\nほんきを だした!",
|
||||
"regainedHealth": "{{pokemonName}}は\nたいりょくを かいふくした!",
|
||||
"keptGoingAndCrashed": "いきおいあまって {{pokemonName}}は\nじめんに ぶつかった!",
|
||||
@ -59,4 +61,4 @@
|
||||
"suppressAbilities": "{{pokemonName}}の とくせいが きかなくなった!",
|
||||
"revivalBlessing": "{{pokemonName}}は\n復活して 戦えるようになった!",
|
||||
"swapArenaTags": "{{pokemonName}}は\nおたがいの ばのこうかを いれかえた!"
|
||||
}
|
||||
}
|
||||
|
@ -1 +1,130 @@
|
||||
{}
|
||||
{
|
||||
"ace_trainer": "エリートトレーナー",
|
||||
"ace_trainer_female": "エリートトレーナー",
|
||||
"ace_duo": "エリートコンビ",
|
||||
"artist": "芸術家",
|
||||
"artist_female": "芸術家",
|
||||
"backers": "ファンクラブ",
|
||||
"backpacker": "バックパッカー",
|
||||
"backpacker_female": "バックパッカー",
|
||||
"backpackers": "バックパッカーズ",
|
||||
"baker": "ベーカリー",
|
||||
"battle_girl": "バトルガール",
|
||||
"beauty": "大人のおねえさん",
|
||||
"beginners": "初心者",
|
||||
"biker": "暴走族",
|
||||
"black_belt": "カラテ王",
|
||||
"breeder": "ポケモンブリーダー",
|
||||
"breeder_female": "ポケモンブリーダー",
|
||||
"breeders": "ブリーダーコンビ",
|
||||
"clerk": "ビジネスマン",
|
||||
"clerk_female": "OL",
|
||||
"colleagues": "ビジネスパートナー",
|
||||
"crush_kin": "格闘兄妹",
|
||||
"cyclist": "サイクリング",
|
||||
"cyclist_female": "サイクリング",
|
||||
"cyclists": "サイクリングチーム",
|
||||
"dancer": "ダンサー",
|
||||
"dancer_female": "ダンサー",
|
||||
"depot_agent": "鉄道員",
|
||||
"doctor": "ドクター",
|
||||
"doctor_female": "ドクター",
|
||||
"firebreather": "火吹きやろう",
|
||||
"fisherman": "釣り人",
|
||||
"fisherman_female": "釣り人",
|
||||
"gentleman": "ジェントルマン",
|
||||
"guitarist": "ギタリスト",
|
||||
"guitarist_female": "ギタリスト",
|
||||
"harlequin": "クラウン",
|
||||
"hiker": "山男",
|
||||
"hooligans": "バッドチーム",
|
||||
"hoopster": "バスケ選手",
|
||||
"infielder": "野球選手",
|
||||
"janitor": "清掃員",
|
||||
"lady": "お嬢さま",
|
||||
"lass": "ミニスカート",
|
||||
"linebacker": "フットボーラー",
|
||||
"maid": "メイド",
|
||||
"madame": "マダム",
|
||||
"medical_team": "医療チーム",
|
||||
"musician": "ミュージシャン",
|
||||
"hex_maniac": "オカルトマニア",
|
||||
"nurse": "ナース",
|
||||
"nursery_aide": "保育士",
|
||||
"officer": "お巡りさん",
|
||||
"parasol_lady": "パラソルおねえさん",
|
||||
"pilot": "パイロット",
|
||||
"pokéfan": "大好きクラブ",
|
||||
"pokéfan_female": "大好きクラブ",
|
||||
"pokéfan_family": "大好き夫婦",
|
||||
"preschooler": "園児",
|
||||
"preschooler_female": "園児",
|
||||
"preschoolers": "園児たち",
|
||||
"psychic": "サイキッカー",
|
||||
"psychic_female": "サイキッカー",
|
||||
"psychics": "サイキッ家",
|
||||
"pokémon_ranger": "ポケモンレンジャー",
|
||||
"pokémon_ranger_female": "ポケモンレンジャー",
|
||||
"pokémon_rangers": "レンジャーズ",
|
||||
"ranger": "レンジャー",
|
||||
"restaurant_staff": "レストランスタッフ",
|
||||
"rich": "お金持ち",
|
||||
"rich_female": "お金持ち",
|
||||
"rich_boy": "お坊っちゃま",
|
||||
"rich_couple": "お二人さま",
|
||||
"rich_kid": "ブルジョワ男子",
|
||||
"rich_kid_female": "ブルジョワ女子",
|
||||
"rich_kids": "ブルジョワ子達",
|
||||
"roughneck": "スキンヘッズ",
|
||||
"sailor": "船乗り",
|
||||
"scientist": "研究員",
|
||||
"scientist_female": "研究員",
|
||||
"scientists": "研究チーム",
|
||||
"smasher": "テニスプレイヤー",
|
||||
"snow_worker": "冷凍作業員",
|
||||
"snow_worker_female": "冷凍作業員",
|
||||
"striker": "サッカー選手",
|
||||
"school_kid": "塾帰り",
|
||||
"school_kid_female": "塾帰り",
|
||||
"school_kids": "塾生たち",
|
||||
"swimmer": "海パンやろう",
|
||||
"swimmer_female": "ビキニのおねえさん",
|
||||
"swimmers": "水着カップル",
|
||||
"twins": "双子ちゃん",
|
||||
"veteran": "ベテラントレーナー",
|
||||
"veteran_female": "ベテラントレーナー",
|
||||
"veteran_duo": "ベテランコンビ",
|
||||
"waiter": "ウエーター",
|
||||
"waitress": "ウエートレス",
|
||||
"worker": "作業員",
|
||||
"worker_female": "作業員",
|
||||
"workers": "作業班",
|
||||
"youngster": "短パン小僧",
|
||||
"rocket_grunt": "ロケット団の下っ端",
|
||||
"rocket_grunts": " ロケット団の下っ端",
|
||||
"rocket_grunt_female": "ロケット団の下っ端",
|
||||
"magma_grunt": "マグマ団の下っ端",
|
||||
"magma_grunt_female": "マグマ団の下っ端",
|
||||
"magma_grunts": "マグマ団の下っ端",
|
||||
"aqua_grunt": "アクア団の下っ端",
|
||||
"aqua_grunt_female": "アクア団の下っ端",
|
||||
"aqua_grunts": "アクア団の下っ端",
|
||||
"galactic_grunt": "ギンガ団の下っ端",
|
||||
"galactic_grunt_female": "ギンガ団の下っ端",
|
||||
"galactic_grunts": "ギンガ団の下っ端",
|
||||
"plasma_grunt": "プラスマ団の下っ端",
|
||||
"plasma_grunt_female": "プラズマ団の下っ端",
|
||||
"plasma_grunts": "プラズマ団の下っ端",
|
||||
"flare_grunt": "フレア団の下っ端",
|
||||
"flare_grunt_female": "フレア団の下っ端",
|
||||
"flare_grunts": "フレア団の下っ端",
|
||||
"aether_grunt": "エーテル財団の職員",
|
||||
"aether_grunt_female": "エーテル財団の職員",
|
||||
"aether_grunts": "エーテル財団の職員",
|
||||
"skull_grunt": "スカル団の下っ端",
|
||||
"skull_grunt_female": "スカル団の下っ端",
|
||||
"skull_grunts": "スカル団の下っ端",
|
||||
"macro_grunt": "マクロコスモスのトレーナ",
|
||||
"macro_grunt_female": "マクロコスモスのトレーナ",
|
||||
"macro_grunts": "マクロコスモスのトレーナ"
|
||||
}
|
||||
|
@ -1 +1,164 @@
|
||||
{}
|
||||
{
|
||||
"brock": "タケシ",
|
||||
"misty": "カスミ",
|
||||
"lt_surge": "マチス",
|
||||
"erika": "エリカ",
|
||||
"janine": "アンズ",
|
||||
"sabrina": "ナツメ",
|
||||
"blaine": "カツラ",
|
||||
"giovanni": "サカキ",
|
||||
"falkner": "ハヤト",
|
||||
"bugsy": "ツクシ",
|
||||
"whitney": "アカネ",
|
||||
"morty": "マツバ",
|
||||
"chuck": "シジマ",
|
||||
"jasmine": "ミカン",
|
||||
"pryce": "ヤナギ",
|
||||
"clair": "イブキ",
|
||||
"roxanne": "ツツジ",
|
||||
"brawly": "トウキ",
|
||||
"wattson": "テッセン",
|
||||
"flannery": "アスナ",
|
||||
"norman": "センリ",
|
||||
"winona": "ナギ",
|
||||
"tate": "フウ",
|
||||
"liza": "ラン",
|
||||
"juan": "アダン",
|
||||
"roark": "ヒョウタ",
|
||||
"gardenia": "ナタネ",
|
||||
"maylene": "スモモ",
|
||||
"crasher_wake": "マキシ",
|
||||
"fantina": "メリッサ",
|
||||
"byron": "トウガン",
|
||||
"candice": "スズナ",
|
||||
"volkner": "デンジ",
|
||||
"cilan": "デント",
|
||||
"chili": "ポッド",
|
||||
"cress": "コーン",
|
||||
"cheren": "チェレン",
|
||||
"lenora": "アロエ",
|
||||
"roxie": "ホミカ",
|
||||
"burgh": "アーティ",
|
||||
"elesa": "カミツレ",
|
||||
"clay": "ヤーコン",
|
||||
"skyla": "フウロ",
|
||||
"brycen": "ハチク",
|
||||
"drayden": "シャガ",
|
||||
"marlon": "シズイ",
|
||||
"viola": "ビオラ",
|
||||
"grant": "ザクロ",
|
||||
"korrina": "コルニ",
|
||||
"ramos": "フクジ",
|
||||
"clemont": "シトロン",
|
||||
"valerie": "マーシュ",
|
||||
"olympia": "ゴジカ",
|
||||
"wulfric": "ウルップ",
|
||||
"milo": "ヤロー",
|
||||
"nessa": "ルリナ",
|
||||
"kabu": "カブ",
|
||||
"bea": "サイトウ",
|
||||
"allister": "オニオン",
|
||||
"opal": "ポプラ",
|
||||
"bede": "ビート",
|
||||
"gordie": "マクワ",
|
||||
"melony": "メロン",
|
||||
"piers": "ネズ",
|
||||
"marnie": "マリィ",
|
||||
"raihan": "キバナ",
|
||||
"katy": "カエデ",
|
||||
"brassius": "コルサ",
|
||||
"iono": " ナンジャモ",
|
||||
"kofu": "ハイダイ",
|
||||
"larry": "アオキ",
|
||||
"ryme": "ライム",
|
||||
"tulip": "リップ",
|
||||
"grusha": "グルーシャ",
|
||||
"lorelei": "カンナ",
|
||||
"bruno": "シバ",
|
||||
"agatha": "キクコ",
|
||||
"lance": "ワタル",
|
||||
"will": "イツキ",
|
||||
"koga": "キョウ",
|
||||
"karen": "カリン",
|
||||
"sidney": "カゲツ",
|
||||
"phoebe": "フヨウ",
|
||||
"glacia": "プリム",
|
||||
"drake": "ゲンジ",
|
||||
"aaron": "リョウ",
|
||||
"bertha": "キクノ",
|
||||
"flint": "オーバ",
|
||||
"lucian": "ゴヨウ",
|
||||
"shauntal": "シキミ",
|
||||
"marshal": "レンブ",
|
||||
"grimsley": "ギーマ",
|
||||
"caitlin": "カトレア",
|
||||
"malva": "パキラ",
|
||||
"siebold": "ズミ",
|
||||
"wikstrom": "ガンピ",
|
||||
"drasna": "ドラセナ",
|
||||
"hala": "ハラ",
|
||||
"molayne": "マーレイン",
|
||||
"olivia": "ライチ",
|
||||
"acerola": "アセロラ",
|
||||
"kahili": "カヒリ",
|
||||
"rika": "チリ",
|
||||
"poppy": "ポピー",
|
||||
"hassel": "ハッサク",
|
||||
"crispin": "アカマツ",
|
||||
"amarys": "ネリネ",
|
||||
"lacey": "タロ",
|
||||
"drayton": "カキツバタ",
|
||||
"blue": "グリーン",
|
||||
"red": "レッド",
|
||||
"steven": "ダイゴ",
|
||||
"wallace": "ミクリ",
|
||||
"cynthia": "シロナ",
|
||||
"alder": "アデク",
|
||||
"iris": "アイリス",
|
||||
"diantha": "カルネ",
|
||||
"hau": "ハウ",
|
||||
"geeta": "オモダカ",
|
||||
"nemona": "ネモ",
|
||||
"kieran": "スグリ",
|
||||
"leon": "ダンデ",
|
||||
"rival": "フィン",
|
||||
"rival_female": "アイヴィー",
|
||||
"archer": "アポロ",
|
||||
"ariana": "アテナ",
|
||||
"proton": "ランス",
|
||||
"petrel": "ラムダ",
|
||||
"tabitha": "ホムラ",
|
||||
"courtney": "カガリ",
|
||||
"shelly": "イズミ",
|
||||
"matt": "ウシオ",
|
||||
"mars": "マーズ",
|
||||
"jupiter": "ジュピター",
|
||||
"saturn": "サターン",
|
||||
"zinzolin": "ヴィオ",
|
||||
"rood": "ロット",
|
||||
"xerosic": "クセロシキ",
|
||||
"bryony": "バラ",
|
||||
"faba": "ザオボー",
|
||||
"plumeria": "プルメリ",
|
||||
"oleana": "オリーヴ",
|
||||
|
||||
"maxie": "マツブサ",
|
||||
"archie": "アオギリ",
|
||||
"cyrus": "アカギ",
|
||||
"ghetsis": "ゲーチス",
|
||||
"lysandre": "フラダリ",
|
||||
"lusamine": "ルザミーネ",
|
||||
"guzma": "グズマ",
|
||||
"rose": "ローズ",
|
||||
|
||||
"blue_red_double": "グリーンとレッド",
|
||||
"red_blue_double": "レッドとグリーン",
|
||||
"tate_liza_double": "フウとラン",
|
||||
"liza_tate_double": "ランとフウ",
|
||||
"steven_wallace_double": "ダイゴとミクリ",
|
||||
"wallace_steven_double": "ミクリとダイゴ",
|
||||
"alder_iris_double": "アデクとアイリス",
|
||||
"iris_alder_double": "アイリスとアデク",
|
||||
"marnie_piers_double": "マリィとネズ",
|
||||
"piers_marnie_double": "ネズとマリィ"
|
||||
}
|
||||
|
@ -1 +1,38 @@
|
||||
{}
|
||||
{
|
||||
"elite_four": "四天王",
|
||||
"elite_four_female": "四天王",
|
||||
"gym_leader": "ジムリーダー",
|
||||
"gym_leader_female": "ジムリーダー",
|
||||
"gym_leader_double": "ジムリーダーコンビ",
|
||||
"champion": "チャンピオン",
|
||||
"champion_female": "チャンピオン",
|
||||
"champion_double": "チャンピオンコンビ",
|
||||
"rival": "ライバル",
|
||||
"professor": "ポケモン博士",
|
||||
"frontier_brain": "フロンティアブレーン",
|
||||
"rocket_boss": "ロケット団ボス",
|
||||
"magma_boss": "マグマ団リーダー",
|
||||
"aqua_boss": "アクア団リーダー",
|
||||
"galactic_boss": "ギンガ団ボス",
|
||||
"plasma_boss": "プラズマ団ボス",
|
||||
"flare_boss": "フレア団ボス",
|
||||
"aether_boss": "エーテル代表",
|
||||
"skull_boss": "スカル団ボス",
|
||||
"macro_boss": "マクロコスモス社長",
|
||||
|
||||
"rocket_admin": "ロケット団幹部",
|
||||
"rocket_admin_female": "ロケット団幹部",
|
||||
"magma_admin": "マグマ団幹部",
|
||||
"magma_admin_female": "マグマロケット団幹部",
|
||||
"aqua_admin": "アクア団幹部",
|
||||
"aqua_admin_female": "アクア団幹部",
|
||||
"galactic_commander": "ギンガ団幹部",
|
||||
"galactic_commander_female": "ギンガ団幹部",
|
||||
"plasma_sage": "プラズマ団賢人",
|
||||
"plasma_admin": "プラズマ団賢人",
|
||||
"flare_admin": "フレア団幹部",
|
||||
"flare_admin_female": "フレア団幹部",
|
||||
"aether_admin": "エーテル支部長",
|
||||
"skull_admin": "スカル団幹部",
|
||||
"macro_admin": "マクロコスモス"
|
||||
}
|
||||
|
@ -80,7 +80,7 @@
|
||||
"100_RIBBONS": {
|
||||
"name": "마스터 리그 챔피언"
|
||||
},
|
||||
"TRANSFER_MAX_BATTLE_STAT": {
|
||||
"TRANSFER_MAX_STAT_STAGE": {
|
||||
"name": "팀워크",
|
||||
"description": "한 개 이상의 능력치가 최대 랭크일 때 배턴터치 사용"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"ending": "@c{smile}오? 이긴거야?@d{96} @c{smile_eclosed}진즉 알았어야 했는데.\n아무튼, 돌아왔구나.\n$@c{smile}다 끝난거야.@d{64} 네가 굴레를 끝장냈어.\n$@c{serious_smile_fists}네 꿈도 이뤄졌고말야.\n진짜로 한 번도 안 졌잖아.\n$@c{neutral}기억하는 건 우리들 뿐일 모양이지만.@d{96}\n그래도, 괜찮지?\n$@c{serious_smile_fists}오늘의 일은\n너와 나의 마음 속에 항상 함께할 거야.\n$@c{smile_eclosed}여기 구경도 충분히 했으니\n이제 집에 가자.\n$@c{serious_smile_fists}되돌아가서, 다시 배틀을 할 수도 있지 않을까?\n네가 원한다면 말야.",
|
||||
"ending_female": "@c{shock}돌아왔구나?@d{32} 그 말은…@d{96} 이겼어?!\n@c{smile_ehalf}그럴 줄 알았다니까.\n$@c{smile_eclosed}물론… 언제나 느껴왔지.\n@c{smile}끝난 거, 맞지? 이 굴레를 말이야.\n$@c{smile_ehalf}네 꿈도 이뤘고 말이야.\n어떻게 한번도 안 졌대?\n$네가 한 일은 나만 기억하게 될 모양이지만.\n@c{angry_mopen}나, 안 까먹어볼 테니까!\n$@c{smile_wave_wink}농담이야!@d{64} @c{smile}절대 안 잊어버릴 거야.@d{32}\n마음 속엔 쭉 남아있을 수 있게.\n$@c{smile_wave}어쨌든,@d{64} 시간이 좀 늦었어…@d{96}\n이런 곳에서 할 말은 아닌가?\n$집에 가자. @c{smile_wave_wink}아마 내일은,\n추억을 되짚어보기 위한 배틀을 해볼 수 있을 거야.",
|
||||
"ending": "@c{shock}돌아왔구나?@d{32} 그 말은…@d{96} 이겼어?!\n@c{smile_ehalf}그럴 줄 알았다니까.\n$@c{smile_eclosed}물론… 언제나 느껴왔지.\n@c{smile}끝난 거, 맞지? 이 굴레를 말이야.\n$@c{smile_ehalf}네 꿈도 이뤘고 말이야.\n어떻게 한번도 안 졌대?\n$네가 한 일은 나만 기억하게 될 모양이지만.\n@c{angry_mopen}나, 안 까먹어볼 테니까!\n$@c{smile_wave_wink}농담이야!@d{64} @c{smile}절대 안 잊어버릴 거야.@d{32}\n마음 속엔 쭉 남아있을 수 있게.\n$@c{smile_wave}어쨌든,@d{64} 시간이 좀 늦었어…@d{96}\n이런 곳에서 할 말은 아닌가?\n$집에 가자. @c{smile_wave_wink}아마 내일은,\n추억을 되짚어보기 위한 배틀을 해볼 수 있을 거야.",
|
||||
"ending_female": "@c{smile}오? 이긴거야?@d{96} @c{smile_eclosed}진즉 알았어야 했는데.\n아무튼, 돌아왔구나.\n$@c{smile}다 끝난거야.@d{64} 네가 굴레를 끝장냈어.\n$@c{serious_smile_fists}네 꿈도 이뤄졌고말야.\n진짜로 한 번도 안 졌잖아.\n$@c{neutral}기억하는 건 우리들 뿐일 모양이지만.@d{96}\n그래도, 괜찮지?\n$@c{serious_smile_fists}오늘의 일은\n너와 나의 마음 속에 항상 함께할 거야.\n$@c{smile_eclosed}여기 구경도 충분히 했으니\n이제 집에 가자.\n$@c{serious_smile_fists}되돌아가서, 다시 배틀을 할 수도 있지 않을까?\n네가 원한다면 말야.",
|
||||
"ending_endless": "끝에 도달하신 것을 축하드립니다!\n더 많은 컨텐츠를 기다려주세요.",
|
||||
"ending_name": "Devs"
|
||||
}
|
||||
}
|
||||
|
@ -49,8 +49,8 @@
|
||||
"DoubleBattleChanceBoosterModifierType": {
|
||||
"description": "{{battleCount}}번의 배틀 동안 더블 배틀이 등장할 확률이 두 배가 된다."
|
||||
},
|
||||
"TempBattleStatBoosterModifierType": {
|
||||
"description": "자신의 모든 포켓몬이 5번의 배틀 동안 {{tempBattleStatName}}[[가]] 한 단계 증가한다."
|
||||
"TempStatStageBoosterModifierType": {
|
||||
"description": "자신의 모든 포켓몬이 5번의 배틀 동안 {{stat}}[[가]] 한 단계 증가한다."
|
||||
},
|
||||
"AttackTypeBoosterModifierType": {
|
||||
"description": "지니게 하면 {{moveType}}타입 기술의 위력이 20% 상승한다."
|
||||
@ -61,8 +61,8 @@
|
||||
"AllPokemonLevelIncrementModifierType": {
|
||||
"description": "자신의 모든 포켓몬의 레벨이 {{levels}}만큼 상승한다."
|
||||
},
|
||||
"PokemonBaseStatBoosterModifierType": {
|
||||
"description": "지니게 하면 {{statName}} 종족값을 10% 올려준다. 개체값이 높을수록 더 많이 누적시킬 수 있다."
|
||||
"BaseStatBoosterModifierType": {
|
||||
"description": "지니게 하면 {{stat}} 종족값을 10% 올려준다. 개체값이 높을수록 더 많이 누적시킬 수 있다."
|
||||
},
|
||||
"AllPokemonFullHpRestoreModifierType": {
|
||||
"description": "자신의 포켓몬의 HP를 모두 회복한다."
|
||||
@ -248,6 +248,12 @@
|
||||
"name": "초점렌즈",
|
||||
"description": "약점이 보이는 렌즈. 지니게 한 포켓몬의 기술이 급소에 맞기 쉬워진다."
|
||||
},
|
||||
"DIRE_HIT": {
|
||||
"name": "크리티컬커터",
|
||||
"extra": {
|
||||
"raises": "급소율"
|
||||
}
|
||||
},
|
||||
"LEEK": {
|
||||
"name": "대파",
|
||||
"description": "매우 길고 단단한 줄기. 파오리에게 지니게 하면 기술이 급소에 맞기 쉬워진다."
|
||||
@ -411,25 +417,13 @@
|
||||
"description": "메타몽에게 지니게 하면 스피드가 올라가는 이상한 가루. 매우 잘고 단단하다."
|
||||
}
|
||||
},
|
||||
"TempBattleStatBoosterItem": {
|
||||
"TempStatStageBoosterItem": {
|
||||
"x_attack": "플러스파워",
|
||||
"x_defense": "디펜드업",
|
||||
"x_sp_atk": "스페셜업",
|
||||
"x_sp_def": "스페셜가드",
|
||||
"x_speed": "스피드업",
|
||||
"x_accuracy": "잘-맞히기",
|
||||
"dire_hit": "크리티컬커터"
|
||||
},
|
||||
"TempBattleStatBoosterStatName": {
|
||||
"ATK": "공격",
|
||||
"DEF": "방어",
|
||||
"SPATK": "특수공격",
|
||||
"SPDEF": "특수방어",
|
||||
"SPD": "스피드",
|
||||
"ACC": "명중률",
|
||||
"CRIT": "급소율",
|
||||
"EVA": "회피율",
|
||||
"DEFAULT": "???"
|
||||
"x_accuracy": "잘-맞히기"
|
||||
},
|
||||
"AttackTypeBoosterItem": {
|
||||
"silk_scarf": "실크스카프",
|
||||
@ -606,4 +600,4 @@
|
||||
"FAIRY_MEMORY": "페어리메모리",
|
||||
"NORMAL_MEMORY": "일반메모리"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,10 @@
|
||||
"cutHpPowerUpMove": "{{pokemonName}}[[는]]\n체력을 깎아서 자신의 기술을 강화했다!",
|
||||
"absorbedElectricity": "{{pokemonName}}는(은)\n전기를 흡수했다!",
|
||||
"switchedStatChanges": "{{pokemonName}}[[는]] 상대와 자신의\n능력 변화를 바꿨다!",
|
||||
"switchedTwoStatChanges": "{{pokemonName}} 상대와 자신의 {{firstStat}}과 {{secondStat}}의 능력 변화를 바꿨다!",
|
||||
"switchedStat": "{{pokemonName}} 서로의 {{stat}}를 교체했다!",
|
||||
"sharedGuard": "{{pokemonName}} 서로의 가드를 셰어했다!",
|
||||
"sharedPower": "{{pokemonName}} 서로의 파워를 셰어했다!",
|
||||
"goingAllOutForAttack": "{{pokemonName}}[[는]]\n전력을 다하기 시작했다!",
|
||||
"regainedHealth": "{{pokemonName}}[[는]]\n기력을 회복했다!",
|
||||
"keptGoingAndCrashed": "{{pokemonName}}[[는]]\n의욕이 넘쳐서 땅에 부딪쳤다!",
|
||||
@ -63,4 +67,4 @@
|
||||
"swapArenaTags": "{{pokemonName}}[[는]]\n서로의 필드 효과를 교체했다!",
|
||||
"exposedMove": "{{pokemonName}}[[는]]\n{{targetPokemonName}}의 정체를 꿰뚫어 보았다!",
|
||||
"safeguard": "{{targetName}}[[는]] 신비의 베일이 지켜 주고 있다!"
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@
|
||||
"100_RIBBONS": {
|
||||
"name": "Fita de Diamante"
|
||||
},
|
||||
"TRANSFER_MAX_BATTLE_STAT": {
|
||||
"TRANSFER_MAX_STAT_STAGE": {
|
||||
"name": "Trabalho em Equipe",
|
||||
"description": "Use Baton Pass com pelo menos um atributo aumentado ao máximo"
|
||||
},
|
||||
@ -269,4 +269,4 @@
|
||||
"name": "A torre da derrotA",
|
||||
"description": "Complete o desafio da Batalha Inversa.\n.asrevnI ahlataB ad oifased o etelpmoC"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"ending": "@c{smile}Oh? Você venceu?@d{96} @c{smile_eclosed}Acho que eu deveria saber.\nMas, você está de volta agora.\n$@c{smile}Acabou.@d{64} Você quebrou o ciclo.\n$@c{serious_smile_fists}Você também realizou seu sonho, não é?\nVocê não perdeu nenhuma vez.\n$@c{neutral}Eu sou o único que vai lembrar o que você fez.@d{96}\nAcho que está tudo bem, não é?\n$@c{serious_smile_fists}Sua lenda sempre viverá em nossos corações.\n$@c{smile_eclosed}Enfim, já tive o suficiente deste lugar, não é? Vamos para casa.\n$@c{serious_smile_fists}Talvez quando voltarmos, possamos ter outra batalha?\nSe você estiver disposto.",
|
||||
"ending_female": "@c{shock}Você está de volta?@d{32} Isso significa que…@d{96} você venceu?!\n@c{smile_ehalf}Eu deveria saber que você conseguiria.\n$@c{smile_eclosed}Claro… Eu sempre tive essa sensação.\n@c{smile}Acabou agora, certo? Você quebrou o ciclo.\n$@c{smile_ehalf}Você também realizou seu sonho, não foi?\nVocê não perdeu nenhuma vez.\n$Eu serei a única a lembrar o que você fez.\n@c{angry_mopen}Eu tentarei não esquecer!\n$@c{smile_wave_wink}Brincadeirinha!@d{64} @c{smile}Eu nunca esqueceria.@d{32}\nSua lenda viverá em nossos corações.\n$@c{smile_wave}De qualquer forma,@d{64} está ficando tarde…@d{96} Eu acho?\nÉ difícil dizer neste lugar.\n$Vamos para casa. @c{smile_wave_wink}Talvez amanhã possamos ter outra batalha, pelos velhos tempos?",
|
||||
"ending": "@c{shock}Você está de volta?@d{32} Isso significa que…@d{96} você venceu?!\n@c{smile_ehalf}Eu deveria saber que você conseguiria.\n$@c{smile_eclosed}Claro… Eu sempre tive essa sensação.\n@c{smile}Acabou agora, certo? Você quebrou o ciclo.\n$@c{smile_ehalf}Você também realizou seu sonho, não foi?\nVocê não perdeu nenhuma vez.\n$Eu serei a única a lembrar o que você fez.\n@c{angry_mopen}Eu tentarei não esquecer!\n$@c{smile_wave_wink}Brincadeirinha!@d{64} @c{smile}Eu nunca esqueceria.@d{32}\nSua lenda viverá em nossos corações.\n$@c{smile_wave}De qualquer forma,@d{64} está ficando tarde…@d{96} Eu acho?\nÉ difícil dizer neste lugar.\n$Vamos para casa. @c{smile_wave_wink}Talvez amanhã possamos ter outra batalha, pelos velhos tempos?",
|
||||
"ending_female": "@c{smile}Oh? Você venceu?@d{96} @c{smile_eclosed}Acho que eu deveria saber.\nMas, você está de volta agora.\n$@c{smile}Acabou.@d{64} Você quebrou o ciclo.\n$@c{serious_smile_fists}Você também realizou seu sonho, não é?\nVocê não perdeu nenhuma vez.\n$@c{neutral}Eu sou o único que vai lembrar o que você fez.@d{96}\nAcho que está tudo bem, não é?\n$@c{serious_smile_fists}Sua lenda sempre viverá em nossos corações.\n$@c{smile_eclosed}Enfim, já tive o suficiente deste lugar, não é? Vamos para casa.\n$@c{serious_smile_fists}Talvez quando voltarmos, possamos ter outra batalha?\nSe você estiver disposto.",
|
||||
"ending_endless": "Parabéns por alcançar o final atual!\nMais conteúdo chegará em breve.",
|
||||
"ending_name": "Desenvolvedores"
|
||||
}
|
||||
}
|
||||
|
@ -49,8 +49,8 @@
|
||||
"DoubleBattleChanceBoosterModifierType": {
|
||||
"description": "Dobra as chances de encontrar uma batalha em dupla por {{battleCount}} batalhas."
|
||||
},
|
||||
"TempBattleStatBoosterModifierType": {
|
||||
"description": "Aumenta o atributo de {{tempBattleStatName}} para todos os membros da equipe por 5 batalhas."
|
||||
"TempStatStageBoosterModifierType": {
|
||||
"description": "Aumenta o atributo de {{stat}} para todos os membros da equipe por 5 batalhas."
|
||||
},
|
||||
"AttackTypeBoosterModifierType": {
|
||||
"description": "Aumenta o poder dos ataques do tipo {{moveType}} de um Pokémon em 20%."
|
||||
@ -61,8 +61,8 @@
|
||||
"AllPokemonLevelIncrementModifierType": {
|
||||
"description": "Aumenta em {{levels}} o nível de todos os membros da equipe."
|
||||
},
|
||||
"PokemonBaseStatBoosterModifierType": {
|
||||
"description": "Aumenta o atributo base de {{statName}} em 10%. Quanto maior os IVs, maior o limite de aumento."
|
||||
"BaseStatBoosterModifierType": {
|
||||
"description": "Aumenta o atributo base de {{stat}} em 10%. Quanto maior os IVs, maior o limite de aumento."
|
||||
},
|
||||
"AllPokemonFullHpRestoreModifierType": {
|
||||
"description": "Restaura totalmente os PS de todos os Pokémon."
|
||||
@ -248,6 +248,12 @@
|
||||
"name": "Lentes de Mira",
|
||||
"description": "Estas lentes facilitam o foco em pontos fracos. Aumenta a chance de acerto crítico de quem a segurar."
|
||||
},
|
||||
"DIRE_HIT": {
|
||||
"name": "Direto",
|
||||
"extra": {
|
||||
"raises": "Chance de Acerto Crítico"
|
||||
}
|
||||
},
|
||||
"LEEK": {
|
||||
"name": "Alho-poró",
|
||||
"description": "Esse talo de alho-poró muito longo e rígido aumenta a taxa de acerto crítico dos movimentos do Farfetch'd."
|
||||
@ -411,25 +417,13 @@
|
||||
"description": "Extremamente fino, porém duro, este pó estranho aumenta o atributo de Velocidade de Ditto."
|
||||
}
|
||||
},
|
||||
"TempBattleStatBoosterItem": {
|
||||
"TempStatStageBoosterItem": {
|
||||
"x_attack": "Ataque X",
|
||||
"x_defense": "Defesa X",
|
||||
"x_sp_atk": "Ataque Esp. X",
|
||||
"x_sp_def": "Defesa Esp. X",
|
||||
"x_speed": "Velocidade X",
|
||||
"x_accuracy": "Precisão X",
|
||||
"dire_hit": "Direto"
|
||||
},
|
||||
"TempBattleStatBoosterStatName": {
|
||||
"ATK": "Ataque",
|
||||
"DEF": "Defesa",
|
||||
"SPATK": "Ataque Esp.",
|
||||
"SPDEF": "Defesa Esp.",
|
||||
"SPD": "Velocidade",
|
||||
"ACC": "Precisão",
|
||||
"CRIT": "Chance de Acerto Crítico",
|
||||
"EVA": "Evasão",
|
||||
"DEFAULT": "???"
|
||||
"x_accuracy": "Precisão X"
|
||||
},
|
||||
"AttackTypeBoosterItem": {
|
||||
"silk_scarf": "Lenço de Seda",
|
||||
|
@ -3,7 +3,7 @@
|
||||
"turnHealApply": "{{pokemonNameWithAffix}} restaurou um pouco de PS usando\nsuas {{typeName}}!",
|
||||
"hitHealApply": "{{pokemonNameWithAffix}} restaurou um pouco de PS usando\nsua {{typeName}}!",
|
||||
"pokemonInstantReviveApply": "{{pokemonNameWithAffix}} foi reanimado\npor sua {{typeName}}!",
|
||||
"pokemonResetNegativeStatStageApply": "Os atributos diminuídos de {{pokemonNameWithAffix}} foram\nrestaurados por seu(sua) {{typeName}}!",
|
||||
"resetNegativeStatStageApply": "Os atributos diminuídos de {{pokemonNameWithAffix}} foram\nrestaurados por seu(sua) {{typeName}}!",
|
||||
"moneyInterestApply": "Você recebeu um juros de ₽{{moneyAmount}}\nde sua {{typeName}}!",
|
||||
"turnHeldItemTransferApply": "{{itemName}} de {{pokemonNameWithAffix}} foi absorvido(a)\npelo {{typeName}} de {{pokemonName}}!",
|
||||
"contactHeldItemTransferApply": "{{itemName}} de {{pokemonNameWithAffix}} foi pego(a)\npela {{typeName}} de {{pokemonName}}!",
|
||||
|
@ -63,4 +63,4 @@
|
||||
"swapArenaTags": "{{pokemonName}} trocou os efeitos de batalha que afetam cada lado do campo!",
|
||||
"exposedMove": "{{pokemonName}} identificou\n{{targetPokemonName}}!",
|
||||
"safeguard": "{{targetName}} está protegido por Safeguard!"
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@
|
||||
"name": "大师球联盟冠军"
|
||||
},
|
||||
|
||||
"TRANSFER_MAX_BATTLE_STAT": {
|
||||
"TRANSFER_MAX_STAT_STAGE": {
|
||||
"name": "团队协作",
|
||||
"description": "在一项属性强化至最大时用接力棒传递给其他宝可梦"
|
||||
},
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"ending": "@c{smile}哦?你赢了?@d{96} @c{smile_eclosed}我应该早猜到了\n你回来了。\n$@c{smile}结束了。@d{64} 你终结了这个循环。\n$@c{serious_smile_fists}你也完成了自己的梦想,不是吗?\n你甚至一次都没失败。\n$@c{neutral}我是唯一能够记得你所作所为的人@d{96}\n我觉得这应该也还行吧?\n$@c{serious_smile_fists}你的传奇将永远留存于我们心中。\n$@c{smile_eclosed}不管了,我真是受够这个地方了,你也一样吗?我们回家吧。\n$@c{serious_smile_fists}可能等我们回家以后,再打一场?\n要是你想的话",
|
||||
"ending_female": "@c{shock}你回来了?@d{32} 也就是说…@d{96} 你赢了呀!?\n@c{smile_ehalf}我应该早料到了。\n$@c{smile_eclosed}当然…我一直有这种感觉\n@c{smile}一切都结束了,对么? 你打破了循环。\n$@c{smile_ehalf}你也完成了自己的梦想,不是吗?\n你甚至一次都没失败。\n$我是唯一能够记得你所作所为的人\n@c{angry_mopen}我会努力不忘掉哒!\n$@c{smile_wave_wink}开玩笑啦,@d{64} @c{smile}我才不会忘呢。@d{32}\n你的传奇将永远留存于我们心中。\n$@c{smile_wave}不管了,@d{64} 时候不早了@d{96} ,应该吧?\n在这地方还真搞不清楚。\n$一起回家吧。 @c{smile_wave_wink}可能明天,我们再来打一场,为了重温回忆嘛~"
|
||||
}
|
||||
"ending": "@c{shock}你回来了?@d{32} 也就是说…@d{96} 你赢了呀!?\n@c{smile_ehalf}我应该早料到了。\n$@c{smile_eclosed}当然…我一直有这种感觉\n@c{smile}一切都结束了,对么? 你打破了循环。\n$@c{smile_ehalf}你也完成了自己的梦想,不是吗?\n你甚至一次都没失败。\n$我是唯一能够记得你所作所为的人\n@c{angry_mopen}我会努力不忘掉哒!\n$@c{smile_wave_wink}开玩笑啦,@d{64} @c{smile}我才不会忘呢。@d{32}\n你的传奇将永远留存于我们心中。\n$@c{smile_wave}不管了,@d{64} 时候不早了@d{96} ,应该吧?\n在这地方还真搞不清楚。\n$一起回家吧。 @c{smile_wave_wink}可能明天,我们再来打一场,为了重温回忆嘛~",
|
||||
"ending_female": "@c{smile}哦?你赢了?@d{96} @c{smile_eclosed}我应该早猜到了\n你回来了。\n$@c{smile}结束了。@d{64} 你终结了这个循环。\n$@c{serious_smile_fists}你也完成了自己的梦想,不是吗?\n你甚至一次都没失败。\n$@c{neutral}我是唯一能够记得你所作所为的人@d{96}\n我觉得这应该也还行吧?\n$@c{serious_smile_fists}你的传奇将永远留存于我们心中。\n$@c{smile_eclosed}不管了,我真是受够这个地方了,你也一样吗?我们回家吧。\n$@c{serious_smile_fists}可能等我们回家以后,再打一场?\n要是你想的话"
|
||||
}
|
||||
|
@ -49,8 +49,8 @@
|
||||
"DoubleBattleChanceBoosterModifierType": {
|
||||
"description": "接下来的{{battleCount}}场战斗是双打的概率翻倍。"
|
||||
},
|
||||
"TempBattleStatBoosterModifierType": {
|
||||
"description": "为所有成员宝可梦提升一级{{tempBattleStatName}},持续5场战斗。"
|
||||
"TempStatStageBoosterModifierType": {
|
||||
"description": "为所有成员宝可梦提升一级{{stat}},持续5场战斗。"
|
||||
},
|
||||
"AttackTypeBoosterModifierType": {
|
||||
"description": "一只宝可梦的{{moveType}}系招式威力提升20%。"
|
||||
@ -61,8 +61,8 @@
|
||||
"AllPokemonLevelIncrementModifierType": {
|
||||
"description": "使一只寶可夢的等級提升{{levels}}級。"
|
||||
},
|
||||
"PokemonBaseStatBoosterModifierType": {
|
||||
"description": "增加10%持有者的{{statName}},\n个体值越高堆叠上限越高。"
|
||||
"BaseStatBoosterModifierType": {
|
||||
"description": "增加10%持有者的{{stat}},\n个体值越高堆叠上限越高。"
|
||||
},
|
||||
"AllPokemonFullHpRestoreModifierType": {
|
||||
"description": "所有宝可梦完全回复HP。"
|
||||
@ -248,6 +248,12 @@
|
||||
"name": "焦点镜",
|
||||
"description": "能看见弱点的镜片。携带它的宝可梦的招式\n会变得容易击中要害。"
|
||||
},
|
||||
"DIRE_HIT": {
|
||||
"name": "要害攻击",
|
||||
"extra": {
|
||||
"raises": "会心"
|
||||
}
|
||||
},
|
||||
"LEEK": {
|
||||
"name": "大葱",
|
||||
"description": "非常长且坚硬的茎。让大葱鸭携带后,\n招式会变得容易击中要害。"
|
||||
@ -411,25 +417,13 @@
|
||||
"description": "让百变怪携带后,速度就会提高的神奇粉末。\n非常细腻坚硬。"
|
||||
}
|
||||
},
|
||||
"TempBattleStatBoosterItem": {
|
||||
"TempStatStageBoosterItem": {
|
||||
"x_attack": "力量强化",
|
||||
"x_defense": "防御强化",
|
||||
"x_sp_atk": "特攻强化",
|
||||
"x_sp_def": "特防强化",
|
||||
"x_speed": "速度强化",
|
||||
"x_accuracy": "命中强化",
|
||||
"dire_hit": "要害攻击"
|
||||
},
|
||||
"TempBattleStatBoosterStatName": {
|
||||
"ATK": "攻击",
|
||||
"DEF": "防御",
|
||||
"SPATK": "特攻",
|
||||
"SPDEF": "特防",
|
||||
"SPD": "速度",
|
||||
"ACC": "命中",
|
||||
"CRIT": "会心",
|
||||
"EVA": "闪避",
|
||||
"DEFAULT": "???"
|
||||
"x_accuracy": "命中强化"
|
||||
},
|
||||
"AttackTypeBoosterItem": {
|
||||
"silk_scarf": "丝绸围巾",
|
||||
@ -606,4 +600,4 @@
|
||||
"FAIRY_MEMORY": "妖精存储碟",
|
||||
"NORMAL_MEMORY": "一般存储碟"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
"turnHealApply": "{{pokemonNameWithAffix}}用{{typeName}}\n回复了体力!",
|
||||
"hitHealApply": "{{pokemonNameWithAffix}}用{{typeName}}\n回复了体力!",
|
||||
"pokemonInstantReviveApply": "{{pokemonNameWithAffix}}用{{typeName}}\n恢复了活力!",
|
||||
"pokemonResetNegativeStatStageApply": "{{pokemonNameWithAffix}}降低的能力被{{typeName}}\n复原了!",
|
||||
"resetNegativeStatStageApply": "{{pokemonNameWithAffix}}降低的能力被{{typeName}}\n复原了!",
|
||||
"moneyInterestApply": "用{{typeName}}\n获得了 ₽{{moneyAmount}} 利息!",
|
||||
"turnHeldItemTransferApply": "{{pokemonNameWithAffix}}的{{itemName}}被\n{{pokemonName}}的{{typeName}}吸收了!",
|
||||
"contactHeldItemTransferApply": "{{pokemonNameWithAffix}}的{{itemName}}被\n{{pokemonName}}的{{typeName}}夺取了!",
|
||||
|
@ -3,6 +3,10 @@
|
||||
"cutHpPowerUpMove": "{{pokemonName}}\n削减了体力并提升了招式威力!",
|
||||
"absorbedElectricity": "{{pokemonName}}\n吸收了电力!",
|
||||
"switchedStatChanges": "{{pokemonName}}和对手互换了\n自己的能力变化!",
|
||||
"switchedTwoStatChanges": "{{pokemonName}} 和对手互换了自己的{{firstStat}}和{{secondStat}}的能力变化!",
|
||||
"switchedStat": "{{pokemonName}} 互换了各自的{{stat}}!",
|
||||
"sharedGuard": "{{pokemonName}} 平分了各自的防守!",
|
||||
"sharedPower": "{{pokemonName}} 平分了各自的力量!",
|
||||
"goingAllOutForAttack": "{{pokemonName}}拿出全力了!",
|
||||
"regainedHealth": "{{pokemonName}}的\n体力回复了!",
|
||||
"keptGoingAndCrashed": "{{pokemonName}}因势头过猛\n而撞到了地面!",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"Stat": {
|
||||
"HP": "最大HP",
|
||||
"HPshortened": "最大HP",
|
||||
"HPshortened": "HP",
|
||||
"ATK": "攻击",
|
||||
"ATKshortened": "攻击",
|
||||
"DEF": "防御",
|
||||
@ -37,4 +37,4 @@
|
||||
"FAIRY": "妖精",
|
||||
"STELLAR": "星晶"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@
|
||||
"100_RIBBONS": {
|
||||
"name": "大師球聯盟冠軍"
|
||||
},
|
||||
"TRANSFER_MAX_BATTLE_STAT": {
|
||||
"TRANSFER_MAX_STAT_STAGE": {
|
||||
"name": "團隊協作",
|
||||
"description": "在一項屬性強化至最大時用接力棒傳遞給其他寶可夢"
|
||||
},
|
||||
@ -257,4 +257,4 @@
|
||||
"name": "鏡子子鏡",
|
||||
"description": "完成逆轉之戰挑戰\n戰挑戰之轉逆成完"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"ending": "@c{smile}哦?你贏了?@d{96} @c{smile_eclosed}我應該早猜到了\n你回來了。\n$@c{smile}結束了。@d{64} 你終結了這個循環。\n$@c{serious_smile_fists}你也完成了自己的夢想,不是嗎?\n你甚至一次都沒失敗。\n$@c{neutral}我是唯一能夠記得你所作所為的人@d{96}\n我覺得這應該也還行吧?\n$@c{serious_smile_fists}你的傳奇將永遠留存於我們心中。\n$@c{smile_eclosed}不管了,我真是受夠這個地方了,你也一樣嗎?我們回家吧。\n$@c{serious_smile_fists}可能等我們回家以後,再打一場?\n要是你想的話",
|
||||
"ending_female": "@c{shock}你回來了?@d{32} 也就是說…@d{96} 你贏了呀!?\n@c{smile_ehalf}我應該早料到了。\n$@c{smile_eclosed}當然…我一直有這種感覺\n@c{smile}一切都結束了,對麼? 你打破了循環。\n$@c{smile_ehalf}你也完成了自己的夢想,不是嗎?\n你甚至一次都沒失敗。\n$我是唯一能夠記得你所作所為的人\n@c{angry_mopen}我會努力不忘掉哒!\n$@c{smile_wave_wink}開玩笑啦,@d{64} @c{smile}我才不會忘呢。@d{32}\n你的傳奇將永遠留存於我們心中。\n$@c{smile_wave}不管了,@d{64} 時候不早了@d{96} ,應該吧?\n在這地方還真搞不清楚。\n$一起回家吧。 @c{smile_wave_wink}可能明天,我們再來打一場,為了重溫回憶嘛~"
|
||||
}
|
||||
"ending": "@c{shock}你回來了?@d{32} 也就是說…@d{96} 你贏了呀!?\n@c{smile_ehalf}我應該早料到了。\n$@c{smile_eclosed}當然…我一直有這種感覺\n@c{smile}一切都結束了,對麼? 你打破了循環。\n$@c{smile_ehalf}你也完成了自己的夢想,不是嗎?\n你甚至一次都沒失敗。\n$我是唯一能夠記得你所作所為的人\n@c{angry_mopen}我會努力不忘掉哒!\n$@c{smile_wave_wink}開玩笑啦,@d{64} @c{smile}我才不會忘呢。@d{32}\n你的傳奇將永遠留存於我們心中。\n$@c{smile_wave}不管了,@d{64} 時候不早了@d{96} ,應該吧?\n在這地方還真搞不清楚。\n$一起回家吧。 @c{smile_wave_wink}可能明天,我們再來打一場,為了重溫回憶嘛~",
|
||||
"ending_female": "@c{smile}哦?你贏了?@d{96} @c{smile_eclosed}我應該早猜到了\n你回來了。\n$@c{smile}結束了。@d{64} 你終結了這個循環。\n$@c{serious_smile_fists}你也完成了自己的夢想,不是嗎?\n你甚至一次都沒失敗。\n$@c{neutral}我是唯一能夠記得你所作所為的人@d{96}\n我覺得這應該也還行吧?\n$@c{serious_smile_fists}你的傳奇將永遠留存於我們心中。\n$@c{smile_eclosed}不管了,我真是受夠這個地方了,你也一樣嗎?我們回家吧。\n$@c{serious_smile_fists}可能等我們回家以後,再打一場?\n要是你想的話"
|
||||
}
|
||||
|
@ -49,8 +49,8 @@
|
||||
"DoubleBattleChanceBoosterModifierType": {
|
||||
"description": "接下來的{{battleCount}}場戰鬥是雙打的概率翻倍。"
|
||||
},
|
||||
"TempBattleStatBoosterModifierType": {
|
||||
"description": "爲所有成員寶可夢提升一級{{tempBattleStatName}},持續5場戰鬥。"
|
||||
"TempStatStageBoosterModifierType": {
|
||||
"description": "爲所有成員寶可夢提升一級{{stat}},持續5場戰鬥。"
|
||||
},
|
||||
"AttackTypeBoosterModifierType": {
|
||||
"description": "一隻寶可夢的{{moveType}}系招式威力提升20%。"
|
||||
@ -61,8 +61,8 @@
|
||||
"AllPokemonLevelIncrementModifierType": {
|
||||
"description": "Increases all party members' level by {{levels}}."
|
||||
},
|
||||
"PokemonBaseStatBoosterModifierType": {
|
||||
"description": "增加持有者的{{statName}}10%,個體值越高堆疊\n上限越高。"
|
||||
"BaseStatBoosterModifierType": {
|
||||
"description": "增加持有者的{{stat}}10%,個體值越高堆疊\n上限越高。"
|
||||
},
|
||||
"AllPokemonFullHpRestoreModifierType": {
|
||||
"description": "所有寶可夢完全恢復HP。"
|
||||
@ -244,6 +244,12 @@
|
||||
"name": "焦點鏡",
|
||||
"description": "能看見弱點的鏡片。攜帶它的寶可夢的招式 會變得容易擊中要害。"
|
||||
},
|
||||
"DIRE_HIT": {
|
||||
"name": "要害攻擊",
|
||||
"extra": {
|
||||
"raises": "會心"
|
||||
}
|
||||
},
|
||||
"LEEK": {
|
||||
"name": "大蔥",
|
||||
"description": "非常長且堅硬的莖。讓大蔥鴨攜帶後,招式會 變得容易擊中要害。"
|
||||
@ -407,25 +413,13 @@
|
||||
"description": "讓百變怪攜帶後,速度就會提高的神奇粉末。非常細緻堅硬。"
|
||||
}
|
||||
},
|
||||
"TempBattleStatBoosterItem": {
|
||||
"TempStatStageBoosterItem": {
|
||||
"x_attack": "力量強化",
|
||||
"x_defense": "防禦強化",
|
||||
"x_sp_atk": "特攻強化",
|
||||
"x_sp_def": "特防強化",
|
||||
"x_speed": "速度強化",
|
||||
"x_accuracy": "命中強化",
|
||||
"dire_hit": "要害攻擊"
|
||||
},
|
||||
"TempBattleStatBoosterStatName": {
|
||||
"ATK": "攻擊",
|
||||
"DEF": "防禦",
|
||||
"SPATK": "特攻",
|
||||
"SPDEF": "特防",
|
||||
"SPD": "速度",
|
||||
"ACC": "命中",
|
||||
"CRIT": "會心",
|
||||
"EVA": "閃避",
|
||||
"DEFAULT": "???"
|
||||
"x_accuracy": "命中強化"
|
||||
},
|
||||
"AttackTypeBoosterItem": {
|
||||
"silk_scarf": "絲綢圍巾",
|
||||
@ -602,4 +596,4 @@
|
||||
"FAIRY_MEMORY": "妖精記憶碟",
|
||||
"NORMAL_MEMORY": "一般記憶碟"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,4 +8,4 @@
|
||||
"contactHeldItemTransferApply": "{{pokemonNameWithAffix}}的{{itemName}}被\n{{pokemonName}}的{{typeName}}奪取了!",
|
||||
"enemyTurnHealApply": "{{pokemonNameWithAffix}}\n回復了一些體力!",
|
||||
"bypassSpeedChanceApply": "{{pokemonName}}用了{{itemName}}後,行動變快了!"
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,10 @@
|
||||
"cutHpPowerUpMove": "{{pokemonName}}\n削減體力並提升了招式威力!",
|
||||
"absorbedElectricity": "{{pokemonName}}\n吸收了电力!",
|
||||
"switchedStatChanges": "{{pokemonName}}和對手互換了\n自身的能力變化!",
|
||||
"switchedTwoStatChanges": "{{pokemonName}} 和對手互換了自身的{{firstStat}}和{{secondStat}}的能力變化!",
|
||||
"switchedStat": "{{pokemonName}} 互換了各自的{{stat}}!",
|
||||
"sharedGuard": "{{pokemonName}} 平分了各自的防守!",
|
||||
"sharedPower": "{{pokemonName}} 平分了各自的力量!",
|
||||
"goingAllOutForAttack": "{{pokemonName}}拿出全力了!",
|
||||
"regainedHealth": "{{pokemonName}}的\n體力回復了!",
|
||||
"keptGoingAndCrashed": "{{pokemonName}}因勢頭過猛\n而撞到了地面!",
|
||||
|
@ -3,12 +3,10 @@ import { AttackMove, allMoves, selfStatLowerMoves } from "../data/move";
|
||||
import { MAX_PER_TYPE_POKEBALLS, PokeballType, getPokeballCatchMultiplier, getPokeballName } from "../data/pokeball";
|
||||
import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "../field/pokemon";
|
||||
import { EvolutionItem, pokemonEvolutions } from "../data/pokemon-evolutions";
|
||||
import { Stat, getStatName } from "../data/pokemon-stat";
|
||||
import { tmPoolTiers, tmSpecies } from "../data/tms";
|
||||
import { Type } from "../data/type";
|
||||
import PartyUiHandler, { PokemonMoveSelectFilter, PokemonSelectFilter } from "../ui/party-ui-handler";
|
||||
import * as Utils from "../utils";
|
||||
import { TempBattleStat, getTempBattleStatBoosterItemName, getTempBattleStatName } from "../data/temp-battle-stat";
|
||||
import { getBerryEffectDescription, getBerryName } from "../data/berry";
|
||||
import { Unlockables } from "../system/unlockables";
|
||||
import { StatusEffect, getStatusEffectDescriptor } from "../data/status-effect";
|
||||
@ -28,6 +26,7 @@ import { BerryType } from "#enums/berry-type";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { getPokemonNameWithAffix } from "#app/messages.js";
|
||||
import { PermanentStat, TEMP_BATTLE_STATS, TempBattleStat, Stat, getStatKey } from "#app/enums/stat";
|
||||
|
||||
const outputModifierData = false;
|
||||
const useMaxWeightForOutput = false;
|
||||
@ -447,26 +446,28 @@ export class DoubleBattleChanceBoosterModifierType extends ModifierType {
|
||||
}
|
||||
}
|
||||
|
||||
export class TempBattleStatBoosterModifierType extends ModifierType implements GeneratedPersistentModifierType {
|
||||
public tempBattleStat: TempBattleStat;
|
||||
export class TempStatStageBoosterModifierType extends ModifierType implements GeneratedPersistentModifierType {
|
||||
private stat: TempBattleStat;
|
||||
private key: string;
|
||||
|
||||
constructor(tempBattleStat: TempBattleStat) {
|
||||
super("", getTempBattleStatBoosterItemName(tempBattleStat).replace(/\./g, "").replace(/[ ]/g, "_").toLowerCase(),
|
||||
(_type, _args) => new Modifiers.TempBattleStatBoosterModifier(this, this.tempBattleStat));
|
||||
constructor(stat: TempBattleStat) {
|
||||
const key = TempStatStageBoosterModifierTypeGenerator.items[stat];
|
||||
super("", key, (_type, _args) => new Modifiers.TempStatStageBoosterModifier(this, this.stat));
|
||||
|
||||
this.tempBattleStat = tempBattleStat;
|
||||
this.stat = stat;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t(`modifierType:TempBattleStatBoosterItem.${getTempBattleStatBoosterItemName(this.tempBattleStat).replace(/\./g, "").replace(/[ ]/g, "_").toLowerCase()}`);
|
||||
return i18next.t(`modifierType:TempStatStageBoosterItem.${this.key}`);
|
||||
}
|
||||
|
||||
getDescription(scene: BattleScene): string {
|
||||
return i18next.t("modifierType:ModifierType.TempBattleStatBoosterModifierType.description", { tempBattleStatName: getTempBattleStatName(this.tempBattleStat) });
|
||||
getDescription(_scene: BattleScene): string {
|
||||
return i18next.t("modifierType:ModifierType.TempStatStageBoosterModifierType.description", { stat: i18next.t(getStatKey(this.stat)) });
|
||||
}
|
||||
|
||||
getPregenArgs(): any[] {
|
||||
return [ this.tempBattleStat ];
|
||||
return [ this.stat ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,40 +612,24 @@ export class AllPokemonLevelIncrementModifierType extends ModifierType {
|
||||
}
|
||||
}
|
||||
|
||||
function getBaseStatBoosterItemName(stat: Stat) {
|
||||
switch (stat) {
|
||||
case Stat.HP:
|
||||
return "HP Up";
|
||||
case Stat.ATK:
|
||||
return "Protein";
|
||||
case Stat.DEF:
|
||||
return "Iron";
|
||||
case Stat.SPATK:
|
||||
return "Calcium";
|
||||
case Stat.SPDEF:
|
||||
return "Zinc";
|
||||
case Stat.SPD:
|
||||
return "Carbos";
|
||||
}
|
||||
}
|
||||
export class BaseStatBoosterModifierType extends PokemonHeldItemModifierType implements GeneratedPersistentModifierType {
|
||||
private stat: PermanentStat;
|
||||
private key: string;
|
||||
|
||||
export class PokemonBaseStatBoosterModifierType extends PokemonHeldItemModifierType implements GeneratedPersistentModifierType {
|
||||
private localeName: string;
|
||||
private stat: Stat;
|
||||
constructor(stat: PermanentStat) {
|
||||
const key = BaseStatBoosterModifierTypeGenerator.items[stat];
|
||||
super("", key, (_type, args) => new Modifiers.BaseStatModifier(this, (args[0] as Pokemon).id, this.stat));
|
||||
|
||||
constructor(localeName: string, stat: Stat) {
|
||||
super("", localeName.replace(/[ \-]/g, "_").toLowerCase(), (_type, args) => new Modifiers.PokemonBaseStatModifier(this, (args[0] as Pokemon).id, this.stat));
|
||||
|
||||
this.localeName = localeName;
|
||||
this.stat = stat;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t(`modifierType:BaseStatBoosterItem.${this.localeName.replace(/[ \-]/g, "_").toLowerCase()}`);
|
||||
return i18next.t(`modifierType:BaseStatBoosterItem.${this.key}`);
|
||||
}
|
||||
|
||||
getDescription(scene: BattleScene): string {
|
||||
return i18next.t("modifierType:ModifierType.PokemonBaseStatBoosterModifierType.description", { statName: getStatName(this.stat) });
|
||||
getDescription(_scene: BattleScene): string {
|
||||
return i18next.t("modifierType:ModifierType.BaseStatBoosterModifierType.description", { stat: i18next.t(getStatKey(this.stat)) });
|
||||
}
|
||||
|
||||
getPregenArgs(): any[] {
|
||||
@ -922,6 +907,48 @@ class AttackTypeBoosterModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
class BaseStatBoosterModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
public static readonly items: Record<PermanentStat, string> = {
|
||||
[Stat.HP]: "hp_up",
|
||||
[Stat.ATK]: "protein",
|
||||
[Stat.DEF]: "iron",
|
||||
[Stat.SPATK]: "calcium",
|
||||
[Stat.SPDEF]: "zinc",
|
||||
[Stat.SPD]: "carbos"
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super((_party: Pokemon[], pregenArgs?: any[]) => {
|
||||
if (pregenArgs) {
|
||||
return new BaseStatBoosterModifierType(pregenArgs[0]);
|
||||
}
|
||||
const randStat: PermanentStat = Utils.randSeedInt(Stat.SPD + 1);
|
||||
return new BaseStatBoosterModifierType(randStat);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class TempStatStageBoosterModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
public static readonly items: Record<TempBattleStat, string> = {
|
||||
[Stat.ATK]: "x_attack",
|
||||
[Stat.DEF]: "x_defense",
|
||||
[Stat.SPATK]: "x_sp_atk",
|
||||
[Stat.SPDEF]: "x_sp_def",
|
||||
[Stat.SPD]: "x_speed",
|
||||
[Stat.ACC]: "x_accuracy"
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super((_party: Pokemon[], pregenArgs?: any[]) => {
|
||||
if (pregenArgs && (pregenArgs.length === 1) && TEMP_BATTLE_STATS.includes(pregenArgs[0])) {
|
||||
return new TempStatStageBoosterModifierType(pregenArgs[0]);
|
||||
}
|
||||
const randStat: TempBattleStat = Utils.randSeedInt(Stat.ACC, Stat.ATK);
|
||||
return new TempStatStageBoosterModifierType(randStat);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifier type generator for {@linkcode SpeciesStatBoosterModifierType}, which
|
||||
* encapsulates the logic for weighting the most useful held item from
|
||||
@ -930,7 +957,7 @@ class AttackTypeBoosterModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
*/
|
||||
class SpeciesStatBoosterModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
/** Object comprised of the currently available species-based stat boosting held items */
|
||||
public static items = {
|
||||
public static readonly items = {
|
||||
LIGHT_BALL: { stats: [Stat.ATK, Stat.SPATK], multiplier: 2, species: [Species.PIKACHU] },
|
||||
THICK_CLUB: { stats: [Stat.ATK], multiplier: 2, species: [Species.CUBONE, Species.MAROWAK, Species.ALOLA_MAROWAK] },
|
||||
METAL_POWDER: { stats: [Stat.DEF], multiplier: 2, species: [Species.DITTO] },
|
||||
@ -1233,7 +1260,7 @@ export type GeneratorModifierOverride = {
|
||||
type?: SpeciesStatBoosterItem;
|
||||
}
|
||||
| {
|
||||
name: keyof Pick<typeof modifierTypes, "TEMP_STAT_BOOSTER">;
|
||||
name: keyof Pick<typeof modifierTypes, "TEMP_STAT_STAGE_BOOSTER">;
|
||||
type?: TempBattleStat;
|
||||
}
|
||||
| {
|
||||
@ -1306,7 +1333,7 @@ export const modifierTypes = {
|
||||
SACRED_ASH: () => new AllPokemonFullReviveModifierType("modifierType:ModifierType.SACRED_ASH", "sacred_ash"),
|
||||
|
||||
REVIVER_SEED: () => new PokemonHeldItemModifierType("modifierType:ModifierType.REVIVER_SEED", "reviver_seed", (type, args) => new Modifiers.PokemonInstantReviveModifier(type, (args[0] as Pokemon).id)),
|
||||
WHITE_HERB: () => new PokemonHeldItemModifierType("modifierType:ModifierType.WHITE_HERB", "white_herb", (type, args) => new Modifiers.PokemonResetNegativeStatStageModifier(type, (args[0] as Pokemon).id)),
|
||||
WHITE_HERB: () => new PokemonHeldItemModifierType("modifierType:ModifierType.WHITE_HERB", "white_herb", (type, args) => new Modifiers.ResetNegativeStatStageModifier(type, (args[0] as Pokemon).id)),
|
||||
|
||||
ETHER: () => new PokemonPpRestoreModifierType("modifierType:ModifierType.ETHER", "ether", 10),
|
||||
MAX_ETHER: () => new PokemonPpRestoreModifierType("modifierType:ModifierType.MAX_ETHER", "max_ether", -1),
|
||||
@ -1327,23 +1354,15 @@ export const modifierTypes = {
|
||||
|
||||
SPECIES_STAT_BOOSTER: () => new SpeciesStatBoosterModifierTypeGenerator(),
|
||||
|
||||
TEMP_STAT_BOOSTER: () => new ModifierTypeGenerator((party: Pokemon[], pregenArgs?: any[]) => {
|
||||
if (pregenArgs && (pregenArgs.length === 1) && (pregenArgs[0] in TempBattleStat)) {
|
||||
return new TempBattleStatBoosterModifierType(pregenArgs[0] as TempBattleStat);
|
||||
}
|
||||
const randTempBattleStat = Utils.randSeedInt(6) as TempBattleStat;
|
||||
return new TempBattleStatBoosterModifierType(randTempBattleStat);
|
||||
}),
|
||||
DIRE_HIT: () => new TempBattleStatBoosterModifierType(TempBattleStat.CRIT),
|
||||
TEMP_STAT_STAGE_BOOSTER: () => new TempStatStageBoosterModifierTypeGenerator(),
|
||||
|
||||
BASE_STAT_BOOSTER: () => new ModifierTypeGenerator((party: Pokemon[], pregenArgs?: any[]) => {
|
||||
if (pregenArgs && (pregenArgs.length === 1) && (pregenArgs[0] in Stat)) {
|
||||
const stat = pregenArgs[0] as Stat;
|
||||
return new PokemonBaseStatBoosterModifierType(getBaseStatBoosterItemName(stat), stat);
|
||||
DIRE_HIT: () => new class extends ModifierType {
|
||||
getDescription(_scene: BattleScene): string {
|
||||
return i18next.t("modifierType:ModifierType.TempStatStageBoosterModifierType.description", { stat: i18next.t("modifierType:ModifierType.DIRE_HIT.extra.raises") });
|
||||
}
|
||||
const randStat = Utils.randSeedInt(6) as Stat;
|
||||
return new PokemonBaseStatBoosterModifierType(getBaseStatBoosterItemName(randStat), randStat);
|
||||
}),
|
||||
}("modifierType:ModifierType.DIRE_HIT", "dire_hit", (type, _args) => new Modifiers.TempCritBoosterModifier(type)),
|
||||
|
||||
BASE_STAT_BOOSTER: () => new BaseStatBoosterModifierTypeGenerator(),
|
||||
|
||||
ATTACK_TYPE_BOOSTER: () => new AttackTypeBoosterModifierTypeGenerator(),
|
||||
|
||||
@ -1513,7 +1532,7 @@ const modifierPool: ModifierPool = {
|
||||
return thresholdPartyMemberCount;
|
||||
}, 3),
|
||||
new WeightedModifierType(modifierTypes.LURE, skipInLastClassicWaveOrDefault(2)),
|
||||
new WeightedModifierType(modifierTypes.TEMP_STAT_BOOSTER, 4),
|
||||
new WeightedModifierType(modifierTypes.TEMP_STAT_STAGE_BOOSTER, 4),
|
||||
new WeightedModifierType(modifierTypes.BERRY, 2),
|
||||
new WeightedModifierType(modifierTypes.TM_COMMON, 2),
|
||||
].map(m => {
|
||||
@ -1626,7 +1645,7 @@ const modifierPool: ModifierPool = {
|
||||
new WeightedModifierType(modifierTypes.WHITE_HERB, (party: Pokemon[]) => {
|
||||
const checkedAbilities = [Abilities.WEAK_ARMOR, Abilities.CONTRARY, Abilities.MOODY, Abilities.ANGER_SHELL, Abilities.COMPETITIVE, Abilities.DEFIANT];
|
||||
const weightMultiplier = party.filter(
|
||||
p => !p.getHeldItems().some(i => i instanceof Modifiers.PokemonResetNegativeStatStageModifier && i.stackCount >= i.getMaxHeldItemCount(p)) &&
|
||||
p => !p.getHeldItems().some(i => i instanceof Modifiers.ResetNegativeStatStageModifier && i.stackCount >= i.getMaxHeldItemCount(p)) &&
|
||||
(checkedAbilities.some(a => p.hasAbility(a, false, true)) || p.getMoveset(true).some(m => m && selfStatLowerMoves.includes(m.moveId)))).length;
|
||||
// If a party member has one of the above moves or abilities and doesn't have max herbs, the herb will appear more frequently
|
||||
return 0 * (weightMultiplier ? 2 : 1) + (weightMultiplier ? weightMultiplier * 0 : 0);
|
||||
@ -2225,7 +2244,7 @@ export class ModifierTypeOption {
|
||||
}
|
||||
|
||||
export function getPartyLuckValue(party: Pokemon[]): integer {
|
||||
const luck = Phaser.Math.Clamp(party.map(p => p.isFainted() ? 0 : p.getLuck())
|
||||
const luck = Phaser.Math.Clamp(party.map(p => p.isAllowedInBattle() ? p.getLuck() : 0)
|
||||
.reduce((total: integer, value: integer) => total += value, 0), 0, 14);
|
||||
return luck || 0;
|
||||
}
|
||||
|
@ -3,14 +3,12 @@ import BattleScene from "../battle-scene";
|
||||
import { getLevelTotalExp } from "../data/exp";
|
||||
import { MAX_PER_TYPE_POKEBALLS, PokeballType } from "../data/pokeball";
|
||||
import Pokemon, { PlayerPokemon } from "../field/pokemon";
|
||||
import { Stat } from "../data/pokemon-stat";
|
||||
import { addTextObject, TextStyle } from "../ui/text";
|
||||
import { Type } from "../data/type";
|
||||
import { EvolutionPhase } from "../phases/evolution-phase";
|
||||
import { FusionSpeciesFormEvolution, pokemonEvolutions, pokemonPrevolutions } from "../data/pokemon-evolutions";
|
||||
import { getPokemonNameWithAffix } from "../messages";
|
||||
import * as Utils from "../utils";
|
||||
import { TempBattleStat } from "../data/temp-battle-stat";
|
||||
import { getBerryEffectFunc, getBerryPredicate } from "../data/berry";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
@ -23,6 +21,7 @@ import Overrides from "#app/overrides";
|
||||
import { ModifierType, modifierTypes } from "./modifier-type";
|
||||
import { Command } from "#app/ui/command-ui-handler";
|
||||
import { Species } from "#enums/species";
|
||||
import { Stat, type PermanentStat, type TempBattleStat, BATTLE_STATS, TEMP_BATTLE_STATS } from "#app/enums/stat";
|
||||
import i18next from "i18next";
|
||||
|
||||
import { allMoves } from "#app/data/move";
|
||||
@ -362,41 +361,160 @@ export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier
|
||||
}
|
||||
}
|
||||
|
||||
export class TempBattleStatBoosterModifier extends LapsingPersistentModifier {
|
||||
private tempBattleStat: TempBattleStat;
|
||||
/**
|
||||
* Modifier used for party-wide items, specifically the X items, that
|
||||
* temporarily increases the stat stage multiplier of the corresponding
|
||||
* {@linkcode TempBattleStat}.
|
||||
* @extends LapsingPersistentModifier
|
||||
* @see {@linkcode apply}
|
||||
*/
|
||||
export class TempStatStageBoosterModifier extends LapsingPersistentModifier {
|
||||
private stat: TempBattleStat;
|
||||
private multiplierBoost: number;
|
||||
|
||||
constructor(type: ModifierTypes.TempBattleStatBoosterModifierType, tempBattleStat: TempBattleStat, battlesLeft?: integer, stackCount?: integer) {
|
||||
super(type, battlesLeft || 5, stackCount);
|
||||
constructor(type: ModifierType, stat: TempBattleStat, battlesLeft?: number, stackCount?: number) {
|
||||
super(type, battlesLeft ?? 5, stackCount);
|
||||
|
||||
this.tempBattleStat = tempBattleStat;
|
||||
this.stat = stat;
|
||||
// Note that, because we want X Accuracy to maintain its original behavior,
|
||||
// it will increment as it did previously, directly to the stat stage.
|
||||
this.multiplierBoost = stat !== Stat.ACC ? 0.3 : 1;
|
||||
}
|
||||
|
||||
match(modifier: Modifier): boolean {
|
||||
if (modifier instanceof TempBattleStatBoosterModifier) {
|
||||
return (modifier as TempBattleStatBoosterModifier).tempBattleStat === this.tempBattleStat
|
||||
&& (modifier as TempBattleStatBoosterModifier).battlesLeft === this.battlesLeft;
|
||||
if (modifier instanceof TempStatStageBoosterModifier) {
|
||||
const modifierInstance = modifier as TempStatStageBoosterModifier;
|
||||
return (modifierInstance.stat === this.stat);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
clone(): TempBattleStatBoosterModifier {
|
||||
return new TempBattleStatBoosterModifier(this.type as ModifierTypes.TempBattleStatBoosterModifierType, this.tempBattleStat, this.battlesLeft, this.stackCount);
|
||||
clone() {
|
||||
return new TempStatStageBoosterModifier(this.type, this.stat, this.battlesLeft, this.stackCount);
|
||||
}
|
||||
|
||||
getArgs(): any[] {
|
||||
return [ this.tempBattleStat, this.battlesLeft ];
|
||||
return [ this.stat, this.battlesLeft ];
|
||||
}
|
||||
|
||||
apply(args: any[]): boolean {
|
||||
const tempBattleStat = args[0] as TempBattleStat;
|
||||
/**
|
||||
* Checks if {@linkcode args} contains the necessary elements and if the
|
||||
* incoming stat is matches {@linkcode stat}.
|
||||
* @param args [0] {@linkcode TempBattleStat} being checked at the time
|
||||
* [1] {@linkcode Utils.NumberHolder} N/A
|
||||
* @returns true if the modifier can be applied, false otherwise
|
||||
*/
|
||||
shouldApply(args: any[]): boolean {
|
||||
return args && (args.length === 2) && TEMP_BATTLE_STATS.includes(args[0]) && (args[0] === this.stat) && (args[1] instanceof Utils.NumberHolder);
|
||||
}
|
||||
|
||||
if (tempBattleStat === this.tempBattleStat) {
|
||||
const statLevel = args[1] as Utils.IntegerHolder;
|
||||
statLevel.value = Math.min(statLevel.value + 1, 6);
|
||||
return true;
|
||||
/**
|
||||
* Increases the incoming stat stage matching {@linkcode stat} by {@linkcode multiplierBoost}.
|
||||
* @param args [0] {@linkcode TempBattleStat} N/A
|
||||
* [1] {@linkcode Utils.NumberHolder} that holds the resulting value of the stat stage multiplier
|
||||
*/
|
||||
apply(args: any[]): boolean {
|
||||
(args[1] as Utils.NumberHolder).value += this.multiplierBoost;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes through existing modifiers for any that match the selected modifier,
|
||||
* which will then either add it to the existing modifiers if none were found
|
||||
* or, if one was found, it will refresh {@linkcode battlesLeft}.
|
||||
* @param modifiers {@linkcode PersistentModifier} array of the player's modifiers
|
||||
* @param _virtual N/A
|
||||
* @param _scene N/A
|
||||
* @returns true if the modifier was successfully added or applied, false otherwise
|
||||
*/
|
||||
add(modifiers: PersistentModifier[], _virtual: boolean, _scene: BattleScene): boolean {
|
||||
for (const modifier of modifiers) {
|
||||
if (this.match(modifier)) {
|
||||
const modifierInstance = modifier as TempStatStageBoosterModifier;
|
||||
if (modifierInstance.getBattlesLeft() < 5) {
|
||||
modifierInstance.battlesLeft = 5;
|
||||
return true;
|
||||
}
|
||||
// should never get here
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
modifiers.push(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
getMaxStackCount(_scene: BattleScene, _forThreshold?: boolean): number {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifier used for party-wide items, namely Dire Hit, that
|
||||
* temporarily increments the critical-hit stage
|
||||
* @extends LapsingPersistentModifier
|
||||
* @see {@linkcode apply}
|
||||
*/
|
||||
export class TempCritBoosterModifier extends LapsingPersistentModifier {
|
||||
constructor(type: ModifierType, battlesLeft?: integer, stackCount?: number) {
|
||||
super(type, battlesLeft || 5, stackCount);
|
||||
}
|
||||
|
||||
clone() {
|
||||
return new TempCritBoosterModifier(this.type, this.stackCount);
|
||||
}
|
||||
|
||||
match(modifier: Modifier): boolean {
|
||||
return (modifier instanceof TempCritBoosterModifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if {@linkcode args} contains the necessary elements.
|
||||
* @param args [1] {@linkcode Utils.NumberHolder} N/A
|
||||
* @returns true if the critical-hit stage boost applies successfully
|
||||
*/
|
||||
shouldApply(args: any[]): boolean {
|
||||
return args && (args.length === 1) && (args[0] instanceof Utils.NumberHolder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the current critical-hit stage value by 1.
|
||||
* @param args [0] {@linkcode Utils.IntegerHolder} that holds the resulting critical-hit level
|
||||
* @returns true if the critical-hit stage boost applies successfully
|
||||
*/
|
||||
apply(args: any[]): boolean {
|
||||
(args[0] as Utils.NumberHolder).value++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes through existing modifiers for any that match the selected modifier,
|
||||
* which will then either add it to the existing modifiers if none were found
|
||||
* or, if one was found, it will refresh {@linkcode battlesLeft}.
|
||||
* @param modifiers {@linkcode PersistentModifier} array of the player's modifiers
|
||||
* @param _virtual N/A
|
||||
* @param _scene N/A
|
||||
* @returns true if the modifier was successfully added or applied, false otherwise
|
||||
*/
|
||||
add(modifiers: PersistentModifier[], _virtual: boolean, _scene: BattleScene): boolean {
|
||||
for (const modifier of modifiers) {
|
||||
if (this.match(modifier)) {
|
||||
const modifierInstance = modifier as TempCritBoosterModifier;
|
||||
if (modifierInstance.getBattlesLeft() < 5) {
|
||||
modifierInstance.battlesLeft = 5;
|
||||
return true;
|
||||
}
|
||||
// should never get here
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
modifiers.push(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
getMaxStackCount(_scene: BattleScene, _forThreshold?: boolean): number {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -663,24 +781,30 @@ export class TerastallizeModifier extends LapsingPokemonHeldItemModifier {
|
||||
}
|
||||
}
|
||||
|
||||
export class PokemonBaseStatModifier extends PokemonHeldItemModifier {
|
||||
protected stat: Stat;
|
||||
/**
|
||||
* Modifier used for held items, specifically vitamins like Carbos, Hp Up, etc., that
|
||||
* increase the value of a given {@linkcode PermanentStat}.
|
||||
* @extends LapsingPersistentModifier
|
||||
* @see {@linkcode apply}
|
||||
*/
|
||||
export class BaseStatModifier extends PokemonHeldItemModifier {
|
||||
protected stat: PermanentStat;
|
||||
readonly isTransferrable: boolean = false;
|
||||
|
||||
constructor(type: ModifierTypes.PokemonBaseStatBoosterModifierType, pokemonId: integer, stat: Stat, stackCount?: integer) {
|
||||
constructor(type: ModifierType, pokemonId: integer, stat: PermanentStat, stackCount?: integer) {
|
||||
super(type, pokemonId, stackCount);
|
||||
this.stat = stat;
|
||||
}
|
||||
|
||||
matchType(modifier: Modifier): boolean {
|
||||
if (modifier instanceof PokemonBaseStatModifier) {
|
||||
return (modifier as PokemonBaseStatModifier).stat === this.stat;
|
||||
if (modifier instanceof BaseStatModifier) {
|
||||
return (modifier as BaseStatModifier).stat === this.stat;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
clone(): PersistentModifier {
|
||||
return new PokemonBaseStatModifier(this.type as ModifierTypes.PokemonBaseStatBoosterModifierType, this.pokemonId, this.stat, this.stackCount);
|
||||
return new BaseStatModifier(this.type, this.pokemonId, this.stat, this.stackCount);
|
||||
}
|
||||
|
||||
getArgs(): any[] {
|
||||
@ -688,12 +812,12 @@ export class PokemonBaseStatModifier extends PokemonHeldItemModifier {
|
||||
}
|
||||
|
||||
shouldApply(args: any[]): boolean {
|
||||
return super.shouldApply(args) && args.length === 2 && args[1] instanceof Array;
|
||||
return super.shouldApply(args) && args.length === 2 && Array.isArray(args[1]);
|
||||
}
|
||||
|
||||
apply(args: any[]): boolean {
|
||||
args[1][this.stat] = Math.min(Math.floor(args[1][this.stat] * (1 + this.getStackCount() * 0.1)), 999999);
|
||||
|
||||
const baseStats = args[1] as number[];
|
||||
baseStats[this.stat] = Math.floor(baseStats[this.stat] * (1 + this.getStackCount() * 0.1));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1398,42 +1522,48 @@ export class PokemonInstantReviveModifier extends PokemonHeldItemModifier {
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifier used for White Herb, which resets negative {@linkcode Stat} changes
|
||||
* Modifier used for held items, namely White Herb, that restore adverse stat
|
||||
* stages in battle.
|
||||
* @extends PokemonHeldItemModifier
|
||||
* @see {@linkcode apply}
|
||||
*/
|
||||
export class PokemonResetNegativeStatStageModifier extends PokemonHeldItemModifier {
|
||||
export class ResetNegativeStatStageModifier extends PokemonHeldItemModifier {
|
||||
constructor(type: ModifierType, pokemonId: integer, stackCount?: integer) {
|
||||
super(type, pokemonId, stackCount);
|
||||
}
|
||||
|
||||
matchType(modifier: Modifier) {
|
||||
return modifier instanceof PokemonResetNegativeStatStageModifier;
|
||||
return modifier instanceof ResetNegativeStatStageModifier;
|
||||
}
|
||||
|
||||
clone() {
|
||||
return new PokemonResetNegativeStatStageModifier(this.type, this.pokemonId, this.stackCount);
|
||||
return new ResetNegativeStatStageModifier(this.type, this.pokemonId, this.stackCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores any negative stat stages of the mon to 0
|
||||
* @param args args[0] is the {@linkcode Pokemon} whose stat stages are being checked
|
||||
* @returns true if any stat changes were applied (item was used), false otherwise
|
||||
* Goes through the holder's stat stages and, if any are negative, resets that
|
||||
* stat stage back to 0.
|
||||
* @param args [0] {@linkcode Pokemon} that holds the held item
|
||||
* @returns true if any stat stages were reset, false otherwise
|
||||
*/
|
||||
apply(args: any[]): boolean {
|
||||
const pokemon = args[0] as Pokemon;
|
||||
const loweredStats = pokemon.summonData.battleStats.filter(s => s < 0);
|
||||
if (loweredStats.length) {
|
||||
for (let s = 0; s < pokemon.summonData.battleStats.length; s++) {
|
||||
pokemon.summonData.battleStats[s] = Math.max(0, pokemon.summonData.battleStats[s]);
|
||||
let statRestored = false;
|
||||
|
||||
for (const s of BATTLE_STATS) {
|
||||
if (pokemon.getStatStage(s) < 0) {
|
||||
pokemon.setStatStage(s, 0);
|
||||
statRestored = true;
|
||||
}
|
||||
pokemon.scene.queueMessage(i18next.t("modifier:pokemonResetNegativeStatStageApply", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), typeName: this.type.name }));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
if (statRestored) {
|
||||
pokemon.scene.queueMessage(i18next.t("modifier:resetNegativeStatStageApply", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), typeName: this.type.name }));
|
||||
}
|
||||
return statRestored;
|
||||
}
|
||||
|
||||
getMaxHeldItemCount(pokemon: Pokemon): integer {
|
||||
getMaxHeldItemCount(_pokemon: Pokemon): integer {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
@ -1625,7 +1755,7 @@ export class TmModifier extends ConsumablePokemonModifier {
|
||||
apply(args: any[]): boolean {
|
||||
const pokemon = args[0] as PlayerPokemon;
|
||||
|
||||
pokemon.scene.unshiftPhase(new LearnMovePhase(pokemon.scene, pokemon.scene.getParty().indexOf(pokemon), (this.type as ModifierTypes.TmModifierType).moveId));
|
||||
pokemon.scene.unshiftPhase(new LearnMovePhase(pokemon.scene, pokemon.scene.getParty().indexOf(pokemon), (this.type as ModifierTypes.TmModifierType).moveId, true));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -2745,7 +2875,7 @@ export class EnemyFusionChanceModifier extends EnemyPersistentModifier {
|
||||
* - The player
|
||||
* - The enemy
|
||||
* @param scene current {@linkcode BattleScene}
|
||||
* @param isPlayer {@linkcode boolean} for whether the the player (`true`) or enemy (`false`) is being overridden
|
||||
* @param isPlayer {@linkcode boolean} for whether the player (`true`) or enemy (`false`) is being overridden
|
||||
*/
|
||||
export function overrideModifiers(scene: BattleScene, isPlayer: boolean = true): void {
|
||||
const modifiersOverride: ModifierTypes.ModifierOverride[] = isPlayer ? Overrides.STARTING_MODIFIER_OVERRIDE : Overrides.OPP_MODIFIER_OVERRIDE;
|
||||
@ -2760,13 +2890,22 @@ export function overrideModifiers(scene: BattleScene, isPlayer: boolean = true):
|
||||
|
||||
modifiersOverride.forEach(item => {
|
||||
const modifierFunc = modifierTypes[item.name];
|
||||
const modifier = modifierFunc().withIdFromFunc(modifierFunc).newModifier() as PersistentModifier;
|
||||
modifier.stackCount = item.count || 1;
|
||||
let modifierType: ModifierType | null = modifierFunc();
|
||||
|
||||
if (isPlayer) {
|
||||
scene.addModifier(modifier, true, false, false, true);
|
||||
} else {
|
||||
scene.addEnemyModifier(modifier, true, true);
|
||||
if (modifierType instanceof ModifierTypes.ModifierTypeGenerator) {
|
||||
const pregenArgs = ("type" in item) && (item.type !== null) ? [item.type] : undefined;
|
||||
modifierType = modifierType.generateType([], pregenArgs);
|
||||
}
|
||||
|
||||
const modifier = modifierType && modifierType.withIdFromFunc(modifierFunc).newModifier() as PersistentModifier;
|
||||
if (modifier) {
|
||||
modifier.stackCount = item.count || 1;
|
||||
|
||||
if (isPlayer) {
|
||||
scene.addModifier(modifier, true, false, false, true);
|
||||
} else {
|
||||
scene.addEnemyModifier(modifier, true, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -116,6 +116,14 @@ class DefaultOverrides {
|
||||
readonly OPP_VARIANT_OVERRIDE: Variant = 0;
|
||||
readonly OPP_IVS_OVERRIDE: number | number[] = [];
|
||||
readonly OPP_FORM_OVERRIDES: Partial<Record<Species, number>> = {};
|
||||
/**
|
||||
* Override to give the enemy Pokemon a given amount of health segments
|
||||
*
|
||||
* 0 (default): the health segments will be handled normally based on wave, level and species
|
||||
* 1: the Pokemon will have a single health segment and therefore will not be a boss
|
||||
* 2+: the Pokemon will be a boss with the given number of health segments
|
||||
*/
|
||||
readonly OPP_HEALTH_SEGMENTS_OVERRIDE: number = 0;
|
||||
|
||||
// -------------
|
||||
// EGG OVERRIDES
|
||||
|
@ -26,6 +26,7 @@ import { ScanIvsPhase } from "./scan-ivs-phase";
|
||||
import { ShinySparklePhase } from "./shiny-sparkle-phase";
|
||||
import { SummonPhase } from "./summon-phase";
|
||||
import { ToggleDoublePositionPhase } from "./toggle-double-position-phase";
|
||||
import Overrides from "#app/overrides";
|
||||
|
||||
export class EncounterPhase extends BattlePhase {
|
||||
private loaded: boolean;
|
||||
@ -112,10 +113,11 @@ export class EncounterPhase extends BattlePhase {
|
||||
if (battle.battleType === BattleType.TRAINER) {
|
||||
loadEnemyAssets.push(battle.trainer?.loadAssets().then(() => battle.trainer?.initSprite())!); // TODO: is this bang correct?
|
||||
} else {
|
||||
// This block only applies for double battles to init the boss segments (idk why it's split up like this)
|
||||
if (battle.enemyParty.filter(p => p.isBoss()).length > 1) {
|
||||
const overridedBossSegments = Overrides.OPP_HEALTH_SEGMENTS_OVERRIDE > 1;
|
||||
// for double battles, reduce the health segments for boss Pokemon unless there is an override
|
||||
if (!overridedBossSegments && battle.enemyParty.filter(p => p.isBoss()).length > 1) {
|
||||
for (const enemyPokemon of battle.enemyParty) {
|
||||
// If the enemy pokemon is a boss and wasn't populated from data source, then set it up
|
||||
// If the enemy pokemon is a boss and wasn't populated from data source, then update the number of segments
|
||||
if (enemyPokemon.isBoss() && !enemyPokemon.isPopulatedFromDataSource) {
|
||||
enemyPokemon.setBoss(true, Math.ceil(enemyPokemon.bossSegments * (enemyPokemon.getSpeciesForm().baseTotal / totalBst)));
|
||||
enemyPokemon.initBattleInfo();
|
||||
|
@ -1,14 +1,14 @@
|
||||
import BattleScene from "#app/battle-scene.js";
|
||||
import { BattlerIndex, BattleType } from "#app/battle.js";
|
||||
import { applyPostFaintAbAttrs, PostFaintAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr } from "#app/data/ability.js";
|
||||
import { BattlerTagLapseType } from "#app/data/battler-tags.js";
|
||||
import { battleSpecDialogue } from "#app/data/dialogue.js";
|
||||
import { allMoves, PostVictoryStatChangeAttr } from "#app/data/move.js";
|
||||
import { BattleSpec } from "#app/enums/battle-spec.js";
|
||||
import { StatusEffect } from "#app/enums/status-effect.js";
|
||||
import { PokemonMove, EnemyPokemon, PlayerPokemon, HitResult } from "#app/field/pokemon.js";
|
||||
import { getPokemonNameWithAffix } from "#app/messages.js";
|
||||
import { PokemonInstantReviveModifier } from "#app/modifier/modifier.js";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { BattlerIndex, BattleType } from "#app/battle";
|
||||
import { applyPostFaintAbAttrs, PostFaintAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr } from "#app/data/ability";
|
||||
import { BattlerTagLapseType } from "#app/data/battler-tags";
|
||||
import { battleSpecDialogue } from "#app/data/dialogue";
|
||||
import { allMoves, PostVictoryStatStageChangeAttr } from "#app/data/move";
|
||||
import { BattleSpec } from "#app/enums/battle-spec";
|
||||
import { StatusEffect } from "#app/enums/status-effect";
|
||||
import { PokemonMove, EnemyPokemon, PlayerPokemon, HitResult } from "#app/field/pokemon";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { PokemonInstantReviveModifier } from "#app/modifier/modifier";
|
||||
import i18next from "i18next";
|
||||
import { DamagePhase } from "./damage-phase";
|
||||
import { PokemonPhase } from "./pokemon-phase";
|
||||
@ -72,7 +72,7 @@ export class FaintPhase extends PokemonPhase {
|
||||
if (defeatSource?.isOnField()) {
|
||||
applyPostVictoryAbAttrs(PostVictoryAbAttr, defeatSource);
|
||||
const pvmove = allMoves[pokemon.turnData.attacksReceived[0].move];
|
||||
const pvattrs = pvmove.getAttrs(PostVictoryStatChangeAttr);
|
||||
const pvattrs = pvmove.getAttrs(PostVictoryStatStageChangeAttr);
|
||||
if (pvattrs.length) {
|
||||
for (const pvattr of pvattrs) {
|
||||
pvattr.applyPostVictory(defeatSource, defeatSource, pvmove);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Pokemon from "#app/field/pokemon.js";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
import Pokemon from "#app/field/pokemon";
|
||||
|
||||
type PokemonFunc = (pokemon: Pokemon) => void;
|
||||
|
||||
|
@ -12,11 +12,13 @@ import { PlayerPartyMemberPokemonPhase } from "./player-party-member-pokemon-pha
|
||||
|
||||
export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
||||
private moveId: Moves;
|
||||
private fromTM: boolean;
|
||||
|
||||
constructor(scene: BattleScene, partyMemberIndex: integer, moveId: Moves) {
|
||||
constructor(scene: BattleScene, partyMemberIndex: integer, moveId: Moves, fromTM?: boolean) {
|
||||
super(scene, partyMemberIndex);
|
||||
|
||||
this.moveId = moveId;
|
||||
this.fromTM = fromTM ?? false;
|
||||
}
|
||||
|
||||
start() {
|
||||
@ -41,6 +43,9 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
||||
|
||||
if (emptyMoveIndex > -1) {
|
||||
pokemon.setMove(emptyMoveIndex, this.moveId);
|
||||
if (this.fromTM) {
|
||||
pokemon.usedTMs.push(this.moveId);
|
||||
}
|
||||
initMoveAnim(this.scene, this.moveId).then(() => {
|
||||
loadMoveAnimAssets(this.scene, [this.moveId], true)
|
||||
.then(() => {
|
||||
@ -85,6 +90,9 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
||||
this.scene.ui.showText(i18next.t("battle:countdownPoof"), null, () => {
|
||||
this.scene.ui.showText(i18next.t("battle:learnMoveForgetSuccess", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: pokemon.moveset[moveIndex]!.getName() }), null, () => { // TODO: is the bang correct?
|
||||
this.scene.ui.showText(i18next.t("battle:learnMoveAnd"), null, () => {
|
||||
if (this.fromTM) {
|
||||
pokemon.usedTMs.push(this.moveId);
|
||||
}
|
||||
pokemon.setMove(moveIndex, Moves.NONE);
|
||||
this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId));
|
||||
this.end();
|
||||
|
@ -1,248 +0,0 @@
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { applyAbAttrs, applyPostStatChangeAbAttrs, applyPreStatChangeAbAttrs, PostStatChangeAbAttr, ProtectStatAbAttr, StatChangeCopyAbAttr, StatChangeMultiplierAbAttr } from "#app/data/ability";
|
||||
import { ArenaTagSide, MistTag } from "#app/data/arena-tag";
|
||||
import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "#app/data/battle-stat";
|
||||
import Pokemon from "#app/field/pokemon";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { PokemonResetNegativeStatStageModifier } from "#app/modifier/modifier";
|
||||
import { handleTutorial, Tutorial } from "#app/tutorial";
|
||||
import * as Utils from "#app/utils";
|
||||
import i18next from "i18next";
|
||||
import { PokemonPhase } from "./pokemon-phase";
|
||||
|
||||
export type StatChangeCallback = (target: Pokemon | null, changed: BattleStat[], relativeChanges: number[]) => void;
|
||||
|
||||
export class StatChangePhase extends PokemonPhase {
|
||||
private stats: BattleStat[];
|
||||
private selfTarget: boolean;
|
||||
private levels: integer;
|
||||
private showMessage: boolean;
|
||||
private ignoreAbilities: boolean;
|
||||
private canBeCopied: boolean;
|
||||
private onChange: StatChangeCallback | null;
|
||||
|
||||
|
||||
constructor(scene: BattleScene, battlerIndex: BattlerIndex, selfTarget: boolean, stats: BattleStat[], levels: integer, showMessage: boolean = true, ignoreAbilities: boolean = false, canBeCopied: boolean = true, onChange: StatChangeCallback | null = null) {
|
||||
super(scene, battlerIndex);
|
||||
|
||||
this.selfTarget = selfTarget;
|
||||
this.stats = stats;
|
||||
this.levels = levels;
|
||||
this.showMessage = showMessage;
|
||||
this.ignoreAbilities = ignoreAbilities;
|
||||
this.canBeCopied = canBeCopied;
|
||||
this.onChange = onChange;
|
||||
}
|
||||
|
||||
start() {
|
||||
const pokemon = this.getPokemon();
|
||||
|
||||
let random = false;
|
||||
|
||||
if (this.stats.length === 1 && this.stats[0] === BattleStat.RAND) {
|
||||
this.stats[0] = this.getRandomStat();
|
||||
random = true;
|
||||
}
|
||||
|
||||
this.aggregateStatChanges(random);
|
||||
|
||||
if (!pokemon.isActive(true)) {
|
||||
return this.end();
|
||||
}
|
||||
|
||||
const filteredStats = this.stats.map(s => s !== BattleStat.RAND ? s : this.getRandomStat()).filter(stat => {
|
||||
const cancelled = new Utils.BooleanHolder(false);
|
||||
|
||||
if (!this.selfTarget && this.levels < 0) {
|
||||
this.scene.arena.applyTagsForSide(MistTag, pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, cancelled);
|
||||
}
|
||||
|
||||
if (!cancelled.value && !this.selfTarget && this.levels < 0) {
|
||||
applyPreStatChangeAbAttrs(ProtectStatAbAttr, this.getPokemon(), stat, cancelled);
|
||||
}
|
||||
|
||||
return !cancelled.value;
|
||||
});
|
||||
|
||||
const levels = new Utils.IntegerHolder(this.levels);
|
||||
|
||||
if (!this.ignoreAbilities) {
|
||||
applyAbAttrs(StatChangeMultiplierAbAttr, pokemon, null, false, levels);
|
||||
}
|
||||
|
||||
const battleStats = this.getPokemon().summonData.battleStats;
|
||||
const relLevels = filteredStats.map(stat => (levels.value >= 1 ? Math.min(battleStats[stat] + levels.value, 6) : Math.max(battleStats[stat] + levels.value, -6)) - battleStats[stat]);
|
||||
|
||||
this.onChange && this.onChange(this.getPokemon(), filteredStats, relLevels);
|
||||
|
||||
const end = () => {
|
||||
if (this.showMessage) {
|
||||
const messages = this.getStatChangeMessages(filteredStats, levels.value, relLevels);
|
||||
for (const message of messages) {
|
||||
this.scene.queueMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
for (const stat of filteredStats) {
|
||||
if (levels.value > 0 && pokemon.summonData.battleStats[stat] < 6) {
|
||||
if (!pokemon.turnData) {
|
||||
// Temporary fix for missing turn data struct on turn 1
|
||||
pokemon.resetTurnData();
|
||||
}
|
||||
pokemon.turnData.battleStatsIncreased = true;
|
||||
} else if (levels.value < 0 && pokemon.summonData.battleStats[stat] > -6) {
|
||||
if (!pokemon.turnData) {
|
||||
// Temporary fix for missing turn data struct on turn 1
|
||||
pokemon.resetTurnData();
|
||||
}
|
||||
pokemon.turnData.battleStatsDecreased = true;
|
||||
}
|
||||
|
||||
pokemon.summonData.battleStats[stat] = Math.max(Math.min(pokemon.summonData.battleStats[stat] + levels.value, 6), -6);
|
||||
}
|
||||
|
||||
if (levels.value > 0 && this.canBeCopied) {
|
||||
for (const opponent of pokemon.getOpponents()) {
|
||||
applyAbAttrs(StatChangeCopyAbAttr, opponent, null, false, this.stats, levels.value);
|
||||
}
|
||||
}
|
||||
|
||||
applyPostStatChangeAbAttrs(PostStatChangeAbAttr, pokemon, filteredStats, this.levels, this.selfTarget);
|
||||
|
||||
// Look for any other stat change phases; if this is the last one, do White Herb check
|
||||
const existingPhase = this.scene.findPhase(p => p instanceof StatChangePhase && p.battlerIndex === this.battlerIndex);
|
||||
if (!(existingPhase instanceof StatChangePhase)) {
|
||||
// Apply White Herb if needed
|
||||
const whiteHerb = this.scene.applyModifier(PokemonResetNegativeStatStageModifier, this.player, pokemon) as PokemonResetNegativeStatStageModifier;
|
||||
// If the White Herb was applied, consume it
|
||||
if (whiteHerb) {
|
||||
--whiteHerb.stackCount;
|
||||
if (whiteHerb.stackCount <= 0) {
|
||||
this.scene.removeModifier(whiteHerb);
|
||||
}
|
||||
this.scene.updateModifiers(this.player);
|
||||
}
|
||||
}
|
||||
|
||||
pokemon.updateInfo();
|
||||
|
||||
handleTutorial(this.scene, Tutorial.Stat_Change).then(() => super.end());
|
||||
};
|
||||
|
||||
if (relLevels.filter(l => l).length && this.scene.moveAnimations) {
|
||||
pokemon.enableMask();
|
||||
const pokemonMaskSprite = pokemon.maskSprite;
|
||||
|
||||
const tileX = (this.player ? 106 : 236) * pokemon.getSpriteScale() * this.scene.field.scale;
|
||||
const tileY = ((this.player ? 148 : 84) + (levels.value >= 1 ? 160 : 0)) * pokemon.getSpriteScale() * this.scene.field.scale;
|
||||
const tileWidth = 156 * this.scene.field.scale * pokemon.getSpriteScale();
|
||||
const tileHeight = 316 * this.scene.field.scale * pokemon.getSpriteScale();
|
||||
|
||||
// On increase, show the red sprite located at ATK
|
||||
// On decrease, show the blue sprite located at SPD
|
||||
const spriteColor = levels.value >= 1 ? BattleStat[BattleStat.ATK].toLowerCase() : BattleStat[BattleStat.SPD].toLowerCase();
|
||||
const statSprite = this.scene.add.tileSprite(tileX, tileY, tileWidth, tileHeight, "battle_stats", spriteColor);
|
||||
statSprite.setPipeline(this.scene.fieldSpritePipeline);
|
||||
statSprite.setAlpha(0);
|
||||
statSprite.setScale(6);
|
||||
statSprite.setOrigin(0.5, 1);
|
||||
|
||||
this.scene.playSound(`se/stat_${levels.value >= 1 ? "up" : "down"}`);
|
||||
|
||||
statSprite.setMask(new Phaser.Display.Masks.BitmapMask(this.scene, pokemonMaskSprite ?? undefined));
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: statSprite,
|
||||
duration: 250,
|
||||
alpha: 0.8375,
|
||||
onComplete: () => {
|
||||
this.scene.tweens.add({
|
||||
targets: statSprite,
|
||||
delay: 1000,
|
||||
duration: 250,
|
||||
alpha: 0
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: statSprite,
|
||||
duration: 1500,
|
||||
y: `${levels.value >= 1 ? "-" : "+"}=${160 * 6}`
|
||||
});
|
||||
|
||||
this.scene.time.delayedCall(1750, () => {
|
||||
pokemon.disableMask();
|
||||
end();
|
||||
});
|
||||
} else {
|
||||
end();
|
||||
}
|
||||
}
|
||||
|
||||
getRandomStat(): BattleStat {
|
||||
const allStats = Utils.getEnumValues(BattleStat);
|
||||
return this.getPokemon() ? allStats[this.getPokemon()!.randSeedInt(BattleStat.SPD + 1)] : BattleStat.ATK; // TODO: return default ATK on random? idk...
|
||||
}
|
||||
|
||||
aggregateStatChanges(random: boolean = false): void {
|
||||
const isAccEva = [BattleStat.ACC, BattleStat.EVA].some(s => this.stats.includes(s));
|
||||
let existingPhase: StatChangePhase;
|
||||
if (this.stats.length === 1) {
|
||||
while ((existingPhase = (this.scene.findPhase(p => p instanceof StatChangePhase && p.battlerIndex === this.battlerIndex && p.stats.length === 1
|
||||
&& (p.stats[0] === this.stats[0] || (random && p.stats[0] === BattleStat.RAND))
|
||||
&& p.selfTarget === this.selfTarget && p.showMessage === this.showMessage && p.ignoreAbilities === this.ignoreAbilities) as StatChangePhase))) {
|
||||
if (existingPhase.stats[0] === BattleStat.RAND) {
|
||||
existingPhase.stats[0] = this.getRandomStat();
|
||||
if (existingPhase.stats[0] !== this.stats[0]) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
this.levels += existingPhase.levels;
|
||||
|
||||
if (!this.scene.tryRemovePhase(p => p === existingPhase)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while ((existingPhase = (this.scene.findPhase(p => p instanceof StatChangePhase && p.battlerIndex === this.battlerIndex && p.selfTarget === this.selfTarget
|
||||
&& ([BattleStat.ACC, BattleStat.EVA].some(s => p.stats.includes(s)) === isAccEva)
|
||||
&& p.levels === this.levels && p.showMessage === this.showMessage && p.ignoreAbilities === this.ignoreAbilities) as StatChangePhase))) {
|
||||
this.stats.push(...existingPhase.stats);
|
||||
if (!this.scene.tryRemovePhase(p => p === existingPhase)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getStatChangeMessages(stats: BattleStat[], levels: integer, relLevels: integer[]): string[] {
|
||||
const messages: string[] = [];
|
||||
|
||||
const relLevelStatIndexes = {};
|
||||
for (let rl = 0; rl < relLevels.length; rl++) {
|
||||
const relLevel = relLevels[rl];
|
||||
if (!relLevelStatIndexes[relLevel]) {
|
||||
relLevelStatIndexes[relLevel] = [];
|
||||
}
|
||||
relLevelStatIndexes[relLevel].push(rl);
|
||||
}
|
||||
|
||||
Object.keys(relLevelStatIndexes).forEach(rl => {
|
||||
const relLevelStats = stats.filter((_, i) => relLevelStatIndexes[rl].includes(i));
|
||||
let statsFragment = "";
|
||||
|
||||
if (relLevelStats.length > 1) {
|
||||
statsFragment = relLevelStats.length >= 5
|
||||
? i18next.t("battle:stats")
|
||||
: `${relLevelStats.slice(0, -1).map(s => getBattleStatName(s)).join(", ")}${relLevelStats.length > 2 ? "," : ""} ${i18next.t("battle:statsAnd")} ${getBattleStatName(relLevelStats[relLevelStats.length - 1])}`;
|
||||
messages.push(getBattleStatLevelChangeDescription(getPokemonNameWithAffix(this.getPokemon()), statsFragment, Math.abs(parseInt(rl)), levels >= 1, relLevelStats.length));
|
||||
} else {
|
||||
statsFragment = getBattleStatName(relLevelStats[0]);
|
||||
messages.push(getBattleStatLevelChangeDescription(getPokemonNameWithAffix(this.getPokemon()), statsFragment, Math.abs(parseInt(rl)), levels >= 1, relLevelStats.length));
|
||||
}
|
||||
});
|
||||
|
||||
return messages;
|
||||
}
|
||||
}
|
244
src/phases/stat-stage-change-phase.ts
Normal file
244
src/phases/stat-stage-change-phase.ts
Normal file
@ -0,0 +1,244 @@
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { applyAbAttrs, applyPostStatStageChangeAbAttrs, applyPreStatStageChangeAbAttrs, PostStatStageChangeAbAttr, ProtectStatAbAttr, StatStageChangeCopyAbAttr, StatStageChangeMultiplierAbAttr } from "#app/data/ability";
|
||||
import { ArenaTagSide, MistTag } from "#app/data/arena-tag";
|
||||
import Pokemon from "#app/field/pokemon";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { ResetNegativeStatStageModifier } from "#app/modifier/modifier";
|
||||
import { handleTutorial, Tutorial } from "#app/tutorial";
|
||||
import * as Utils from "#app/utils";
|
||||
import i18next from "i18next";
|
||||
import { PokemonPhase } from "./pokemon-phase";
|
||||
import { Stat, type BattleStat, getStatKey, getStatStageChangeDescriptionKey } from "#enums/stat";
|
||||
|
||||
export type StatStageChangeCallback = (target: Pokemon | null, changed: BattleStat[], relativeChanges: number[]) => void;
|
||||
|
||||
export class StatStageChangePhase extends PokemonPhase {
|
||||
private stats: BattleStat[];
|
||||
private selfTarget: boolean;
|
||||
private stages: integer;
|
||||
private showMessage: boolean;
|
||||
private ignoreAbilities: boolean;
|
||||
private canBeCopied: boolean;
|
||||
private onChange: StatStageChangeCallback | null;
|
||||
|
||||
|
||||
constructor(scene: BattleScene, battlerIndex: BattlerIndex, selfTarget: boolean, stats: BattleStat[], stages: integer, showMessage: boolean = true, ignoreAbilities: boolean = false, canBeCopied: boolean = true, onChange: StatStageChangeCallback | null = null) {
|
||||
super(scene, battlerIndex);
|
||||
|
||||
this.selfTarget = selfTarget;
|
||||
this.stats = stats;
|
||||
this.stages = stages;
|
||||
this.showMessage = showMessage;
|
||||
this.ignoreAbilities = ignoreAbilities;
|
||||
this.canBeCopied = canBeCopied;
|
||||
this.onChange = onChange;
|
||||
}
|
||||
|
||||
start() {
|
||||
const pokemon = this.getPokemon();
|
||||
|
||||
if (!pokemon.isActive(true)) {
|
||||
return this.end();
|
||||
}
|
||||
|
||||
let simulate = false;
|
||||
|
||||
const filteredStats = this.stats.filter(stat => {
|
||||
const cancelled = new Utils.BooleanHolder(false);
|
||||
|
||||
if (!this.selfTarget && this.stages < 0) {
|
||||
// TODO: Include simulate boolean when tag applications can be simulated
|
||||
this.scene.arena.applyTagsForSide(MistTag, pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, cancelled);
|
||||
}
|
||||
|
||||
if (!cancelled.value && !this.selfTarget && this.stages < 0) {
|
||||
applyPreStatStageChangeAbAttrs(ProtectStatAbAttr, pokemon, stat, cancelled, simulate);
|
||||
}
|
||||
|
||||
// If one stat stage decrease is cancelled, simulate the rest of the applications
|
||||
if (cancelled.value) {
|
||||
simulate = true;
|
||||
}
|
||||
|
||||
return !cancelled.value;
|
||||
});
|
||||
|
||||
const stages = new Utils.IntegerHolder(this.stages);
|
||||
|
||||
if (!this.ignoreAbilities) {
|
||||
applyAbAttrs(StatStageChangeMultiplierAbAttr, pokemon, null, false, stages);
|
||||
}
|
||||
|
||||
const relLevels = filteredStats.map(s => (stages.value >= 1 ? Math.min(pokemon.getStatStage(s) + stages.value, 6) : Math.max(pokemon.getStatStage(s) + stages.value, -6)) - pokemon.getStatStage(s));
|
||||
|
||||
this.onChange && this.onChange(this.getPokemon(), filteredStats, relLevels);
|
||||
|
||||
const end = () => {
|
||||
if (this.showMessage) {
|
||||
const messages = this.getStatStageChangeMessages(filteredStats, stages.value, relLevels);
|
||||
for (const message of messages) {
|
||||
this.scene.queueMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
for (const s of filteredStats) {
|
||||
if (stages.value > 0 && pokemon.getStatStage(s) < 6) {
|
||||
if (!pokemon.turnData) {
|
||||
// Temporary fix for missing turn data struct on turn 1
|
||||
pokemon.resetTurnData();
|
||||
}
|
||||
pokemon.turnData.statStagesIncreased = true;
|
||||
} else if (stages.value < 0 && pokemon.getStatStage(s) > -6) {
|
||||
if (!pokemon.turnData) {
|
||||
// Temporary fix for missing turn data struct on turn 1
|
||||
pokemon.resetTurnData();
|
||||
}
|
||||
pokemon.turnData.statStagesDecreased = true;
|
||||
}
|
||||
|
||||
pokemon.setStatStage(s, pokemon.getStatStage(s) + stages.value);
|
||||
}
|
||||
|
||||
if (stages.value > 0 && this.canBeCopied) {
|
||||
for (const opponent of pokemon.getOpponents()) {
|
||||
applyAbAttrs(StatStageChangeCopyAbAttr, opponent, null, false, this.stats, stages.value);
|
||||
}
|
||||
}
|
||||
|
||||
applyPostStatStageChangeAbAttrs(PostStatStageChangeAbAttr, pokemon, filteredStats, this.stages, this.selfTarget);
|
||||
|
||||
// Look for any other stat change phases; if this is the last one, do White Herb check
|
||||
const existingPhase = this.scene.findPhase(p => p instanceof StatStageChangePhase && p.battlerIndex === this.battlerIndex);
|
||||
if (!(existingPhase instanceof StatStageChangePhase)) {
|
||||
// Apply White Herb if needed
|
||||
const whiteHerb = this.scene.applyModifier(ResetNegativeStatStageModifier, this.player, pokemon) as ResetNegativeStatStageModifier;
|
||||
// If the White Herb was applied, consume it
|
||||
if (whiteHerb) {
|
||||
whiteHerb.stackCount--;
|
||||
if (whiteHerb.stackCount <= 0) {
|
||||
this.scene.removeModifier(whiteHerb);
|
||||
}
|
||||
this.scene.updateModifiers(this.player);
|
||||
}
|
||||
}
|
||||
|
||||
pokemon.updateInfo();
|
||||
|
||||
handleTutorial(this.scene, Tutorial.Stat_Change).then(() => super.end());
|
||||
};
|
||||
|
||||
if (relLevels.filter(l => l).length && this.scene.moveAnimations) {
|
||||
pokemon.enableMask();
|
||||
const pokemonMaskSprite = pokemon.maskSprite;
|
||||
|
||||
const tileX = (this.player ? 106 : 236) * pokemon.getSpriteScale() * this.scene.field.scale;
|
||||
const tileY = ((this.player ? 148 : 84) + (stages.value >= 1 ? 160 : 0)) * pokemon.getSpriteScale() * this.scene.field.scale;
|
||||
const tileWidth = 156 * this.scene.field.scale * pokemon.getSpriteScale();
|
||||
const tileHeight = 316 * this.scene.field.scale * pokemon.getSpriteScale();
|
||||
|
||||
// On increase, show the red sprite located at ATK
|
||||
// On decrease, show the blue sprite located at SPD
|
||||
const spriteColor = stages.value >= 1 ? Stat[Stat.ATK].toLowerCase() : Stat[Stat.SPD].toLowerCase();
|
||||
const statSprite = this.scene.add.tileSprite(tileX, tileY, tileWidth, tileHeight, "battle_stats", spriteColor);
|
||||
statSprite.setPipeline(this.scene.fieldSpritePipeline);
|
||||
statSprite.setAlpha(0);
|
||||
statSprite.setScale(6);
|
||||
statSprite.setOrigin(0.5, 1);
|
||||
|
||||
this.scene.playSound(`se/stat_${stages.value >= 1 ? "up" : "down"}`);
|
||||
|
||||
statSprite.setMask(new Phaser.Display.Masks.BitmapMask(this.scene, pokemonMaskSprite ?? undefined));
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: statSprite,
|
||||
duration: 250,
|
||||
alpha: 0.8375,
|
||||
onComplete: () => {
|
||||
this.scene.tweens.add({
|
||||
targets: statSprite,
|
||||
delay: 1000,
|
||||
duration: 250,
|
||||
alpha: 0
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: statSprite,
|
||||
duration: 1500,
|
||||
y: `${stages.value >= 1 ? "-" : "+"}=${160 * 6}`
|
||||
});
|
||||
|
||||
this.scene.time.delayedCall(1750, () => {
|
||||
pokemon.disableMask();
|
||||
end();
|
||||
});
|
||||
} else {
|
||||
end();
|
||||
}
|
||||
}
|
||||
|
||||
aggregateStatStageChanges(): void {
|
||||
const accEva: BattleStat[] = [ Stat.ACC, Stat.EVA ];
|
||||
const isAccEva = accEva.some(s => this.stats.includes(s));
|
||||
let existingPhase: StatStageChangePhase;
|
||||
if (this.stats.length === 1) {
|
||||
while ((existingPhase = (this.scene.findPhase(p => p instanceof StatStageChangePhase && p.battlerIndex === this.battlerIndex && p.stats.length === 1
|
||||
&& (p.stats[0] === this.stats[0])
|
||||
&& p.selfTarget === this.selfTarget && p.showMessage === this.showMessage && p.ignoreAbilities === this.ignoreAbilities) as StatStageChangePhase))) {
|
||||
this.stages += existingPhase.stages;
|
||||
|
||||
if (!this.scene.tryRemovePhase(p => p === existingPhase)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while ((existingPhase = (this.scene.findPhase(p => p instanceof StatStageChangePhase && p.battlerIndex === this.battlerIndex && p.selfTarget === this.selfTarget
|
||||
&& (accEva.some(s => p.stats.includes(s)) === isAccEva)
|
||||
&& p.stages === this.stages && p.showMessage === this.showMessage && p.ignoreAbilities === this.ignoreAbilities) as StatStageChangePhase))) {
|
||||
this.stats.push(...existingPhase.stats);
|
||||
if (!this.scene.tryRemovePhase(p => p === existingPhase)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getStatStageChangeMessages(stats: BattleStat[], stages: integer, relStages: integer[]): string[] {
|
||||
const messages: string[] = [];
|
||||
|
||||
const relStageStatIndexes = {};
|
||||
for (let rl = 0; rl < relStages.length; rl++) {
|
||||
const relStage = relStages[rl];
|
||||
if (!relStageStatIndexes[relStage]) {
|
||||
relStageStatIndexes[relStage] = [];
|
||||
}
|
||||
relStageStatIndexes[relStage].push(rl);
|
||||
}
|
||||
|
||||
Object.keys(relStageStatIndexes).forEach(rl => {
|
||||
const relStageStats = stats.filter((_, i) => relStageStatIndexes[rl].includes(i));
|
||||
let statsFragment = "";
|
||||
|
||||
if (relStageStats.length > 1) {
|
||||
statsFragment = relStageStats.length >= 5
|
||||
? i18next.t("battle:stats")
|
||||
: `${relStageStats.slice(0, -1).map(s => i18next.t(getStatKey(s))).join(", ")}${relStageStats.length > 2 ? "," : ""} ${i18next.t("battle:statsAnd")} ${i18next.t(getStatKey(relStageStats[relStageStats.length - 1]))}`;
|
||||
messages.push(i18next.t(getStatStageChangeDescriptionKey(Math.abs(parseInt(rl)), stages >= 1), {
|
||||
pokemonNameWithAffix: getPokemonNameWithAffix(this.getPokemon()),
|
||||
stats: statsFragment,
|
||||
count: relStageStats.length
|
||||
}));
|
||||
} else {
|
||||
statsFragment = i18next.t(getStatKey(relStageStats[0]));
|
||||
messages.push(i18next.t(getStatStageChangeDescriptionKey(Math.abs(parseInt(rl)), stages >= 1), {
|
||||
pokemonNameWithAffix: getPokemonNameWithAffix(this.getPokemon()),
|
||||
stats: statsFragment,
|
||||
count: relStageStats.length
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
return messages;
|
||||
}
|
||||
}
|
@ -43,8 +43,8 @@ export class TurnStartPhase extends FieldPhase {
|
||||
}, this.scene.currentBattle.turn, this.scene.waveSeed);
|
||||
|
||||
orderedTargets.sort((a: Pokemon, b: Pokemon) => {
|
||||
const aSpeed = a?.getBattleStat(Stat.SPD) || 0;
|
||||
const bSpeed = b?.getBattleStat(Stat.SPD) || 0;
|
||||
const aSpeed = a?.getEffectiveStat(Stat.SPD) || 0;
|
||||
const bSpeed = b?.getEffectiveStat(Stat.SPD) || 0;
|
||||
|
||||
return bSpeed - aSpeed;
|
||||
});
|
||||
|
@ -5,9 +5,10 @@ import { pokemonEvolutions } from "#app/data/pokemon-evolutions";
|
||||
import i18next from "i18next";
|
||||
import * as Utils from "../utils";
|
||||
import { PlayerGender } from "#enums/player-gender";
|
||||
import { Challenge, FreshStartChallenge, InverseBattleChallenge, SingleGenerationChallenge, SingleTypeChallenge } from "#app/data/challenge";
|
||||
import { Challenges } from "#app/enums/challenges";
|
||||
import { Challenge, FreshStartChallenge, SingleGenerationChallenge, SingleTypeChallenge, InverseBattleChallenge } from "#app/data/challenge";
|
||||
import { ConditionFn } from "#app/@types/common";
|
||||
import { Stat, getShortenedStatKey } from "#app/enums/stat";
|
||||
import { Challenges } from "#app/enums/challenges";
|
||||
|
||||
export enum AchvTier {
|
||||
COMMON,
|
||||
@ -172,13 +173,13 @@ export function getAchievementDescription(localizationKey: string): string {
|
||||
case "10000_DMG":
|
||||
return i18next.t("achv:DamageAchv.description", {context: genderStr, "damageAmount": achvs._10000_DMG.damageAmount.toLocaleString("en-US")});
|
||||
case "250_HEAL":
|
||||
return i18next.t("achv:HealAchv.description", {context: genderStr, "healAmount": achvs._250_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t("pokemonInfo:Stat.HPshortened")});
|
||||
return i18next.t("achv:HealAchv.description", {context: genderStr, "healAmount": achvs._250_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP))});
|
||||
case "1000_HEAL":
|
||||
return i18next.t("achv:HealAchv.description", {context: genderStr, "healAmount": achvs._1000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t("pokemonInfo:Stat.HPshortened")});
|
||||
return i18next.t("achv:HealAchv.description", {context: genderStr, "healAmount": achvs._1000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP))});
|
||||
case "2500_HEAL":
|
||||
return i18next.t("achv:HealAchv.description", {context: genderStr, "healAmount": achvs._2500_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t("pokemonInfo:Stat.HPshortened")});
|
||||
return i18next.t("achv:HealAchv.description", {context: genderStr, "healAmount": achvs._2500_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP))});
|
||||
case "10000_HEAL":
|
||||
return i18next.t("achv:HealAchv.description", {context: genderStr, "healAmount": achvs._10000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t("pokemonInfo:Stat.HPshortened")});
|
||||
return i18next.t("achv:HealAchv.description", {context: genderStr, "healAmount": achvs._10000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP))});
|
||||
case "LV_100":
|
||||
return i18next.t("achv:LevelAchv.description", {context: genderStr, "level": achvs.LV_100.level});
|
||||
case "LV_250":
|
||||
@ -195,7 +196,7 @@ export function getAchievementDescription(localizationKey: string): string {
|
||||
return i18next.t("achv:RibbonAchv.description", {context: genderStr, "ribbonAmount": achvs._75_RIBBONS.ribbonAmount.toLocaleString("en-US")});
|
||||
case "100_RIBBONS":
|
||||
return i18next.t("achv:RibbonAchv.description", {context: genderStr, "ribbonAmount": achvs._100_RIBBONS.ribbonAmount.toLocaleString("en-US")});
|
||||
case "TRANSFER_MAX_BATTLE_STAT":
|
||||
case "TRANSFER_MAX_STAT_STAGE":
|
||||
return i18next.t("achv:TRANSFER_MAX_BATTLE_STAT.description", { context: genderStr });
|
||||
case "MAX_FRIENDSHIP":
|
||||
return i18next.t("achv:MAX_FRIENDSHIP.description", { context: genderStr });
|
||||
@ -305,7 +306,7 @@ export const achvs = {
|
||||
_50_RIBBONS: new RibbonAchv("50_RIBBONS", "", 50, "ultra_ribbon", 50).setSecret(true),
|
||||
_75_RIBBONS: new RibbonAchv("75_RIBBONS", "", 75, "rogue_ribbon", 75).setSecret(true),
|
||||
_100_RIBBONS: new RibbonAchv("100_RIBBONS", "", 100, "master_ribbon", 100).setSecret(true),
|
||||
TRANSFER_MAX_BATTLE_STAT: new Achv("TRANSFER_MAX_BATTLE_STAT", "", "TRANSFER_MAX_BATTLE_STAT.description", "baton", 20),
|
||||
TRANSFER_MAX_STAT_STAGE: new Achv("TRANSFER_MAX_STAT_STAGE", "", "TRANSFER_MAX_STAT_STAGE.description", "baton", 20),
|
||||
MAX_FRIENDSHIP: new Achv("MAX_FRIENDSHIP", "", "MAX_FRIENDSHIP.description", "soothe_bell", 25),
|
||||
MEGA_EVOLVE: new Achv("MEGA_EVOLVE", "", "MEGA_EVOLVE.description", "mega_bracelet", 50),
|
||||
GIGANTAMAX: new Achv("GIGANTAMAX", "", "GIGANTAMAX.description", "dynamax_band", 50),
|
||||
|
@ -1488,7 +1488,7 @@ export class GameData {
|
||||
};
|
||||
}
|
||||
|
||||
const defaultStarterAttr = DexAttr.NON_SHINY | DexAttr.MALE | DexAttr.DEFAULT_VARIANT | DexAttr.DEFAULT_FORM;
|
||||
const defaultStarterAttr = DexAttr.NON_SHINY | DexAttr.MALE | DexAttr.FEMALE | DexAttr.DEFAULT_VARIANT | DexAttr.DEFAULT_FORM;
|
||||
|
||||
const defaultStarterNatures: Nature[] = [];
|
||||
|
||||
@ -1919,6 +1919,7 @@ export class GameData {
|
||||
fixStarterData(systemData: SystemSaveData): void {
|
||||
for (const starterId of defaultStarterSpecies) {
|
||||
systemData.starterData[starterId].abilityAttr |= AbilityAttr.ABILITY_1;
|
||||
systemData.dexData[starterId].caughtAttr |= DexAttr.FEMALE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ export default class PokemonData {
|
||||
public luck: integer;
|
||||
public pauseEvolutions: boolean;
|
||||
public pokerus: boolean;
|
||||
public usedTMs: Moves[];
|
||||
|
||||
public fusionSpecies: Species;
|
||||
public fusionFormIndex: integer;
|
||||
@ -98,6 +99,7 @@ export default class PokemonData {
|
||||
this.fusionVariant = source.fusionVariant;
|
||||
this.fusionGender = source.fusionGender;
|
||||
this.fusionLuck = source.fusionLuck !== undefined ? source.fusionLuck : (source.fusionShiny ? source.fusionVariant + 1 : 0);
|
||||
this.usedTMs = source.usedTMs ?? [];
|
||||
|
||||
if (!forHistory) {
|
||||
this.boss = (source instanceof EnemyPokemon && !!source.bossSegments) || (!this.player && !!source.boss);
|
||||
@ -122,7 +124,8 @@ export default class PokemonData {
|
||||
|
||||
this.summonData = new PokemonSummonData();
|
||||
if (!forHistory && source.summonData) {
|
||||
this.summonData.battleStats = source.summonData.battleStats;
|
||||
this.summonData.stats = source.summonData.stats;
|
||||
this.summonData.statStages = source.summonData.statStages;
|
||||
this.summonData.moveQueue = source.summonData.moveQueue;
|
||||
this.summonData.disabledMove = source.summonData.disabledMove;
|
||||
this.summonData.disabledTurns = source.summonData.disabledTurns;
|
||||
|
97
src/test/abilities/beast_boost.test.ts
Normal file
97
src/test/abilities/beast_boost.test.ts
Normal file
@ -0,0 +1,97 @@
|
||||
import { Stat } from "#enums/stat";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { SPLASH_ONLY } from "../utils/testUtils";
|
||||
import { EnemyCommandPhase } from "#app/phases/enemy-command-phase";
|
||||
import { VictoryPhase } from "#app/phases/victory-phase";
|
||||
import { TurnStartPhase } from "#app/phases/turn-start-phase";
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
|
||||
describe("Abilities - Beast Boost", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.battleType("single")
|
||||
.enemySpecies(Species.BULBASAUR)
|
||||
.enemyAbility(Abilities.BEAST_BOOST)
|
||||
.ability(Abilities.BEAST_BOOST)
|
||||
.startingLevel(2000)
|
||||
.moveset([ Moves.FLAMETHROWER ])
|
||||
.enemyMoveset(SPLASH_ONLY);
|
||||
});
|
||||
|
||||
// Note that both MOXIE and BEAST_BOOST test for their current implementation and not their mainline behavior.
|
||||
it("should prefer highest stat to boost its corresponding stat stage by 1 when winning a battle", async() => {
|
||||
// SLOWBRO's highest stat is DEF, so it should be picked here
|
||||
await game.startBattle([
|
||||
Species.SLOWBRO
|
||||
]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
|
||||
expect(playerPokemon.getStatStage(Stat.DEF)).toBe(0);
|
||||
|
||||
game.move.select(Moves.FLAMETHROWER);
|
||||
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(VictoryPhase);
|
||||
|
||||
expect(playerPokemon.getStatStage(Stat.DEF)).toBe(1);
|
||||
}, 20000);
|
||||
|
||||
it("should use in-battle overriden stats when determining the stat stage to raise by 1", async() => {
|
||||
// If the opponent can GUARD_SPLIT, SLOWBRO's second highest stat should be SPATK
|
||||
game.override.enemyMoveset(new Array(4).fill(Moves.GUARD_SPLIT));
|
||||
|
||||
await game.startBattle([
|
||||
Species.SLOWBRO
|
||||
]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
|
||||
expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(0);
|
||||
|
||||
game.move.select(Moves.FLAMETHROWER);
|
||||
|
||||
await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]);
|
||||
|
||||
await game.phaseInterceptor.runFrom(TurnStartPhase).to(VictoryPhase);
|
||||
|
||||
expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(1);
|
||||
}, 20000);
|
||||
|
||||
it("should have order preference in case of stat ties", async() => {
|
||||
// Order preference follows the order of EFFECTIVE_STAT
|
||||
await game.startBattle([
|
||||
Species.SLOWBRO
|
||||
]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
|
||||
// Set up tie between SPATK, SPDEF, and SPD, where SPATK should win
|
||||
vi.spyOn(playerPokemon, "stats", "get").mockReturnValue([ 10000, 1, 1, 100, 100, 100 ]);
|
||||
|
||||
expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(0);
|
||||
|
||||
game.move.select(Moves.FLAMETHROWER);
|
||||
|
||||
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(VictoryPhase);
|
||||
|
||||
expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(1);
|
||||
}, 20000);
|
||||
});
|
42
src/test/abilities/contrary.test.ts
Normal file
42
src/test/abilities/contrary.test.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { Stat } from "#enums/stat";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Species } from "#enums/species";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
import { SPLASH_ONLY } from "../utils/testUtils";
|
||||
|
||||
describe("Abilities - Contrary", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.battleType("single")
|
||||
.enemySpecies(Species.BULBASAUR)
|
||||
.enemyAbility(Abilities.CONTRARY)
|
||||
.ability(Abilities.INTIMIDATE)
|
||||
.enemyMoveset(SPLASH_ONLY);
|
||||
});
|
||||
|
||||
it("should invert stat changes when applied", async() => {
|
||||
await game.startBattle([
|
||||
Species.SLOWBRO
|
||||
]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
|
||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(1);
|
||||
}, 20000);
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
import { BattleStat } from "#app/data/battle-stat";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { Abilities } from "#app/enums/abilities";
|
||||
import { Moves } from "#app/enums/moves";
|
||||
import { Species } from "#app/enums/species";
|
||||
@ -35,7 +35,7 @@ describe("Abilities - COSTAR", () => {
|
||||
|
||||
|
||||
test(
|
||||
"ability copies positive stat changes",
|
||||
"ability copies positive stat stages",
|
||||
async () => {
|
||||
game.override.enemyAbility(Abilities.BALL_FETCH);
|
||||
|
||||
@ -48,8 +48,8 @@ describe("Abilities - COSTAR", () => {
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(leftPokemon.summonData.battleStats[BattleStat.SPATK]).toBe(+2);
|
||||
expect(rightPokemon.summonData.battleStats[BattleStat.SPATK]).toBe(0);
|
||||
expect(leftPokemon.getStatStage(Stat.SPATK)).toBe(2);
|
||||
expect(rightPokemon.getStatStage(Stat.SPATK)).toBe(0);
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
@ -57,14 +57,14 @@ describe("Abilities - COSTAR", () => {
|
||||
await game.phaseInterceptor.to(MessagePhase);
|
||||
|
||||
[leftPokemon, rightPokemon] = game.scene.getPlayerField();
|
||||
expect(leftPokemon.summonData.battleStats[BattleStat.SPATK]).toBe(+2);
|
||||
expect(rightPokemon.summonData.battleStats[BattleStat.SPATK]).toBe(+2);
|
||||
expect(leftPokemon.getStatStage(Stat.SPATK)).toBe(2);
|
||||
expect(rightPokemon.getStatStage(Stat.SPATK)).toBe(2);
|
||||
},
|
||||
TIMEOUT,
|
||||
);
|
||||
|
||||
test(
|
||||
"ability copies negative stat changes",
|
||||
"ability copies negative stat stages",
|
||||
async () => {
|
||||
game.override.enemyAbility(Abilities.INTIMIDATE);
|
||||
|
||||
@ -72,8 +72,8 @@ describe("Abilities - COSTAR", () => {
|
||||
|
||||
let [leftPokemon, rightPokemon] = game.scene.getPlayerField();
|
||||
|
||||
expect(leftPokemon.summonData.battleStats[BattleStat.ATK]).toBe(-2);
|
||||
expect(leftPokemon.summonData.battleStats[BattleStat.ATK]).toBe(-2);
|
||||
expect(leftPokemon.getStatStage(Stat.ATK)).toBe(-2);
|
||||
expect(leftPokemon.getStatStage(Stat.ATK)).toBe(-2);
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
@ -81,8 +81,8 @@ describe("Abilities - COSTAR", () => {
|
||||
await game.phaseInterceptor.to(MessagePhase);
|
||||
|
||||
[leftPokemon, rightPokemon] = game.scene.getPlayerField();
|
||||
expect(leftPokemon.summonData.battleStats[BattleStat.ATK]).toBe(-2);
|
||||
expect(rightPokemon.summonData.battleStats[BattleStat.ATK]).toBe(-2);
|
||||
expect(leftPokemon.getStatStage(Stat.ATK)).toBe(-2);
|
||||
expect(rightPokemon.getStatStage(Stat.ATK)).toBe(-2);
|
||||
},
|
||||
TIMEOUT,
|
||||
);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user