diff --git a/public/fonts/PokePT_Wansung.woff2 b/public/fonts/PokePT_Wansung.woff2 index 15aab3eb4f4..02b299ef7a0 100644 Binary files a/public/fonts/PokePT_Wansung.woff2 and b/public/fonts/PokePT_Wansung.woff2 differ diff --git a/public/images/pokemon/back/821.png b/public/images/pokemon/back/821.png index 24e0edd705d..a102a0491de 100644 Binary files a/public/images/pokemon/back/821.png and b/public/images/pokemon/back/821.png differ diff --git a/public/images/pokemon/back/shiny/821.png b/public/images/pokemon/back/shiny/821.png index 6d29988ed9f..200489518c4 100644 Binary files a/public/images/pokemon/back/shiny/821.png and b/public/images/pokemon/back/shiny/821.png differ diff --git a/public/images/pokemon/exp/821.png b/public/images/pokemon/exp/821.png index 8bb00063bcb..e4a73a66140 100644 Binary files a/public/images/pokemon/exp/821.png and b/public/images/pokemon/exp/821.png differ diff --git a/public/images/pokemon/exp/953.png b/public/images/pokemon/exp/953.png index 8a6ca2e7eff..fb4255a112b 100644 Binary files a/public/images/pokemon/exp/953.png and b/public/images/pokemon/exp/953.png differ diff --git a/public/images/pokemon/exp/back/821.png b/public/images/pokemon/exp/back/821.png index 13aa5c24e83..80d88dce2f9 100644 Binary files a/public/images/pokemon/exp/back/821.png and b/public/images/pokemon/exp/back/821.png differ diff --git a/public/images/pokemon/exp/back/shiny/821.png b/public/images/pokemon/exp/back/shiny/821.png index d069d59ef72..426a1e81fea 100644 Binary files a/public/images/pokemon/exp/back/shiny/821.png and b/public/images/pokemon/exp/back/shiny/821.png differ diff --git a/public/images/pokemon/exp/shiny/821.png b/public/images/pokemon/exp/shiny/821.png index 6f6cf7f2991..5c03c17c793 100644 Binary files a/public/images/pokemon/exp/shiny/821.png and b/public/images/pokemon/exp/shiny/821.png differ diff --git a/public/images/pokemon/variant/exp/953.json b/public/images/pokemon/variant/exp/953.json index 6f2885be607..df4262f3ed2 100644 --- a/public/images/pokemon/variant/exp/953.json +++ b/public/images/pokemon/variant/exp/953.json @@ -2,35 +2,79 @@ "1": { "5a4d37": "1c1e76", "766348": "323aa5", + "9d8361": "4059bd", "c5b4aa": "d3e6e6", "37332b": "104139", "9e8360": "4059bd", + "f18725": "2e8c19", + "f18625": "2e8c19", + "bb6f2a": "2f7410", "0f0f0f": "0f0f0f", "575243": "18734a", + "b8702d": "2f7410", "777462": "199e46", - "afa668": "f9fba2", - "a28c88": "c1d8db", + "585243": "18734a", + "4f4531": "b29c3e", + "4d4530": "b29c3e", + "aea56b": "f9fba2", + "afa667": "f9fba2", + "a28e85": "c1d8db", + "a28c8c": "c1d8db", + "b64c95": "dedb64", "f2f2f2": "e8eab5", - "b45492": "dedb64", + "b05f8f": "dedb64", + "776348": "323aa5", "f28625": "2e8c19", - "4e4530": "b29c3e", - "ba6e29": "2f7410" + "bc6e28": "2f7410", + "bb6e27": "2f7410", + "4d4430": "b29c3e", + "b0a766": "f9fba2", + "a18f8d": "c1d8db", + "a28f86": "c1d8db", + "b74a94": "dedb64", + "9e8461": "4059bd", + "777362": "199e46", + "ba6d27": "2f7410", + "afa567": "f9fba2", + "a18f85": "c1d8db" }, "2": { "5a4d37": "333e5f", "766348": "8c9fbf", + "9d8361": "dbedec", "c5b4aa": "39cfbc", "37332b": "261031", "9e8360": "dbedec", + "f18725": "4baecd", + "f18625": "4baecd", + "bb6f2a": "4792bd", "0f0f0f": "0f0f0f", "575243": "5e2d72", + "b8702d": "4792bd", "777462": "8358a1", - "afa668": "c9dbac", - "a28e88": "52b0b0", + "585243": "5e2d72", + "4f4531": "534b8c", + "4d4530": "534b8c", + "aea56b": "c9dbac", + "afa667": "c9dbac", + "a28e85": "52b0b0", + "a28c8c": "52b0b0", + "b64c95": "b56c3e", "f2f2f2": "d9c951", - "b45492": "b56c3e", + "b05f8f": "b56c3e", + "776348": "8c9fbf", "f28625": "4baecd", - "4e4530": "534b8c", - "ba6e29": "4792bd" + "bc6e28": "4792bd", + "bb6e27": "4792bd", + "4d4430": "534b8c", + "b0a766": "c9dbac", + "a18f8d": "52b0b0", + "a28f86": "52b0b0", + "b74a94": "b56c3e", + "9e8461": "dbedec", + "777362": "8358a1", + "ba6d27": "4792bd", + "afa567": "c9dbac", + "a18f85": "52b0b0" } -} +} \ No newline at end of file diff --git a/src/battle-scene.ts b/src/battle-scene.ts index eaf550e7d10..e8c401d62fd 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1102,7 +1102,7 @@ export default class BattleScene extends SceneBase { } else if (trainerConfigs[trainerType].hasDouble) { const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8); this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance); - playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, false, doubleChance)); + playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, doubleChance)); doubleTrainer = !Utils.randSeedInt(doubleChance.value); // Add a check that special trainers can't be double except for tate and liza - they should use the normal double chance if (trainerConfigs[trainerType].trainerTypeDouble && ![ TrainerType.TATE, TrainerType.LIZA ].includes(trainerType)) { @@ -1118,7 +1118,7 @@ export default class BattleScene extends SceneBase { if (newBattleType === BattleType.WILD && !this.gameMode.isWaveFinal(newWaveIndex)) { const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8); this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance); - playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, false, doubleChance)); + playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, doubleChance)); newDouble = !Utils.randSeedInt(doubleChance.value); } else if (newBattleType === BattleType.TRAINER) { newDouble = newTrainer?.variant === TrainerVariant.DOUBLE; @@ -1520,7 +1520,7 @@ export default class BattleScene extends SceneBase { return; } const formattedMoney = Utils.formatMoney(this.moneyFormat, this.money); - this.moneyText.setText(i18next.t("battleScene:moneyOwned", { formattedMoney })); + this.moneyText.setText(`₽${formattedMoney}`); this.fieldUI.moveAbove(this.moneyText, this.luckText); if (forceVisible) { this.moneyText.setVisible(true); @@ -2138,7 +2138,7 @@ export default class BattleScene extends SceneBase { pushMovePhase(movePhase: MovePhase, priorityOverride?: integer): void { const movePriority = new Utils.IntegerHolder(priorityOverride !== undefined ? priorityOverride : movePhase.move.getMove().priority); - applyAbAttrs(ChangeMovePriorityAbAttr, movePhase.pokemon, null, false, movePhase.move.getMove(), movePriority); + applyAbAttrs(ChangeMovePriorityAbAttr, movePhase.pokemon, null, movePhase.move.getMove(), movePriority); const lowerPriorityPhase = this.phaseQueue.find(p => p instanceof MovePhase && p.move.getMove().priority < movePriority.value); if (lowerPriorityPhase) { this.phaseQueue.splice(this.phaseQueue.indexOf(lowerPriorityPhase), 0, movePhase); diff --git a/src/data/ability.ts b/src/data/ability.ts index 284a9cb4e91..8e020849a17 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -135,7 +135,7 @@ export abstract class AbAttr { this.showAbility = showAbility; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder | null, args: any[]): boolean | Promise { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder | null, args: any[]): boolean | Promise { return false; } @@ -154,7 +154,7 @@ export abstract class AbAttr { } export class BlockRecoilDamageAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; @@ -170,7 +170,7 @@ export class DoubleBattleChanceAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const doubleChance = (args[0] as Utils.IntegerHolder); doubleChance.value = Math.max(doubleChance.value / 2, 1); return true; @@ -178,7 +178,7 @@ export class DoubleBattleChanceAbAttr extends AbAttr { } export class PostBattleInitAbAttr extends AbAttr { - applyPostBattleInit(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPostBattleInit(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } @@ -192,9 +192,9 @@ export class PostBattleInitFormChangeAbAttr extends PostBattleInitAbAttr { this.formFunc = formFunc; } - applyPostBattleInit(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostBattleInit(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const formIndex = this.formFunc(pokemon); - if (formIndex !== pokemon.formIndex && !simulated) { + if (formIndex !== pokemon.formIndex) { return pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); } @@ -217,24 +217,22 @@ export class PostBattleInitStatChangeAbAttr extends PostBattleInitAbAttr { this.selfTarget = !!selfTarget; } - applyPostBattleInit(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostBattleInit(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const statChangePhases: StatChangePhase[] = []; - if (!simulated) { - if (this.selfTarget) { - statChangePhases.push(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.levels)); - } else { - for (const opponent of pokemon.getOpponents()) { - statChangePhases.push(new StatChangePhase(pokemon.scene, opponent.getBattlerIndex(), false, this.stats, this.levels)); - } + if (this.selfTarget) { + statChangePhases.push(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.levels)); + } else { + for (const opponent of pokemon.getOpponents()) { + statChangePhases.push(new StatChangePhase(pokemon.scene, opponent.getBattlerIndex(), false, this.stats, this.levels)); } + } - for (const statChangePhase of statChangePhases) { - if (!this.selfTarget && !statChangePhase.getPokemon()?.summonData) { - pokemon.scene.pushPhase(statChangePhase); - } else { // TODO: This causes the ability bar to be shown at the wrong time - pokemon.scene.unshiftPhase(statChangePhase); - } + for (const statChangePhase of statChangePhases) { + if (!this.selfTarget && !statChangePhase.getPokemon()?.summonData) { + pokemon.scene.pushPhase(statChangePhase); + } else { // TODO: This causes the ability bar to be shown at the wrong time + pokemon.scene.unshiftPhase(statChangePhase); } } @@ -245,17 +243,17 @@ export class PostBattleInitStatChangeAbAttr extends PostBattleInitAbAttr { type PreDefendAbAttrCondition = (pokemon: Pokemon, attacker: Pokemon, move: Move) => boolean; export class PreDefendAbAttr extends AbAttr { - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move | null, cancelled: Utils.BooleanHolder | null, args: any[]): boolean | Promise { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move | null, cancelled: Utils.BooleanHolder | null, args: any[]): boolean | Promise { return false; } } export class PreDefendFullHpEndureAbAttr extends PreDefendAbAttr { - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (pokemon.isFullHp() - && pokemon.getMaxHp() > 1 //Checks if pokemon has wonder_guard (which forces 1hp) - && (args[0] as Utils.NumberHolder).value >= pokemon.hp) { //Damage >= hp - return simulated || pokemon.addTag(BattlerTagType.STURDY, 1); + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (pokemon.isFullHp() && + pokemon.getMaxHp() > 1 && //Checks if pokemon has wonder_guard (which forces 1hp) + (args[0] as Utils.NumberHolder).value >= pokemon.hp) { //Damage >= hp + return pokemon.addTag(BattlerTagType.STURDY, 1); } return false; @@ -263,7 +261,7 @@ export class PreDefendFullHpEndureAbAttr extends PreDefendAbAttr { } export class BlockItemTheftAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; @@ -278,7 +276,7 @@ export class BlockItemTheftAbAttr extends AbAttr { } export class StabBoostAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if ((args[0] as Utils.NumberHolder).value > 1) { (args[0] as Utils.NumberHolder).value += 0.5; return true; @@ -299,9 +297,9 @@ export class ReceivedMoveDamageMultiplierAbAttr extends PreDefendAbAttr { this.damageMultiplier = damageMultiplier; } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.condition(pokemon, attacker, move)) { - (args[0] as Utils.NumberHolder).value = Utils.toDmgValue((args[0] as Utils.NumberHolder).value * this.damageMultiplier); + (args[0] as Utils.NumberHolder).value = Math.floor((args[0] as Utils.NumberHolder).value * this.damageMultiplier); return true; } @@ -343,7 +341,7 @@ export class TypeImmunityAbAttr extends PreDefendAbAttr { * @param args [0] {@linkcode Utils.NumberHolder} gets set to 0 if move is immuned by an ability. * @param args [1] - Whether the move is simulated. */ - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { // Field moves should ignore immunity if ([ MoveTarget.BOTH_SIDES, MoveTarget.ENEMY_SIDE, MoveTarget.USER_SIDE ].includes(move.moveTarget)) { return false; @@ -370,9 +368,9 @@ export class AttackTypeImmunityAbAttr extends TypeImmunityAbAttr { * Type immunity abilities that do not give additional benefits (HP recovery, stat boosts, etc) are not immune to status moves of the type * Example: Levitate */ - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (move.category !== MoveCategory.STATUS) { - return super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + return super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); } return false; } @@ -383,14 +381,17 @@ export class TypeImmunityHealAbAttr extends TypeImmunityAbAttr { super(immuneType); } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { - if (!pokemon.isFullHp() && !simulated) { - const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; - pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / 4), i18next.t("abilityTriggers:typeImmunityHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), true)); + if (!pokemon.isFullHp()) { + const simulated = args.length > 1 && args[1]; + if (!simulated) { + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; + pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(), + Math.max(Math.floor(pokemon.getMaxHp() / 4), 1), i18next.t("abilityTriggers:typeImmunityHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), true)); + } } return true; } @@ -410,11 +411,12 @@ class TypeImmunityStatChangeAbAttr extends TypeImmunityAbAttr { this.levels = levels; } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { cancelled.value = true; + const simulated = args.length > 1 && args[1]; if (!simulated) { pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.levels)); } @@ -435,11 +437,12 @@ class TypeImmunityAddBattlerTagAbAttr extends TypeImmunityAbAttr { this.turnCount = turnCount; } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { cancelled.value = true; + const simulated = args.length > 1 && args[1]; if (!simulated) { pokemon.addTag(this.tagType, this.turnCount, undefined, pokemon.id); } @@ -454,7 +457,7 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr { super(null, condition); } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (move instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.type, attacker) < 2) { cancelled.value = true; (args[0] as Utils.NumberHolder).value = 0; @@ -473,7 +476,7 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr { } export class PostDefendAbAttr extends AbAttr { - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise { return false; } } @@ -497,16 +500,12 @@ export class PostDefendGulpMissileAbAttr extends PostDefendAbAttr { * @param {any[]} args - n/a * @returns Whether the effects of the ability are applied. */ - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean | Promise { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean | Promise { const battlerTag = pokemon.getTag(GulpMissileTag); if (!battlerTag || move.category === MoveCategory.STATUS || pokemon.getTag(SemiInvulnerableTag)) { return false; } - if (simulated) { - return true; - } - const cancelled = new Utils.BooleanHolder(false); applyAbAttrs(BlockNonDirectDamageAbAttr, attacker, cancelled); @@ -526,12 +525,12 @@ export class PostDefendGulpMissileAbAttr extends PostDefendAbAttr { } export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr { - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { const attackPriority = new Utils.IntegerHolder(move.priority); - applyMoveAttrs(IncrementMovePriorityAttr, attacker, null, move, attackPriority); - applyAbAttrs(ChangeMovePriorityAbAttr, attacker, null, simulated, move, attackPriority); + applyMoveAttrs(IncrementMovePriorityAttr,attacker,null,move,attackPriority); + applyAbAttrs(ChangeMovePriorityAbAttr, attacker, null, move, attackPriority); - if (move.moveTarget === MoveTarget.USER || move.moveTarget === MoveTarget.NEAR_ALLY) { + if (move.moveTarget===MoveTarget.USER || move.moveTarget===MoveTarget.NEAR_ALLY) { return false; } @@ -545,7 +544,7 @@ export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr { } export class PostStatChangeAbAttr extends AbAttr { - applyPostStatChange(pokemon: Pokemon, simulated: boolean, statsChanged: BattleStat[], levelChanged: integer, selfTarget: boolean, args: any[]): boolean | Promise { + applyPostStatChange(pokemon: Pokemon, statsChanged: BattleStat[], levelChanged: integer, selfTarget: boolean, args: any[]): boolean | Promise { return false; } } @@ -559,7 +558,7 @@ export class MoveImmunityAbAttr extends PreDefendAbAttr { this.immuneCondition = immuneCondition; } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.immuneCondition(pokemon, attacker, move)) { cancelled.value = true; return true; @@ -580,7 +579,7 @@ export class MoveImmunityAbAttr extends PreDefendAbAttr { * @extends PreDefendAbAttr */ export class WonderSkinAbAttr extends PreDefendAbAttr { - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { const moveAccuracy = args[0] as Utils.NumberHolder; if (move.category === MoveCategory.STATUS && moveAccuracy.value >= 50) { moveAccuracy.value = 50; @@ -601,10 +600,13 @@ export class MoveImmunityStatChangeAbAttr extends MoveImmunityAbAttr { this.levels = levels; } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); - if (ret && !simulated) { - pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.levels)); + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); + if (ret) { + const simulated = args.length > 1 && args[1]; + if (!simulated) { + pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.levels)); + } } return ret; @@ -628,11 +630,9 @@ export class ReverseDrainAbAttr extends PostDefendAbAttr { * @args N/A * @returns true if healing should be reversed on a healing move, false otherwise. */ - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (move.hasAttr(HitHealAttr)) { - if (!simulated) { - pokemon.scene.queueMessage(i18next.t("abilityTriggers:reverseDrain", { pokemonNameWithAffix: getPokemonNameWithAffix(attacker) })); - } + pokemon.scene.queueMessage(i18next.t("abilityTriggers:reverseDrain", { pokemonNameWithAffix: getPokemonNameWithAffix(attacker) })); return true; } return false; @@ -656,12 +656,8 @@ export class PostDefendStatChangeAbAttr extends PostDefendAbAttr { this.allOthers = allOthers; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (this.condition(pokemon, attacker, move)) { - if (simulated) { - return true; - } - if (this.allOthers) { const otherPokemon = pokemon.getAlly() ? pokemon.getOpponents().concat([ pokemon.getAlly() ]) : pokemon.getOpponents(); for (const other of otherPokemon) { @@ -694,15 +690,13 @@ export class PostDefendHpGatedStatChangeAbAttr extends PostDefendAbAttr { this.selfTarget = selfTarget; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { const hpGateFlat: integer = Math.ceil(pokemon.getMaxHp() * this.hpGate); const lastAttackReceived = pokemon.turnData.attacksReceived[pokemon.turnData.attacksReceived.length - 1]; const damageReceived = lastAttackReceived?.damage || 0; if (this.condition(pokemon, attacker, move) && (pokemon.hp <= hpGateFlat && (pokemon.hp + damageReceived) > hpGateFlat)) { - if (!simulated) { - pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, (this.selfTarget ? pokemon : attacker).getBattlerIndex(), true, this.stats, this.levels)); - } + pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, (this.selfTarget ? pokemon : attacker).getBattlerIndex(), true, this.stats, this.levels)); return true; } @@ -721,13 +715,11 @@ export class PostDefendApplyArenaTrapTagAbAttr extends PostDefendAbAttr { this.tagType = tagType; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (this.condition(pokemon, attacker, move)) { const tag = pokemon.scene.arena.getTag(this.tagType) as ArenaTrapTag; if (!pokemon.scene.arena.getTag(this.tagType) || tag.layers < tag.maxLayers) { - if (!simulated) { - pokemon.scene.arena.addTag(this.tagType, 0, undefined, pokemon.id, pokemon.isPlayer() ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER); - } + pokemon.scene.arena.addTag(this.tagType, 0, undefined, pokemon.id, pokemon.isPlayer() ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER); return true; } } @@ -745,9 +737,9 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr { this.tagType = tagType; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (this.condition(pokemon, attacker, move)) { - if (!pokemon.getTag(this.tagType) && !simulated) { + if (!pokemon.getTag(this.tagType)) { pokemon.addTag(this.tagType, undefined, undefined, pokemon.id); pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name })); } @@ -758,11 +750,8 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr { } export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr { - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (hitResult < HitResult.NO_EFFECT) { - if (simulated) { - return true; - } const type = move.type; const pokemonTypes = pokemon.getTypes(true); if (pokemonTypes.length !== 1 || pokemonTypes[0] !== type) { @@ -792,13 +781,9 @@ export class PostDefendTerrainChangeAbAttr extends PostDefendAbAttr { this.terrainType = terrainType; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (hitResult < HitResult.NO_EFFECT) { - if (simulated) { - return pokemon.scene.arena.terrain?.terrainType !== (this.terrainType || undefined); - } else { - return pokemon.scene.arena.trySetTerrain(this.terrainType, true); - } + return pokemon.scene.arena.trySetTerrain(this.terrainType, true); } return false; @@ -816,14 +801,10 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { this.effects = effects; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; - if (simulated) { - return attacker.canSetStatus(effect, true, false, pokemon); - } else { - return attacker.trySetStatus(effect, true, pokemon); - } + return attacker.trySetStatus(effect, true, pokemon); } return false; @@ -835,11 +816,11 @@ export class EffectSporeAbAttr extends PostDefendContactApplyStatusEffectAbAttr super(10, StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP); } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (attacker.hasAbility(Abilities.OVERCOAT) || attacker.isOfType(Type.GRASS)) { return false; } - return super.applyPostDefend(pokemon, passive, simulated, attacker, move, hitResult, args); + return super.applyPostDefend(pokemon, passive, attacker, move, hitResult, args); } } @@ -856,13 +837,9 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr { this.turnCount = turnCount; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance) { - if (simulated) { - return attacker.canAddTag(this.tagType); - } else { - return attacker.addTag(this.tagType, this.turnCount, move.id, attacker.id); - } + return attacker.addTag(this.tagType, this.turnCount, move.id, attacker.id); } return false; @@ -880,10 +857,8 @@ export class PostDefendCritStatChangeAbAttr extends PostDefendAbAttr { this.levels = levels; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (!simulated) { - pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.levels)); - } + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.levels)); return true; } @@ -902,10 +877,10 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr { this.damageRatio = damageRatio; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (!simulated && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { - attacker.damageAndUpdate(Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); - attacker.turnData.damageTaken += Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)); + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { + attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); + attacker.turnData.damageTaken += Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)); return true; } @@ -935,15 +910,13 @@ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr { this.turns = turns; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { if (pokemon.getTag(BattlerTagType.PERISH_SONG) || attacker.getTag(BattlerTagType.PERISH_SONG)) { return false; } else { - if (!simulated) { - attacker.addTag(BattlerTagType.PERISH_SONG, this.turns); - pokemon.addTag(BattlerTagType.PERISH_SONG, this.turns); - } + attacker.addTag(BattlerTagType.PERISH_SONG, this.turns); + pokemon.addTag(BattlerTagType.PERISH_SONG, this.turns); return true; } } @@ -966,14 +939,11 @@ export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr { this.condition = condition ?? null; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (this.condition !== null && !this.condition(pokemon, attacker, move)) { return false; } if (!pokemon.scene.arena.weather?.isImmutable()) { - if (simulated) { - return pokemon.scene.arena.weather?.weatherType !== this.weatherType; - } return pokemon.scene.arena.trySetWeather(this.weatherType, true); } @@ -986,13 +956,11 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr { super(); } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr)) { - if (!simulated) { - const tempAbilityId = attacker.getAbility().id; - attacker.summonData.ability = pokemon.getAbility().id; - pokemon.summonData.ability = tempAbilityId; - } + const tempAbilityId = attacker.getAbility().id; + attacker.summonData.ability = pokemon.getAbility().id; + pokemon.summonData.ability = tempAbilityId; return true; } @@ -1012,11 +980,9 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr { this.ability = ability; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr) && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr)) { - if (!simulated) { - attacker.summonData.ability = this.ability; - } + attacker.summonData.ability = this.ability; return true; } @@ -1043,13 +1009,9 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr { this.chance = chance; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (!attacker.summonData.disabledMove) { if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && !attacker.isMax()) { - if (simulated) { - return true; - } - this.attacker = attacker; this.move = move; @@ -1082,11 +1044,9 @@ export class PostStatChangeStatChangeAbAttr extends PostStatChangeAbAttr { this.levels = levels; } - applyPostStatChange(pokemon: Pokemon, simulated: boolean, statsChanged: BattleStat[], levelsChanged: integer, selfTarget: boolean, args: any[]): boolean { + applyPostStatChange(pokemon: Pokemon, statsChanged: BattleStat[], levelsChanged: integer, selfTarget: boolean, args: any[]): boolean { if (this.condition(pokemon, statsChanged, levelsChanged) && !selfTarget) { - if (!simulated) { - pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, (pokemon).getBattlerIndex(), true, this.statsToChange, this.levels)); - } + pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, (pokemon).getBattlerIndex(), true, this.statsToChange, this.levels)); return true; } @@ -1095,7 +1055,7 @@ export class PostStatChangeStatChangeAbAttr extends PostStatChangeAbAttr { } export class PreAttackAbAttr extends AbAttr { - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean | Promise { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean | Promise { return false; } } @@ -1116,7 +1076,7 @@ export class MoveEffectChanceMultiplierAbAttr extends AbAttr { * @param args [0]: {@linkcode Utils.NumberHolder} Move additional effect chance. Has to be higher than or equal to 0. * [1]: {@linkcode Moves } Move used by the ability user. */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { // Disable showAbility during getTargetBenefitScore this.showAbility = args[4]; if ((args[0] as Utils.NumberHolder).value <= 0 || (args[1] as Move).id === Moves.ORDER_UP) { @@ -1139,7 +1099,7 @@ export class IgnoreMoveEffectsAbAttr extends PreDefendAbAttr { /** * @param args [0]: {@linkcode Utils.NumberHolder} Move additional effect chance. */ - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { if ((args[0] as Utils.NumberHolder).value <= 0) { return false; @@ -1152,14 +1112,14 @@ export class IgnoreMoveEffectsAbAttr extends PreDefendAbAttr { } export class VariableMovePowerAbAttr extends PreAttackAbAttr { - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { //const power = args[0] as Utils.NumberHolder; return false; } } export class FieldPreventExplosiveMovesAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { cancelled.value = true; return true; } @@ -1196,7 +1156,7 @@ export class FieldMultiplyBattleStatAbAttr extends AbAttr { * @param args {any[]} unused * @returns true if this changed the checked stat, false otherwise. */ - applyFieldBattleStat(pokemon: Pokemon, passive: boolean, simulated: boolean, stat: Stat, statValue: Utils.NumberHolder, checkedPokemon: Pokemon, hasApplied: Utils.BooleanHolder, args: any[]): boolean { + applyFieldBattleStat(pokemon: Pokemon, passive: boolean, stat: Stat, statValue: Utils.NumberHolder, checkedPokemon: Pokemon, hasApplied: Utils.BooleanHolder, args: any[]): boolean { if (!this.canStack && hasApplied.value) { return false; } @@ -1220,7 +1180,7 @@ export class MoveTypeChangeAttr extends PreAttackAbAttr { super(true); } - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { if (this.condition && this.condition(pokemon, defender, move)) { move.type = this.newType; if (args[0] && args[0] instanceof Utils.NumberHolder) { @@ -1241,7 +1201,7 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr { super(true); } - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { if ( !pokemon.isTerastallized() && move.id !== Moves.STRUGGLE && @@ -1269,11 +1229,9 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr { } if (pokemon.getTypes().some((t) => t !== moveCopy.type)) { - if (!simulated) { - this.moveType = moveCopy.type; - pokemon.summonData.types = [moveCopy.type]; - pokemon.updateInfo(); - } + this.moveType = moveCopy.type; + pokemon.summonData.types = [moveCopy.type]; + pokemon.updateInfo(); return true; } @@ -1349,7 +1307,7 @@ export class AddSecondStrikeAbAttr extends PreAttackAbAttr { * @param {Utils.NumberHolder} args\[2\] the damage multiplier for the current strike * @returns */ - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { const numTargets = args[0] as integer; const hitCount = args[1] as Utils.IntegerHolder; const multiplier = args[2] as Utils.NumberHolder; @@ -1394,7 +1352,7 @@ export class DamageBoostAbAttr extends PreAttackAbAttr { * @param args Utils.NumberHolder as damage * @returns true if the function succeeds */ - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { if (this.condition(pokemon, defender, move)) { const power = args[0] as Utils.NumberHolder; power.value = Math.floor(power.value * this.damageMultiplier); @@ -1415,7 +1373,7 @@ export class MovePowerBoostAbAttr extends VariableMovePowerAbAttr { this.powerMultiplier = powerMultiplier; } - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { if (this.condition(pokemon, defender, move)) { (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; @@ -1462,7 +1420,7 @@ export class VariableMovePowerBoostAbAttr extends VariableMovePowerAbAttr { /** * @override */ - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move, args: any[]): boolean { const multiplier = this.mult(pokemon, defender, move); if (multiplier !== 1) { (args[0] as Utils.NumberHolder).value *= multiplier; @@ -1491,7 +1449,7 @@ export class FieldMovePowerBoostAbAttr extends AbAttr { this.powerMultiplier = powerMultiplier; } - applyPreAttack(pokemon: Pokemon | null, passive: boolean | null, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean { + applyPreAttack(pokemon: Pokemon | null, passive: boolean | null, defender: Pokemon | null, move: Move, args: any[]): boolean { if (this.condition(pokemon, defender, move)) { (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; @@ -1555,7 +1513,7 @@ export class BattleStatMultiplierAbAttr extends AbAttr { this.condition = condition ?? null; } - applyBattleStat(pokemon: Pokemon, passive: boolean, simulated: boolean, battleStat: BattleStat, statValue: Utils.NumberHolder, args: any[]): boolean | Promise { + applyBattleStat(pokemon: Pokemon, passive: boolean, battleStat: BattleStat, statValue: Utils.NumberHolder, args: any[]): boolean | Promise { const move = (args[0] as Move); if (battleStat === this.battleStat && (!this.condition || this.condition(pokemon, null, move))) { statValue.value *= this.multiplier; @@ -1581,11 +1539,11 @@ export class PostAttackAbAttr extends AbAttr { * applying the effect of any inherited class. This can be changed by providing a different {@link attackCondition} to the constructor. See {@link ConfusionOnStatusEffectAbAttr} * for an example of an effect that does not require a damaging move. */ - applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise { + applyPostAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise { // When attackRequired is true, we require the move to be an attack move and to deal damage before checking secondary requirements. // If attackRequired is false, we always defer to the secondary requirements. if (this.attackCondition(pokemon, defender, move)) { - return this.applyPostAttackAfterMoveTypeCheck(pokemon, passive, simulated, defender, move, hitResult, args); + return this.applyPostAttackAfterMoveTypeCheck(pokemon, passive, defender, move, hitResult, args); } else { return false; } @@ -1594,7 +1552,7 @@ export class PostAttackAbAttr extends AbAttr { /** * This method is only called after {@link applyPostAttack} has already been applied. Use this for handling checks specific to the ability in question. */ - applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise { + applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise { return false; } } @@ -1608,9 +1566,9 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { this.stealCondition = stealCondition ?? null; } - applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise { + applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise { return new Promise(resolve => { - if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.stealCondition || this.stealCondition(pokemon, defender, move))) { + if (hitResult < HitResult.NO_EFFECT && (!this.stealCondition || this.stealCondition(pokemon, defender, move))) { const heldItems = this.getTargetHeldItems(defender).filter(i => i.isTransferrable); if (heldItems.length) { const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; @@ -1623,7 +1581,7 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { return; } } - resolve(simulated); + resolve(false); }); } @@ -1646,14 +1604,14 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { this.effects = effects; } - applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { /**Status inflicted by abilities post attacking are also considered additional effects.*/ - if (!attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && !simulated && pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) { + if (!attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; return attacker.trySetStatus(effect, true, pokemon); } - return simulated; + return false; } } @@ -1677,11 +1635,11 @@ export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr { this.effects = effects; } - applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { /**Battler tags inflicted by abilities post attacking are also considered additional effects.*/ if (!attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance(attacker, pokemon, move) && !pokemon.status) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; - return simulated || attacker.addTag(effect); + return attacker.addTag(effect); } return false; @@ -1697,9 +1655,9 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { this.condition = condition ?? null; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise { + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise { return new Promise(resolve => { - if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move))) { + if (hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move))) { const heldItems = this.getTargetHeldItems(attacker).filter(i => i.isTransferrable); if (heldItems.length) { const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; @@ -1712,7 +1670,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { return; } } - resolve(simulated); + resolve(false); }); } @@ -1723,7 +1681,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { } export class PostVictoryAbAttr extends AbAttr { - applyPostVictory(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPostVictory(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } @@ -1739,13 +1697,12 @@ class PostVictoryStatChangeAbAttr extends PostVictoryAbAttr { this.levels = levels; } - applyPostVictory(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPostVictory(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { const stat = typeof this.stat === "function" ? this.stat(pokemon) : this.stat; - if (!simulated) { - pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], this.levels)); - } + pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], this.levels)); + return true; } } @@ -1759,12 +1716,10 @@ export class PostVictoryFormChangeAbAttr extends PostVictoryAbAttr { this.formFunc = formFunc; } - applyPostVictory(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPostVictory(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) { - if (!simulated) { - pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); - } + pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); return true; } @@ -1773,7 +1728,7 @@ export class PostVictoryFormChangeAbAttr extends PostVictoryAbAttr { } export class PostKnockOutAbAttr extends AbAttr { - applyPostKnockOut(pokemon: Pokemon, passive: boolean, simulated: boolean, knockedOut: Pokemon, args: any[]): boolean | Promise { + applyPostKnockOut(pokemon: Pokemon, passive: boolean, knockedOut: Pokemon, args: any[]): boolean | Promise { return false; } } @@ -1789,13 +1744,12 @@ export class PostKnockOutStatChangeAbAttr extends PostKnockOutAbAttr { this.levels = levels; } - applyPostKnockOut(pokemon: Pokemon, passive: boolean, simulated: boolean, knockedOut: Pokemon, args: any[]): boolean | Promise { + applyPostKnockOut(pokemon: Pokemon, passive: boolean, knockedOut: Pokemon, args: any[]): boolean | Promise { const stat = typeof this.stat === "function" ? this.stat(pokemon) : this.stat; - if (!simulated) { - pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], this.levels)); - } + pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], this.levels)); + return true; } } @@ -1805,12 +1759,10 @@ export class CopyFaintedAllyAbilityAbAttr extends PostKnockOutAbAttr { super(); } - applyPostKnockOut(pokemon: Pokemon, passive: boolean, simulated: boolean, knockedOut: Pokemon, args: any[]): boolean | Promise { + applyPostKnockOut(pokemon: Pokemon, passive: boolean, knockedOut: Pokemon, args: any[]): boolean | Promise { if (pokemon.isPlayer() === knockedOut.isPlayer() && !knockedOut.getAbility().hasAttr(UncopiableAbilityAbAttr)) { - if (!simulated) { - pokemon.summonData.ability = knockedOut.getAbility().id; - pokemon.scene.queueMessage(i18next.t("abilityTriggers:copyFaintedAllyAbility", { pokemonNameWithAffix: getPokemonNameWithAffix(knockedOut), abilityName: allAbilities[knockedOut.getAbility().id].name })); - } + pokemon.summonData.ability = knockedOut.getAbility().id; + pokemon.scene.queueMessage(i18next.t("abilityTriggers:copyFaintedAllyAbility", { pokemonNameWithAffix: getPokemonNameWithAffix(knockedOut), abilityName: allAbilities[knockedOut.getAbility().id].name })); return true; } @@ -1823,7 +1775,7 @@ export class IgnoreOpponentStatChangesAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]) { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]) { (args[0] as Utils.IntegerHolder).value = 0; return true; @@ -1846,7 +1798,7 @@ export class IgnoreOpponentEvasionAbAttr extends AbAttr { * @param args [0] {@linkcode Utils.IntegerHolder} of BattleStat.EVA * @returns if evasion level was successfully considered as 0 */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]) { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]) { (args[0] as Utils.IntegerHolder).value = 0; return true; } @@ -1857,7 +1809,7 @@ export class IntimidateImmunityAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } @@ -1882,10 +1834,8 @@ export class PostIntimidateStatChangeAbAttr extends AbAttr { this.overwrites = !!overwrites; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (!simulated) { - pokemon.scene.pushPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, this.stats, this.levels)); - } + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + pokemon.scene.pushPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, this.stats, this.levels)); cancelled.value = this.overwrites; return true; } @@ -1903,7 +1853,7 @@ export class PostSummonAbAttr extends AbAttr { * @param args Set of unique arguments needed by this attribute * @returns true if application of the ability succeeds */ - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } @@ -1922,11 +1872,9 @@ export class PostSummonRemoveArenaTagAbAttr extends PostSummonAbAttr { this.arenaTags = arenaTags; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { - if (!simulated) { - for (const arenaTag of this.arenaTags) { - pokemon.scene.arena.removeTag(arenaTag); - } + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { + for (const arenaTag of this.arenaTags) { + pokemon.scene.arena.removeTag(arenaTag); } return true; } @@ -1941,10 +1889,8 @@ export class PostSummonMessageAbAttr extends PostSummonAbAttr { this.messageFunc = messageFunc; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (!simulated) { - pokemon.scene.queueMessage(this.messageFunc(pokemon)); - } + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { + pokemon.scene.queueMessage(this.messageFunc(pokemon)); return true; } @@ -1960,10 +1906,8 @@ export class PostSummonUnnamedMessageAbAttr extends PostSummonAbAttr { this.message = message; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (!simulated) { - pokemon.scene.queueMessage(this.message); - } + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { + pokemon.scene.queueMessage(this.message); return true; } @@ -1980,12 +1924,8 @@ export class PostSummonAddBattlerTagAbAttr extends PostSummonAbAttr { this.turnCount = turnCount; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (simulated) { - return pokemon.canAddTag(this.tagType); - } else { - return pokemon.addTag(this.tagType, this.turnCount); - } + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { + return pokemon.addTag(this.tagType, this.turnCount); } } @@ -2006,11 +1946,7 @@ export class PostSummonStatChangeAbAttr extends PostSummonAbAttr { this.intimidate = !!intimidate; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (simulated) { - return true; - } - + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { queueShowAbility(pokemon, passive); // TODO: Better solution than manually showing the ability here if (this.selfTarget) { // we unshift the StatChangePhase to put it right after the showAbility and not at the end of the @@ -2021,8 +1957,8 @@ export class PostSummonStatChangeAbAttr extends PostSummonAbAttr { for (const opponent of pokemon.getOpponents()) { const cancelled = new Utils.BooleanHolder(false); if (this.intimidate) { - applyAbAttrs(IntimidateImmunityAbAttr, opponent, cancelled, simulated); - applyAbAttrs(PostIntimidateStatChangeAbAttr, opponent, cancelled, simulated); + applyAbAttrs(IntimidateImmunityAbAttr, opponent, cancelled); + applyAbAttrs(PostIntimidateStatChangeAbAttr, opponent, cancelled); } if (!cancelled.value) { const statChangePhase = new StatChangePhase(pokemon.scene, opponent.getBattlerIndex(), false, this.stats, this.levels); @@ -2044,14 +1980,11 @@ export class PostSummonAllyHealAbAttr extends PostSummonAbAttr { this.showAnim = showAnim; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const target = pokemon.getAlly(); if (target?.isActive(true)) { - if (!simulated) { - target.scene.unshiftPhase(new PokemonHealPhase(target.scene, target.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / this.healRatio), i18next.t("abilityTriggers:postSummonAllyHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(target), pokemonName: pokemon.name }), true, !this.showAnim)); - } - + target.scene.unshiftPhase(new PokemonHealPhase(target.scene, target.getBattlerIndex(), + Math.max(Math.floor(pokemon.getMaxHp() / this.healRatio), 1), i18next.t("abilityTriggers:postSummonAllyHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(target), pokemonName: pokemon.name }), true, !this.showAnim)); return true; } @@ -2072,17 +2005,15 @@ export class PostSummonClearAllyStatsAbAttr extends PostSummonAbAttr { super(); } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const target = pokemon.getAlly(); if (target?.isActive(true)) { - if (!simulated) { - for (let s = 0; s < target.summonData.battleStats.length; s++) { - target.summonData.battleStats[s] = 0; - } - - target.scene.queueMessage(i18next.t("abilityTriggers:postSummonClearAllyStats", { pokemonNameWithAffix: getPokemonNameWithAffix(target) })); + for (let s = 0; s < target.summonData.battleStats.length; s++) { + target.summonData.battleStats[s] = 0; } + target.scene.queueMessage(i18next.t("abilityTriggers:postSummonClearAllyStats", { pokemonNameWithAffix: getPokemonNameWithAffix(target) })); + return true; } @@ -2112,7 +2043,7 @@ export class DownloadAbAttr extends PostSummonAbAttr { * @param {any[]} args N/A * @returns Returns true if ability is used successful, false if not. */ - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { this.enemyDef = 0; this.enemySpDef = 0; this.enemyCountTally = 0; @@ -2132,9 +2063,7 @@ export class DownloadAbAttr extends PostSummonAbAttr { } if (this.enemyDef > 0 && this.enemySpDef > 0) { // only activate if there's actually an enemy to download from - if (!simulated) { - pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, this.stats, 1)); - } + pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, this.stats, 1)); return true; } @@ -2151,15 +2080,11 @@ export class PostSummonWeatherChangeAbAttr extends PostSummonAbAttr { this.weatherType = weatherType; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { if ((this.weatherType === WeatherType.HEAVY_RAIN || this.weatherType === WeatherType.HARSH_SUN || this.weatherType === WeatherType.STRONG_WINDS) || !pokemon.scene.arena.weather?.isImmutable()) { - if (simulated) { - return pokemon.scene.arena.weather?.weatherType !== this.weatherType; - } else { - return pokemon.scene.arena.trySetWeather(this.weatherType, true); - } + return pokemon.scene.arena.trySetWeather(this.weatherType, true); } return false; @@ -2175,12 +2100,8 @@ export class PostSummonTerrainChangeAbAttr extends PostSummonAbAttr { this.terrainType = terrainType; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (simulated) { - return pokemon.scene.arena.terrain?.terrainType !== this.terrainType; - } else { - return pokemon.scene.arena.trySetTerrain(this.terrainType, true); - } + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { + return pokemon.scene.arena.trySetTerrain(this.terrainType, true); } } @@ -2193,10 +2114,10 @@ export class PostSummonFormChangeAbAttr extends PostSummonAbAttr { this.formFunc = formFunc; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) { - return simulated || pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); + return pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); } return false; @@ -2208,7 +2129,7 @@ export class PostSummonCopyAbilityAbAttr extends PostSummonAbAttr { private target: Pokemon; private targetAbilityName: string; - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const targets = pokemon.getOpponents(); if (!targets.length) { return false; @@ -2229,13 +2150,11 @@ export class PostSummonCopyAbilityAbAttr extends PostSummonAbAttr { return false; } - if (!simulated) { - this.target = target!; - this.targetAbilityName = allAbilities[target!.getAbility().id].name; - pokemon.summonData.ability = target!.getAbility().id; - setAbilityRevealed(target!); - pokemon.updateInfo(); - } + this.target = target!; + this.targetAbilityName = allAbilities[target!.getAbility().id].name; + pokemon.summonData.ability = target!.getAbility().id; + setAbilityRevealed(target!); + pokemon.updateInfo(); return true; } @@ -2272,7 +2191,7 @@ export class PostSummonUserFieldRemoveStatusEffectAbAttr extends PostSummonAbAtt * @param args - n/a * @returns A boolean or a promise that resolves to a boolean indicating the result of the ability application. */ - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { const party = pokemon instanceof PlayerPokemon ? pokemon.scene.getPlayerField() : pokemon.scene.getEnemyField(); const allowedParty = party.filter(p => p.isAllowedInBattle()); @@ -2280,15 +2199,14 @@ export class PostSummonUserFieldRemoveStatusEffectAbAttr extends PostSummonAbAtt return false; } - if (!simulated) { - for (const pokemon of allowedParty) { - if (pokemon.status && this.statusEffect.includes(pokemon.status.effect)) { - pokemon.scene.queueMessage(getStatusEffectHealText(pokemon.status.effect, getPokemonNameWithAffix(pokemon))); - pokemon.resetStatus(false); - pokemon.updateInfo(); - } + for (const pokemon of allowedParty) { + if (pokemon.status && this.statusEffect.includes(pokemon.status.effect)) { + pokemon.scene.queueMessage(getStatusEffectHealText(pokemon.status.effect, getPokemonNameWithAffix(pokemon))); + pokemon.resetStatus(false); + pokemon.updateInfo(); } } + return true; } } @@ -2296,7 +2214,7 @@ export class PostSummonUserFieldRemoveStatusEffectAbAttr extends PostSummonAbAtt /** Attempt to copy the stat changes on an ally pokemon */ export class PostSummonCopyAllyStatsAbAttr extends PostSummonAbAttr { - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { if (!pokemon.scene.currentBattle.double) { return false; } @@ -2306,10 +2224,8 @@ export class PostSummonCopyAllyStatsAbAttr extends PostSummonAbAttr { return false; } - if (!simulated) { - pokemon.summonData.battleStats = ally.summonData.battleStats; - pokemon.updateInfo(); - } + pokemon.summonData.battleStats = ally.summonData.battleStats; + pokemon.updateInfo(); return true; } @@ -2327,10 +2243,10 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr { super(true); } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const targets = pokemon.getOpponents(); - if (simulated || !targets.length) { - return simulated; + if (!targets.length) { + return false; } let target: Pokemon; @@ -2366,19 +2282,16 @@ export class PreSwitchOutAbAttr extends AbAttr { super(true); } - applyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } export class PreSwitchOutResetStatusAbAttr extends PreSwitchOutAbAttr { - applyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { if (pokemon.status) { - if (!simulated) { - pokemon.resetStatus(); - pokemon.updateInfo(); - } - + pokemon.resetStatus(); + pokemon.updateInfo(); return true; } @@ -2397,7 +2310,7 @@ export class PreSwitchOutClearWeatherAbAttr extends PreSwitchOutAbAttr { * @param args N/A * @returns {boolean} Returns true if the weather clears, otherwise false. */ - applyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { const weatherType = pokemon.scene.arena.weather?.weatherType; let turnOffWeather = false; @@ -2423,10 +2336,6 @@ export class PreSwitchOutClearWeatherAbAttr extends PreSwitchOutAbAttr { break; } - if (simulated) { - return turnOffWeather; - } - if (turnOffWeather) { pokemon.scene.arena.trySetWeather(WeatherType.NONE, false); return true; @@ -2437,14 +2346,11 @@ export class PreSwitchOutClearWeatherAbAttr extends PreSwitchOutAbAttr { } export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr { - applyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { if (!pokemon.isFullHp()) { - if (!simulated) { - const healAmount = Utils.toDmgValue(pokemon.getMaxHp() * 0.33); - pokemon.heal(healAmount); - pokemon.updateInfo(); - } - + const healAmount = Math.floor(pokemon.getMaxHp() * 0.33); + pokemon.heal(healAmount); + pokemon.updateInfo(); return true; } @@ -2473,12 +2379,10 @@ export class PreSwitchOutFormChangeAbAttr extends PreSwitchOutAbAttr { * @param args N/A * @returns true if the form change was successful */ - applyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) { - if (!simulated) { - pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); - } + pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); return true; } @@ -2488,7 +2392,7 @@ export class PreSwitchOutFormChangeAbAttr extends PreSwitchOutAbAttr { } export class PreStatChangeAbAttr extends AbAttr { - applyPreStatChange(pokemon: Pokemon | null, passive: boolean, simulated: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreStatChange(pokemon: Pokemon | null, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } @@ -2502,7 +2406,7 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr { this.protectedStat = protectedStat; } - applyPreStatChange(pokemon: Pokemon, passive: boolean, simulated: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (Utils.isNullOrUndefined(this.protectedStat) || stat === this.protectedStat) { cancelled.value = true; return true; @@ -2546,20 +2450,16 @@ export class ConfusionOnStatusEffectAbAttr extends PostAttackAbAttr { * @param args [0] {@linkcode StatusEffect} applied by move * @returns true if defender is confused */ - applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (this.effects.indexOf(args[0]) > -1 && !defender.isFainted()) { - if (simulated) { - return defender.canAddTag(BattlerTagType.CONFUSED); - } else { - return defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedInt(3,2), move.id, defender.id); - } + return defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedInt(3,2), move.id, defender.id); } return false; } } export class PreSetStatusAbAttr extends AbAttr { - applyPreSetStatus(pokemon: Pokemon, passive: boolean, simulated: boolean, effect: StatusEffect | undefined, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect | undefined, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } @@ -2589,7 +2489,7 @@ export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { * @param args - n/a * @returns A boolean indicating the result of the status application. */ - applyPreSetStatus(pokemon: Pokemon, passive: boolean, simulated: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.immuneEffects.length < 1 || this.immuneEffects.includes(effect)) { cancelled.value = true; return true; @@ -2625,7 +2525,7 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusEffectImmunityAbAttr export class UserFieldStatusEffectImmunityAbAttr extends PreSetStatusEffectImmunityAbAttr { } export class PreApplyBattlerTagAbAttr extends AbAttr { - applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, simulated: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } @@ -2643,12 +2543,10 @@ export class PreApplyBattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { this.immuneTagType = immuneTagType; } - applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, simulated: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (tag.tagType === this.immuneTagType) { cancelled.value = true; - if (!simulated) { - this.battlerTag = tag; - } + this.battlerTag = tag; return true; } @@ -2677,14 +2575,14 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagImmunityAbAttr { export class UserFieldBattlerTagImmunityAbAttr extends PreApplyBattlerTagImmunityAbAttr { } export class BlockCritAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.BooleanHolder).value = true; return true; } } export class BonusCritAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.BooleanHolder).value = true; return true; } @@ -2699,7 +2597,7 @@ export class MultCritAbAttr extends AbAttr { this.multAmount = multAmount; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const critMult = args[0] as Utils.NumberHolder; if (critMult.value > 1) { critMult.value *= this.multAmount; @@ -2730,7 +2628,7 @@ export class ConditionalCritAbAttr extends AbAttr { * [1] {@linkcode Pokemon} Target. * [2] {@linkcode Move} used by ability user. */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const target = (args[1] as Pokemon); const move = (args[2] as Move); if (!this.condition(pokemon,target,move)) { @@ -2743,7 +2641,7 @@ export class ConditionalCritAbAttr extends AbAttr { } export class BlockNonDirectDamageAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } @@ -2771,7 +2669,7 @@ export class BlockStatusDamageAbAttr extends AbAttr { * @param {any[]} args N/A * @returns Returns true if status damage is blocked */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (pokemon.status && this.effects.includes(pokemon.status.effect)) { cancelled.value = true; return true; @@ -2781,7 +2679,7 @@ export class BlockStatusDamageAbAttr extends AbAttr { } export class BlockOneHitKOAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } @@ -2807,7 +2705,7 @@ export class ChangeMovePriorityAbAttr extends AbAttr { this.changeAmount = changeAmount; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (!this.moveFunc(pokemon, args[0] as Move)) { return false; } @@ -2820,7 +2718,7 @@ export class ChangeMovePriorityAbAttr extends AbAttr { export class IgnoreContactAbAttr extends AbAttr { } export class PreWeatherEffectAbAttr extends AbAttr { - applyPreWeatherEffect(pokemon: Pokemon, passive: Boolean, simulated: boolean, weather: Weather | null, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, weather: Weather | null, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; } } @@ -2836,7 +2734,7 @@ export class BlockWeatherDamageAttr extends PreWeatherDamageAbAttr { this.weatherTypes = weatherTypes; } - applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (!this.weatherTypes.length || this.weatherTypes.indexOf(weather?.weatherType) > -1) { cancelled.value = true; } @@ -2854,7 +2752,7 @@ export class SuppressWeatherEffectAbAttr extends PreWeatherEffectAbAttr { this.affectsImmutable = !!affectsImmutable; } - applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.affectsImmutable || weather.isImmutable()) { cancelled.value = true; return true; @@ -2961,7 +2859,7 @@ export class ForewarnAbAttr extends PostSummonAbAttr { super(true); } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { let maxPowerSeen = 0; let maxMove = ""; let movePower = 0; @@ -2985,9 +2883,7 @@ export class ForewarnAbAttr extends PostSummonAbAttr { } } } - if (!simulated) { - pokemon.scene.queueMessage(i18next.t("abilityTriggers:forewarn", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: maxMove })); - } + pokemon.scene.queueMessage(i18next.t("abilityTriggers:forewarn", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: maxMove })); return true; } } @@ -2997,19 +2893,17 @@ export class FriskAbAttr extends PostSummonAbAttr { super(true); } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (!simulated) { - for (const opponent of pokemon.getOpponents()) { - pokemon.scene.queueMessage(i18next.t("abilityTriggers:frisk", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), opponentName: opponent.name, opponentAbilityName: opponent.getAbility().name })); - setAbilityRevealed(opponent); - } + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { + for (const opponent of pokemon.getOpponents()) { + pokemon.scene.queueMessage(i18next.t("abilityTriggers:frisk", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), opponentName: opponent.name, opponentAbilityName: opponent.getAbility().name })); + setAbilityRevealed(opponent); } return true; } } export class PostWeatherChangeAbAttr extends AbAttr { - applyPostWeatherChange(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: WeatherType, args: any[]): boolean { + applyPostWeatherChange(pokemon: Pokemon, passive: boolean, weather: WeatherType, args: any[]): boolean { return false; } } @@ -3027,17 +2921,13 @@ export class PostWeatherChangeAddBattlerTagAttr extends PostWeatherChangeAbAttr this.weatherTypes = weatherTypes; } - applyPostWeatherChange(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: WeatherType, args: any[]): boolean { + applyPostWeatherChange(pokemon: Pokemon, passive: boolean, weather: WeatherType, args: any[]): boolean { console.log(this.weatherTypes.find(w => weather === w), WeatherType[weather]); if (!this.weatherTypes.find(w => weather === w)) { return false; } - if (simulated) { - return pokemon.canAddTag(this.tagType); - } else { - return pokemon.addTag(this.tagType, this.turnCount); - } + return pokemon.addTag(this.tagType, this.turnCount); } } @@ -3050,7 +2940,7 @@ export class PostWeatherLapseAbAttr extends AbAttr { this.weatherTypes = weatherTypes; } - applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather | null, args: any[]): boolean | Promise { + applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, weather: Weather | null, args: any[]): boolean | Promise { return false; } @@ -3068,14 +2958,12 @@ export class PostWeatherLapseHealAbAttr extends PostWeatherLapseAbAttr { this.healFactor = healFactor; } - applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather, args: any[]): boolean { + applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, weather: Weather, args: any[]): boolean { if (!pokemon.isFullHp()) { const scene = pokemon.scene; const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; - if (!simulated) { - scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / (16 / this.healFactor)), i18next.t("abilityTriggers:postWeatherLapseHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), true)); - } + scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), + Math.max(Math.floor(pokemon.getMaxHp() / (16 / this.healFactor)), 1), i18next.t("abilityTriggers:postWeatherLapseHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), true)); return true; } @@ -3092,24 +2980,20 @@ export class PostWeatherLapseDamageAbAttr extends PostWeatherLapseAbAttr { this.damageFactor = damageFactor; } - applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather, args: any[]): boolean { + applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, weather: Weather, args: any[]): boolean { const scene = pokemon.scene; if (pokemon.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { return false; } - - if (!simulated) { - const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; - scene.queueMessage(i18next.t("abilityTriggers:postWeatherLapseDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName })); - pokemon.damageAndUpdate(Utils.toDmgValue(pokemon.getMaxHp() / (16 / this.damageFactor)), HitResult.OTHER); - } - + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; + scene.queueMessage(i18next.t("abilityTriggers:postWeatherLapseDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName })); + pokemon.damageAndUpdate(Math.ceil(pokemon.getMaxHp() / (16 / this.damageFactor)), HitResult.OTHER); return true; } } export class PostTerrainChangeAbAttr extends AbAttr { - applyPostTerrainChange(pokemon: Pokemon, passive: boolean, simulated: boolean, terrain: TerrainType, args: any[]): boolean { + applyPostTerrainChange(pokemon: Pokemon, passive: boolean, terrain: TerrainType, args: any[]): boolean { return false; } } @@ -3127,16 +3011,12 @@ export class PostTerrainChangeAddBattlerTagAttr extends PostTerrainChangeAbAttr this.terrainTypes = terrainTypes; } - applyPostTerrainChange(pokemon: Pokemon, passive: boolean, simulated: boolean, terrain: TerrainType, args: any[]): boolean { + applyPostTerrainChange(pokemon: Pokemon, passive: boolean, terrain: TerrainType, args: any[]): boolean { if (!this.terrainTypes.find(t => t === terrain)) { return false; } - if (simulated) { - return pokemon.canAddTag(this.tagType); - } else { - return pokemon.addTag(this.tagType, this.turnCount); - } + return pokemon.addTag(this.tagType, this.turnCount); } } @@ -3148,7 +3028,7 @@ function getTerrainCondition(...terrainTypes: TerrainType[]): AbAttrCondition { } export class PostTurnAbAttr extends AbAttr { - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { return false; } } @@ -3174,15 +3054,13 @@ export class PostTurnStatusHealAbAttr extends PostTurnAbAttr { * @param {any[]} args N/A * @returns Returns true if healed from status, false if not */ - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { if (pokemon.status && this.effects.includes(pokemon.status.effect)) { if (!pokemon.isFullHp()) { - if (!simulated) { - const scene = pokemon.scene; - const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; - scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / 8), i18next.t("abilityTriggers:poisonHeal", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName }), true)); - } + const scene = pokemon.scene; + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; + scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), + Math.max(Math.floor(pokemon.getMaxHp() / 8), 1), i18next.t("abilityTriggers:poisonHeal", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName }), true)); return true; } } @@ -3203,19 +3081,17 @@ export class PostTurnResetStatusAbAttr extends PostTurnAbAttr { this.allyTarget = allyTarget; } - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { if (this.allyTarget) { this.target = pokemon.getAlly(); } else { this.target = pokemon; } if (this.target?.status) { - if (!simulated) { - this.target.scene.queueMessage(getStatusEffectHealText(this.target.status?.effect, getPokemonNameWithAffix(this.target))); - this.target.resetStatus(false); - this.target.updateInfo(); - } + this.target.scene.queueMessage(getStatusEffectHealText(this.target.status?.effect, getPokemonNameWithAffix(this.target))); + this.target.resetStatus(false); + this.target.updateInfo(); return true; } @@ -3240,7 +3116,7 @@ export class PostTurnLootAbAttr extends PostTurnAbAttr { super(); } - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const pass = Phaser.Math.RND.realInRange(0, 1); // Clamp procChance to [0, 1]. Skip if didn't proc (less than pass) if (Math.max(Math.min(this.procChance(pokemon), 1), 0) < pass) { @@ -3248,7 +3124,7 @@ export class PostTurnLootAbAttr extends PostTurnAbAttr { } if (this.itemType === "EATEN_BERRIES") { - return this.createEatenBerry(pokemon, simulated); + return this.createEatenBerry(pokemon); } else { return false; } @@ -3257,20 +3133,15 @@ export class PostTurnLootAbAttr extends PostTurnAbAttr { /** * Create a new berry chosen randomly from the berries the pokemon ate this battle * @param pokemon The pokemon with this ability - * @param simulated whether the associated ability call is simulated * @returns whether a new berry was created */ - createEatenBerry(pokemon: Pokemon, simulated: boolean): boolean { + createEatenBerry(pokemon: Pokemon): boolean { const berriesEaten = pokemon.battleData.berriesEaten; if (!berriesEaten.length) { return false; } - if (simulated) { - return true; - } - const randomIdx = Utils.randSeedInt(berriesEaten.length); const chosenBerryType = berriesEaten[randomIdx]; const chosenBerry = new BerryModifierType(chosenBerryType); @@ -3304,17 +3175,17 @@ export class MoodyAbAttr extends PostTurnAbAttr { super(true); } - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const selectableStats = [BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD]; const increaseStatArray = selectableStats.filter(s => pokemon.summonData.battleStats[s] < 6); let decreaseStatArray = selectableStats.filter(s => pokemon.summonData.battleStats[s] > -6); - if (!simulated && increaseStatArray.length > 0) { + if (increaseStatArray.length > 0) { const increaseStat = increaseStatArray[Utils.randInt(increaseStatArray.length)]; decreaseStatArray = decreaseStatArray.filter(s => s !== increaseStat); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [increaseStat], 2)); } - if (!simulated && decreaseStatArray.length > 0) { + if (decreaseStatArray.length > 0) { const decreaseStat = selectableStats[Utils.randInt(selectableStats.length)]; pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [decreaseStat], -1)); } @@ -3335,24 +3206,19 @@ export class PostTurnStatChangeAbAttr extends PostTurnAbAttr { this.levels = levels; } - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (!simulated) { - pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.levels)); - } + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { + pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.levels)); return true; } } export class PostTurnHealAbAttr extends PostTurnAbAttr { - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { if (!pokemon.isFullHp()) { - if (!simulated) { - const scene = pokemon.scene; - const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; - scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / 16), i18next.t("abilityTriggers:postTurnHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), true)); - } - + const scene = pokemon.scene; + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; + scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), + Math.max(Math.floor(pokemon.getMaxHp() / 16), 1), i18next.t("abilityTriggers:postTurnHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), true)); return true; } @@ -3369,13 +3235,10 @@ export class PostTurnFormChangeAbAttr extends PostTurnAbAttr { this.formFunc = formFunc; } - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) { - if (!simulated) { - pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); - } - + pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); return true; } @@ -3393,18 +3256,15 @@ export class PostTurnHurtIfSleepingAbAttr extends PostTurnAbAttr { * Deals damage to all sleeping opponents equal to 1/8 of their max hp (min 1) * @param {Pokemon} pokemon Pokemon that has this ability * @param {boolean} passive N/A - * @param {boolean} simulated true if applying in a simulated call. * @param {any[]} args N/A * @returns {boolean} true if any opponents are sleeping */ - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean | Promise { + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { let hadEffect: boolean = false; for (const opp of pokemon.getOpponents()) { if ((opp.status?.effect === StatusEffect.SLEEP || opp.hasAbility(Abilities.COMATOSE)) && !opp.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { - if (!simulated) { - opp.damageAndUpdate(Utils.toDmgValue(opp.getMaxHp() / 8), HitResult.OTHER); - pokemon.scene.queueMessage(i18next.t("abilityTriggers:badDreams", {pokemonName: getPokemonNameWithAffix(opp)})); - } + opp.damageAndUpdate(Math.floor(Math.max(1, opp.getMaxHp() / 8)), HitResult.OTHER); + pokemon.scene.queueMessage(i18next.t("abilityTriggers:badDreams", {pokemonName: getPokemonNameWithAffix(opp)})); hadEffect = true; } @@ -3429,10 +3289,7 @@ export class FetchBallAbAttr extends PostTurnAbAttr { * @param args N/A * @returns true if player has used a pokeball and this pokemon is owned by the player */ - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (simulated) { - return false; - } + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const lastUsed = pokemon.scene.currentBattle.lastUsedPokeball; if (lastUsed !== null && !!pokemon.isPlayer) { pokemon.scene.pokeballCounts[lastUsed]++; @@ -3455,13 +3312,9 @@ export class PostBiomeChangeWeatherChangeAbAttr extends PostBiomeChangeAbAttr { this.weatherType = weatherType; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (!pokemon.scene.arena.weather?.isImmutable()) { - if (simulated) { - return pokemon.scene.arena.weather?.weatherType !== this.weatherType; - } else { - return pokemon.scene.arena.trySetWeather(this.weatherType, true); - } + return pokemon.scene.arena.trySetWeather(this.weatherType, true); } return false; @@ -3477,12 +3330,8 @@ export class PostBiomeChangeTerrainChangeAbAttr extends PostBiomeChangeAbAttr { this.terrainType = terrainType; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (simulated) { - return pokemon.scene.arena.terrain?.terrainType !== this.terrainType; - } else { - return pokemon.scene.arena.trySetTerrain(this.terrainType, true); - } + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + return pokemon.scene.arena.trySetTerrain(this.terrainType, true); } } @@ -3491,7 +3340,7 @@ export class PostBiomeChangeTerrainChangeAbAttr extends PostBiomeChangeAbAttr { * @extends AbAttr */ export class PostMoveUsedAbAttr extends AbAttr { - applyPostMoveUsed(pokemon: Pokemon, move: PokemonMove, source: Pokemon, targets: BattlerIndex[], simulated: boolean, args: any[]): boolean | Promise { + applyPostMoveUsed(pokemon: Pokemon, move: PokemonMove, source: Pokemon, targets: BattlerIndex[], args: any[]): boolean | Promise { return false; } } @@ -3512,22 +3361,20 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr { * * @return true if the Dancer ability was resolved */ - applyPostMoveUsed(dancer: Pokemon, move: PokemonMove, source: Pokemon, targets: BattlerIndex[], simulated: boolean, args: any[]): boolean | Promise { + applyPostMoveUsed(dancer: Pokemon, move: PokemonMove, source: Pokemon, targets: BattlerIndex[], args: any[]): boolean | Promise { // List of tags that prevent the Dancer from replicating the move const forbiddenTags = [BattlerTagType.FLYING, BattlerTagType.UNDERWATER, BattlerTagType.UNDERGROUND, BattlerTagType.HIDDEN]; // The move to replicate cannot come from the Dancer if (source.getBattlerIndex() !== dancer.getBattlerIndex() && !dancer.summonData.tags.some(tag => forbiddenTags.includes(tag.tagType))) { - if (!simulated) { - // If the move is an AttackMove or a StatusMove the Dancer must replicate the move on the source of the Dance - if (move.getMove() instanceof AttackMove || move.getMove() instanceof StatusMove) { - const target = this.getTarget(dancer, source, targets); - dancer.scene.unshiftPhase(new MovePhase(dancer.scene, dancer, target, move, true)); - } else if (move.getMove() instanceof SelfStatusMove) { - // If the move is a SelfStatusMove (ie. Swords Dance) the Dancer should replicate it on itself - dancer.scene.unshiftPhase(new MovePhase(dancer.scene, dancer, [dancer.getBattlerIndex()], move, true)); - } + // If the move is an AttackMove or a StatusMove the Dancer must replicate the move on the source of the Dance + if (move.getMove() instanceof AttackMove || move.getMove() instanceof StatusMove) { + const target = this.getTarget(dancer, source, targets); + dancer.scene.unshiftPhase(new MovePhase(dancer.scene, dancer, target, move, true)); + } else if (move.getMove() instanceof SelfStatusMove) { + // If the move is a SelfStatusMove (ie. Swords Dance) the Dancer should replicate it on itself + dancer.scene.unshiftPhase(new MovePhase(dancer.scene, dancer, [dancer.getBattlerIndex()], move, true)); } return true; } @@ -3558,7 +3405,7 @@ export class StatChangeMultiplierAbAttr extends AbAttr { this.multiplier = multiplier; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.IntegerHolder).value *= this.multiplier; return true; @@ -3566,10 +3413,8 @@ export class StatChangeMultiplierAbAttr extends AbAttr { } export class StatChangeCopyAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { - if (!simulated) { - pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, (args[0] as BattleStat[]), (args[1] as integer), true, false, false)); - } + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { + pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, (args[0] as BattleStat[]), (args[1] as integer), true, false, false)); return true; } } @@ -3579,7 +3424,7 @@ export class BypassBurnDamageReductionAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; @@ -3603,15 +3448,15 @@ export class ReduceBurnDamageAbAttr extends AbAttr { * @param args `[0]` {@linkcode Utils.NumberHolder} The damage value being modified * @returns `true` */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - (args[0] as Utils.NumberHolder).value = Utils.toDmgValue((args[0] as Utils.NumberHolder).value * this.multiplier); + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + (args[0] as Utils.NumberHolder).value = Math.max(Math.floor((args[0] as Utils.NumberHolder).value * this.multiplier), 1); return true; } } export class DoubleBerryEffectAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.NumberHolder).value *= 2; return true; @@ -3619,7 +3464,7 @@ export class DoubleBerryEffectAbAttr extends AbAttr { } export class PreventBerryUseAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; @@ -3642,25 +3487,24 @@ export class HealFromBerryUseAbAttr extends AbAttr { this.healPercent = Math.max(Math.min(healPercent, 1), 0); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, ...args: [Utils.BooleanHolder, any[]]): boolean { + apply(pokemon: Pokemon, passive: boolean, ...args: [Utils.BooleanHolder, any[]]): boolean { const { name: abilityName } = passive ? pokemon.getPassiveAbility() : pokemon.getAbility(); - if (!simulated) { - pokemon.scene.unshiftPhase( - new PokemonHealPhase( - pokemon.scene, - pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() * this.healPercent), - i18next.t("abilityTriggers:healFromBerryUse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), - true - ) - ); - } + pokemon.scene.unshiftPhase( + new PokemonHealPhase( + pokemon.scene, + pokemon.getBattlerIndex(), + Math.max(Math.floor(pokemon.getMaxHp() * this.healPercent), 1), + i18next.t("abilityTriggers:healFromBerryUse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), + true + ) + ); + return true; } } export class RunSuccessAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.IntegerHolder).value = 256; return true; @@ -3683,7 +3527,7 @@ export class CheckTrappedAbAttr extends AbAttr { this.arenaTrapCondition = condition; } - applyCheckTrapped(pokemon: Pokemon, passive: boolean, simulated: boolean, trapped: Utils.BooleanHolder, otherPokemon: Pokemon, args: any[]): boolean | Promise { + applyCheckTrapped(pokemon: Pokemon, passive: boolean, trapped: Utils.BooleanHolder, otherPokemon: Pokemon, args: any[]): boolean | Promise { return false; } } @@ -3708,7 +3552,7 @@ export class ArenaTrapAbAttr extends CheckTrappedAbAttr { * @param args N/A * @returns if enemy Pokemon is trapped or not */ - applyCheckTrapped(pokemon: Pokemon, passive: boolean, simulated: boolean, trapped: Utils.BooleanHolder, otherPokemon: Pokemon, args: any[]): boolean { + applyCheckTrapped(pokemon: Pokemon, passive: boolean, trapped: Utils.BooleanHolder, otherPokemon: Pokemon, args: any[]): boolean { if (this.arenaTrapCondition(pokemon, otherPokemon)) { if (otherPokemon.getTypes(true).includes(Type.GHOST) || (otherPokemon.getTypes(true).includes(Type.STELLAR) && otherPokemon.getTypes().includes(Type.GHOST))) { trapped.value = false; @@ -3730,7 +3574,7 @@ export class ArenaTrapAbAttr extends CheckTrappedAbAttr { } export class MaxMultiHitAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.IntegerHolder).value = 0; return true; @@ -3742,15 +3586,15 @@ export class PostBattleAbAttr extends AbAttr { super(true); } - applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostBattle(pokemon: Pokemon, passive: boolean, args: any[]): boolean { return false; } } export class PostBattleLootAbAttr extends PostBattleAbAttr { - applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostBattle(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const postBattleLoot = pokemon.scene.currentBattle.postBattleLoot; - if (!simulated && postBattleLoot.length) { + if (postBattleLoot.length) { const randItem = Utils.randSeedItem(postBattleLoot); //@ts-ignore - TODO see below if (pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, true, 1, true)) { // TODO: fix. This is a promise!? @@ -3765,7 +3609,7 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr { } export class PostFaintAbAttr extends AbAttr { - applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { return false; } } @@ -3784,7 +3628,7 @@ export class PostFaintClearWeatherAbAttr extends PostFaintAbAttr { * @param args N/A * @returns {boolean} Returns true if the weather clears, otherwise false. */ - applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { const weatherType = pokemon.scene.arena.weather?.weatherType; let turnOffWeather = false; @@ -3810,10 +3654,6 @@ export class PostFaintClearWeatherAbAttr extends PostFaintAbAttr { break; } - if (simulated) { - return turnOffWeather; - } - if (turnOffWeather) { pokemon.scene.arena.trySetWeather(WeatherType.NONE, false); return true; @@ -3832,17 +3672,15 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr { this.damageRatio = damageRatio; } - applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { const cancelled = new Utils.BooleanHolder(false); - pokemon.scene.getField(true).map(p => applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled, simulated)); + pokemon.scene.getField(true).map(p=>applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled)); if (cancelled.value || attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { return false; } - if (!simulated) { - attacker.damageAndUpdate(Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); - attacker.turnData.damageTaken += Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)); - } + attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); + attacker.turnData.damageTaken += Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)); return true; } @@ -3862,12 +3700,10 @@ export class PostFaintHPDamageAbAttr extends PostFaintAbAttr { super (); } - applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (!simulated) { - const damage = pokemon.turnData.attacksReceived[0].damage; - attacker.damageAndUpdate((damage), HitResult.OTHER); - attacker.turnData.damageTaken += damage; - } + applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + const damage = pokemon.turnData.attacksReceived[0].damage; + attacker.damageAndUpdate((damage), HitResult.OTHER); + attacker.turnData.damageTaken += damage; return true; } @@ -3877,7 +3713,7 @@ export class PostFaintHPDamageAbAttr extends PostFaintAbAttr { } export class RedirectMoveAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.canRedirect(args[0] as Moves)) { const target = args[1] as Utils.IntegerHolder; const newTarget = pokemon.getBattlerIndex(); @@ -3920,9 +3756,9 @@ export class ReduceStatusEffectDurationAbAttr extends AbAttr { this.statusEffect = statusEffect; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (args[0] === this.statusEffect) { - (args[1] as Utils.IntegerHolder).value = Utils.toDmgValue((args[1] as Utils.IntegerHolder).value / 2); + (args[1] as Utils.IntegerHolder).value = Math.floor((args[1] as Utils.IntegerHolder).value / 2); return true; } @@ -3949,10 +3785,8 @@ export class FlinchStatChangeAbAttr extends FlinchEffectAbAttr { this.levels = levels; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (!simulated) { - pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.levels)); - } + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, this.stats, this.levels)); return true; } } @@ -3960,7 +3794,7 @@ export class FlinchStatChangeAbAttr extends FlinchEffectAbAttr { export class IncreasePpAbAttr extends AbAttr { } export class ForceSwitchOutImmunityAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; return true; } @@ -3971,7 +3805,7 @@ export class ReduceBerryUseThresholdAbAttr extends AbAttr { super(); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const hpRatio = pokemon.getHpRatio(); if (args[0].value < hpRatio) { @@ -3992,7 +3826,7 @@ export class WeightMultiplierAbAttr extends AbAttr { this.multiplier = multiplier; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Utils.NumberHolder).value *= this.multiplier; return true; @@ -4004,7 +3838,7 @@ export class SyncEncounterNatureAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { (args[0] as Pokemon).setNature(pokemon.getNature()); return true; @@ -4020,7 +3854,7 @@ export class MoveAbilityBypassAbAttr extends AbAttr { this.moveIgnoreFunc = moveIgnoreFunc || ((pokemon, move) => true); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.moveIgnoreFunc(pokemon, (args[0] as Move))) { cancelled.value = true; return true; @@ -4034,7 +3868,7 @@ export class SuppressFieldAbilitiesAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const ability = (args[0] as Ability); if (!ability.hasAttr(UnsuppressableAbilityAbAttr) && !ability.hasAttr(SuppressFieldAbilitiesAbAttr)) { cancelled.value = true; @@ -4089,7 +3923,7 @@ export class IgnoreTypeImmunityAbAttr extends AbAttr { this.allowedMoveTypes = allowedMoveTypes; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.defenderType === (args[1] as Type) && this.allowedMoveTypes.includes(args[0] as Type)) { cancelled.value = true; return true; @@ -4112,7 +3946,7 @@ export class IgnoreTypeStatusEffectImmunityAbAttr extends AbAttr { this.defenderType = defenderType; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.statusEffect.includes(args[0] as StatusEffect) && this.defenderType.includes(args[1] as Type)) { cancelled.value = true; return true; @@ -4139,10 +3973,8 @@ export class MoneyAbAttr extends PostBattleAbAttr { * @param args N/A * @returns true */ - applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (!simulated) { - pokemon.scene.currentBattle.moneyScattered += pokemon.scene.getWaveMoneyAmount(0.2); - } + applyPostBattle(pokemon: Pokemon, passive: boolean, args: any[]): boolean { + pokemon.scene.currentBattle.moneyScattered += pokemon.scene.getWaveMoneyAmount(0.2); return true; } } @@ -4181,11 +4013,11 @@ export class PostSummonStatChangeOnArenaAbAttr extends PostSummonStatChangeAbAtt * @param {any[]} args - Additional arguments. * @returns {boolean} - Returns true if the stat change was applied, otherwise false. */ - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { const side = pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; if (pokemon.scene.arena.getTagOnSide(this.tagType, side)) { - return super.applyPostSummon(pokemon, passive, simulated, args); + return super.applyPostSummon(pokemon, passive, args); } return false; } @@ -4223,14 +4055,12 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr { * @param {any[]} args Additional arguments. * @returns {boolean} Whether the immunity was applied. */ - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.condition(pokemon, attacker, move)) { - if (!simulated) { - (args[0] as Utils.NumberHolder).value = this.multiplier; - pokemon.removeTag(this.tagType); - if (this.recoilDamageFunc) { - pokemon.damageAndUpdate(this.recoilDamageFunc(pokemon), HitResult.OTHER); - } + (args[0] as Utils.NumberHolder).value = this.multiplier; + pokemon.removeTag(this.tagType); + if (this.recoilDamageFunc) { + pokemon.damageAndUpdate(this.recoilDamageFunc(pokemon), HitResult.OTHER); } return true; } @@ -4274,10 +4104,7 @@ export class BypassSpeedChanceAbAttr extends AbAttr { * @param {any[]} args [0] {@linkcode Utils.BooleanHolder} set to true when the ability activated * @returns {boolean} - whether the ability was activated. */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (simulated) { - return false; - } + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const bypassSpeed = args[0] as Utils.BooleanHolder; if (!bypassSpeed.value && pokemon.randSeedInt(100) < this.chance) { @@ -4320,7 +4147,7 @@ export class PreventBypassSpeedChanceAbAttr extends AbAttr { * @argument {boolean} bypassSpeed - determines if a Pokemon is able to bypass speed at the moment * @argument {boolean} canCheckHeldItems - determines if a Pokemon has access to Quick Claw's effects or not */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const bypassSpeed = args[0] as Utils.BooleanHolder; const canCheckHeldItems = args[1] as Utils.BooleanHolder; @@ -4342,7 +4169,7 @@ async function applyAbAttrsInternal( applyFunc: AbAttrApplyFunc, args: any[], showAbilityInstant: boolean = false, - quiet: boolean = false, + isQuiet: boolean = false, messages: string[] = [], ) { for (const passive of [false, true]) { @@ -4369,11 +4196,11 @@ async function applyAbAttrsInternal( if (pokemon.summonData && !pokemon.summonData.abilitiesApplied.includes(ability.id)) { pokemon.summonData.abilitiesApplied.push(ability.id); } - if (pokemon.battleData && !quiet && !pokemon.battleData.abilitiesApplied.includes(ability.id)) { + if (pokemon.battleData && !pokemon.battleData.abilitiesApplied.includes(ability.id)) { pokemon.battleData.abilitiesApplied.push(ability.id); } - if (attr.showAbility && !quiet) { + if (attr.showAbility && !isQuiet) { if (showAbilityInstant) { pokemon.scene.abilityBar.showAbility(pokemon, passive); } else { @@ -4381,12 +4208,12 @@ async function applyAbAttrsInternal( } } - if (!quiet) { - const message = attr.getTriggerMessage(pokemon, ability.name, args); - if (message) { + const message = attr.getTriggerMessage(pokemon, ability.name, args); + if (message) { + if (!isQuiet) { pokemon.scene.queueMessage(message); - messages.push(message); } + messages.push(message); } } } @@ -4395,33 +4222,34 @@ async function applyAbAttrsInternal( } } -export function applyAbAttrs(attrType: Constructor, pokemon: Pokemon, cancelled: Utils.BooleanHolder | null, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.apply(pokemon, passive, simulated, cancelled, args), args, false, simulated); +export function applyAbAttrs(attrType: Constructor, pokemon: Pokemon, cancelled: Utils.BooleanHolder | null, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.apply(pokemon, passive, cancelled, args), args); } export function applyPostBattleInitAbAttrs(attrType: Constructor, - pokemon: Pokemon, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostBattleInit(pokemon, passive, simulated, args), args, false, simulated); + pokemon: Pokemon, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostBattleInit(pokemon, passive, args), args); } export function applyPreDefendAbAttrs(attrType: Constructor, - pokemon: Pokemon, attacker: Pokemon, move: Move | null, cancelled: Utils.BooleanHolder | null, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args), args, false, simulated); + pokemon: Pokemon, attacker: Pokemon, move: Move | null, cancelled: Utils.BooleanHolder | null, ...args: any[]): Promise { + const simulated = args.length > 1 && args[1]; + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreDefend(pokemon, passive, attacker, move, cancelled, args), args, false, simulated); } export function applyPostDefendAbAttrs(attrType: Constructor, - pokemon: Pokemon, attacker: Pokemon, move: Move, hitResult: HitResult | null, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostDefend(pokemon, passive, simulated, attacker, move, hitResult, args), args, false, simulated); + pokemon: Pokemon, attacker: Pokemon, move: Move, hitResult: HitResult | null, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostDefend(pokemon, passive, attacker, move, hitResult, args), args); } export function applyPostMoveUsedAbAttrs(attrType: Constructor, - pokemon: Pokemon, move: PokemonMove, source: Pokemon, targets: BattlerIndex[], simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostMoveUsed(pokemon, move, source, targets, simulated, args), args, false, simulated); + pokemon: Pokemon, move: PokemonMove, source: Pokemon, targets: BattlerIndex[], ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostMoveUsed(pokemon, move, source, targets, args), args); } export function applyBattleStatMultiplierAbAttrs(attrType: Constructor, - pokemon: Pokemon, battleStat: BattleStat, statValue: Utils.NumberHolder, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyBattleStat(pokemon, passive, simulated, battleStat, statValue, args), args, false, simulated); + pokemon: Pokemon, battleStat: BattleStat, statValue: Utils.NumberHolder, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyBattleStat(pokemon, passive, battleStat, statValue, args), args); } /** @@ -4435,98 +4263,99 @@ export function applyBattleStatMultiplierAbAttrs(attrType: Constructor, - pokemon: Pokemon, stat: Stat, statValue: Utils.NumberHolder, checkedPokemon: Pokemon, hasApplied: Utils.BooleanHolder, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyFieldBattleStat(pokemon, passive, simulated, stat, statValue, checkedPokemon, hasApplied, args), args, false, simulated); + pokemon: Pokemon, stat: Stat, statValue: Utils.NumberHolder, checkedPokemon: Pokemon, hasApplied: Utils.BooleanHolder, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyFieldBattleStat(pokemon, passive, stat, statValue, checkedPokemon, hasApplied, args), args); } export function applyPreAttackAbAttrs(attrType: Constructor, - pokemon: Pokemon, defender: Pokemon | null, move: Move, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreAttack(pokemon, passive, simulated, defender, move, args), args, false, simulated); + pokemon: Pokemon, defender: Pokemon | null, move: Move, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreAttack(pokemon, passive, defender, move, args), args); } export function applyPostAttackAbAttrs(attrType: Constructor, - pokemon: Pokemon, defender: Pokemon, move: Move, hitResult: HitResult | null, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args), args, false, simulated); + pokemon: Pokemon, defender: Pokemon, move: Move, hitResult: HitResult | null, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostAttack(pokemon, passive, defender, move, hitResult, args), args); } export function applyPostKnockOutAbAttrs(attrType: Constructor, - pokemon: Pokemon, knockedOut: Pokemon, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostKnockOut(pokemon, passive, simulated, knockedOut, args), args, false, simulated); + pokemon: Pokemon, knockedOut: Pokemon, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostKnockOut(pokemon, passive, knockedOut, args), args); } export function applyPostVictoryAbAttrs(attrType: Constructor, - pokemon: Pokemon, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostVictory(pokemon, passive, simulated, args), args, false, simulated); + pokemon: Pokemon, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostVictory(pokemon, passive, args), args); } export function applyPostSummonAbAttrs(attrType: Constructor, - pokemon: Pokemon, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostSummon(pokemon, passive, simulated, args), args, false, simulated); + pokemon: Pokemon, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostSummon(pokemon, passive, args), args); } export function applyPreSwitchOutAbAttrs(attrType: Constructor, - pokemon: Pokemon, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreSwitchOut(pokemon, passive, simulated, args), args, true, simulated); + pokemon: Pokemon, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreSwitchOut(pokemon, passive, args), args, true); } export function applyPreStatChangeAbAttrs(attrType: Constructor, - pokemon: Pokemon | null, stat: BattleStat, cancelled: Utils.BooleanHolder, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreStatChange(pokemon, passive, simulated, stat, cancelled, args), args, false, simulated); + pokemon: Pokemon | null, stat: BattleStat, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreStatChange(pokemon, passive, stat, cancelled, args), args); } export function applyPostStatChangeAbAttrs(attrType: Constructor, - pokemon: Pokemon, stats: BattleStat[], levels: integer, selfTarget: boolean, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostStatChange(pokemon, simulated, stats, levels, selfTarget, args), args, false, simulated); + pokemon: Pokemon, stats: BattleStat[], levels: integer, selfTarget: boolean, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostStatChange(pokemon, stats, levels, selfTarget, args), args); } export function applyPreSetStatusAbAttrs(attrType: Constructor, - pokemon: Pokemon, effect: StatusEffect | undefined, cancelled: Utils.BooleanHolder, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreSetStatus(pokemon, passive, simulated, effect, cancelled, args), args, false, simulated); + pokemon: Pokemon, effect: StatusEffect | undefined, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { + const simulated = args.length > 1 && args[1]; + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreSetStatus(pokemon, passive, effect, cancelled, args), args, false, !simulated); } export function applyPreApplyBattlerTagAbAttrs(attrType: Constructor, - pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreApplyBattlerTag(pokemon, passive, simulated, tag, cancelled, args), args, false, simulated); + pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreApplyBattlerTag(pokemon, passive, tag, cancelled, args), args); } export function applyPreWeatherEffectAbAttrs(attrType: Constructor, - pokemon: Pokemon, weather: Weather | null, cancelled: Utils.BooleanHolder, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreWeatherEffect(pokemon, passive, simulated, weather, cancelled, args), args, true, simulated); + pokemon: Pokemon, weather: Weather | null, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreWeatherEffect(pokemon, passive, weather, cancelled, args), args, true); } export function applyPostTurnAbAttrs(attrType: Constructor, - pokemon: Pokemon, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostTurn(pokemon, passive, simulated, args), args, false, simulated); + pokemon: Pokemon, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostTurn(pokemon, passive, args), args); } export function applyPostWeatherChangeAbAttrs(attrType: Constructor, - pokemon: Pokemon, weather: WeatherType, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostWeatherChange(pokemon, passive, simulated, weather, args), args, false, simulated); + pokemon: Pokemon, weather: WeatherType, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostWeatherChange(pokemon, passive, weather, args), args); } export function applyPostWeatherLapseAbAttrs(attrType: Constructor, - pokemon: Pokemon, weather: Weather | null, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostWeatherLapse(pokemon, passive, simulated, weather, args), args, false, simulated); + pokemon: Pokemon, weather: Weather | null, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostWeatherLapse(pokemon, passive, weather, args), args); } export function applyPostTerrainChangeAbAttrs(attrType: Constructor, - pokemon: Pokemon, terrain: TerrainType, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostTerrainChange(pokemon, passive, simulated, terrain, args), args, false, simulated); + pokemon: Pokemon, terrain: TerrainType, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostTerrainChange(pokemon, passive, terrain, args), args); } export function applyCheckTrappedAbAttrs(attrType: Constructor, - pokemon: Pokemon, trapped: Utils.BooleanHolder, otherPokemon: Pokemon, messages: string[], simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyCheckTrapped(pokemon, passive, simulated, trapped, otherPokemon, args), args, false, simulated, messages); + pokemon: Pokemon, trapped: Utils.BooleanHolder, otherPokemon: Pokemon, isQuiet: boolean, messages: string[], ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyCheckTrapped(pokemon, passive, trapped, otherPokemon, args), args, false, isQuiet, messages); } export function applyPostBattleAbAttrs(attrType: Constructor, - pokemon: Pokemon, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostBattle(pokemon, passive, simulated, args), args, false, simulated); + pokemon: Pokemon, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostBattle(pokemon, passive, args), args); } export function applyPostFaintAbAttrs(attrType: Constructor, - pokemon: Pokemon, attacker: Pokemon, move: Move, hitResult: HitResult, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostFaint(pokemon, passive, simulated, attacker, move, hitResult, args), args, false, simulated); + pokemon: Pokemon, attacker: Pokemon, move: Move, hitResult: HitResult, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostFaint(pokemon, passive, attacker, move, hitResult, args), args); } function queueShowAbility(pokemon: Pokemon, passive: boolean): void { @@ -5211,7 +5040,7 @@ export function initAbilities() { .conditionalAttr(pokemon => pokemon.formIndex === 0, PostSummonAddBattlerTagAbAttr, BattlerTagType.DISGUISE, 0, false) .attr(FormBlockDamageAbAttr, (target, user, move) => !!target.getTag(BattlerTagType.DISGUISE) && target.getAttackTypeEffectiveness(move.type, user) > 0, 0, BattlerTagType.DISGUISE, (pokemon, abilityName) => i18next.t("abilityTriggers:disguiseAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName }), - (pokemon) => Utils.toDmgValue(pokemon.getMaxHp() / 8)) + (pokemon) => Math.floor(pokemon.getMaxHp() / 8)) .attr(PostBattleInitFormChangeAbAttr, () => 0) .bypassFaint() .ignorable(), diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index a60ea5c2981..3394df827fb 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -269,7 +269,7 @@ const QuickGuardConditionFunc: ProtectConditionFunc = (arena, moveId) => { if (effectPhase instanceof MoveEffectPhase) { const attacker = effectPhase.getUserPokemon()!; applyMoveAttrs(IncrementMovePriorityAttr, attacker, null, move, priority); - applyAbAttrs(ChangeMovePriorityAbAttr, attacker, null, false, move, priority); + applyAbAttrs(ChangeMovePriorityAbAttr, attacker, null, move, priority); } return priority.value > 0; }; @@ -427,7 +427,7 @@ class WishTag extends ArenaTag { if (user) { this.battlerIndex = user.getBattlerIndex(); this.triggerMessage = i18next.t("arenaTag:wishTagOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(user) }); - this.healHp = Utils.toDmgValue(user.getMaxHp() / 2); + this.healHp = Math.max(Math.floor(user.getMaxHp() / 2), 1); } else { console.warn("Failed to get source for WishTag onAdd"); } @@ -585,7 +585,7 @@ class SpikesTag extends ArenaTrapTag { if (!cancelled.value) { const damageHpRatio = 1 / (10 - 2 * this.layers); - const damage = Utils.toDmgValue(pokemon.getMaxHp() * damageHpRatio); + const damage = Math.ceil(pokemon.getMaxHp() * damageHpRatio); pokemon.scene.queueMessage(i18next.t("arenaTag:spikesActivateTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); pokemon.damageAndUpdate(damage, HitResult.OTHER); @@ -745,7 +745,7 @@ class StealthRockTag extends ArenaTrapTag { const damageHpRatio = this.getDamageHpRatio(pokemon); if (damageHpRatio) { - const damage = Utils.toDmgValue(pokemon.getMaxHp() * damageHpRatio); + const damage = Math.ceil(pokemon.getMaxHp() * damageHpRatio); pokemon.scene.queueMessage(i18next.t("arenaTag:stealthRockActivateTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); pokemon.damageAndUpdate(damage, HitResult.OTHER); if (pokemon.turnData) { diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 8c05d296e76..ede8d029327 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -347,7 +347,7 @@ export class ConfusedTag extends BattlerTag { if (pokemon.randSeedInt(3) === 0) { const atk = pokemon.getBattleStat(Stat.ATK); const def = pokemon.getBattleStat(Stat.DEF); - const damage = Utils.toDmgValue(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * (pokemon.randSeedInt(15, 85) / 100)); + const damage = Math.ceil(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * (pokemon.randSeedInt(15, 85) / 100)); pokemon.scene.queueMessage(i18next.t("battlerTags:confusedLapseHurtItself")); pokemon.damageAndUpdate(damage); pokemon.battleData.hitCount++; @@ -524,7 +524,7 @@ export class SeedTag extends BattlerTag { if (!cancelled.value) { pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, source.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.LEECH_SEED)); - const damage = pokemon.damageAndUpdate(Utils.toDmgValue(pokemon.getMaxHp() / 8)); + const damage = pokemon.damageAndUpdate(Math.max(Math.floor(pokemon.getMaxHp() / 8), 1)); const reverseDrain = pokemon.hasAbilityWithAttr(ReverseDrainAbAttr, false); pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, source.getBattlerIndex(), !reverseDrain ? damage : damage * -1, @@ -570,7 +570,7 @@ export class NightmareTag extends BattlerTag { applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled); if (!cancelled.value) { - pokemon.damageAndUpdate(Utils.toDmgValue(pokemon.getMaxHp() / 4)); + pokemon.damageAndUpdate(Math.ceil(pokemon.getMaxHp() / 4)); } } @@ -714,7 +714,7 @@ export class IngrainTag extends TrappedTag { new PokemonHealPhase( pokemon.scene, pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / 16), + Math.floor(pokemon.getMaxHp() / 16), i18next.t("battlerTags:ingrainLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }), true ) @@ -777,7 +777,7 @@ export class AquaRingTag extends BattlerTag { new PokemonHealPhase( pokemon.scene, pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / 16), + Math.floor(pokemon.getMaxHp() / 16), i18next.t("battlerTags:aquaRingLapse", { moveName: this.getMoveName(), pokemonName: getPokemonNameWithAffix(pokemon) @@ -883,7 +883,7 @@ export abstract class DamagingTrapTag extends TrappedTag { applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled); if (!cancelled.value) { - pokemon.damageAndUpdate(Utils.toDmgValue(pokemon.getMaxHp() / 8)); + pokemon.damageAndUpdate(Math.ceil(pokemon.getMaxHp() / 8)); } } @@ -1067,7 +1067,7 @@ export class ContactDamageProtectedTag extends ProtectedTag { if (effectPhase instanceof MoveEffectPhase && effectPhase.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT)) { const attacker = effectPhase.getPokemon(); if (!attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { - attacker.damageAndUpdate(Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); + attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); } } } @@ -1541,7 +1541,7 @@ export class SaltCuredTag extends BattlerTag { if (!cancelled.value) { const pokemonSteelOrWater = pokemon.isOfType(Type.STEEL) || pokemon.isOfType(Type.WATER); - pokemon.damageAndUpdate(Utils.toDmgValue(pokemonSteelOrWater ? pokemon.getMaxHp() / 4 : pokemon.getMaxHp() / 8)); + pokemon.damageAndUpdate(Math.max(Math.floor(pokemonSteelOrWater ? pokemon.getMaxHp() / 4 : pokemon.getMaxHp() / 8), 1)); pokemon.scene.queueMessage( i18next.t("battlerTags:saltCuredLapse", { @@ -1587,7 +1587,7 @@ export class CursedTag extends BattlerTag { applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled); if (!cancelled.value) { - pokemon.damageAndUpdate(Utils.toDmgValue(pokemon.getMaxHp() / 4)); + pokemon.damageAndUpdate(Math.max(Math.floor(pokemon.getMaxHp() / 4), 1)); pokemon.scene.queueMessage(i18next.t("battlerTags:cursedLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); } } diff --git a/src/data/berry.ts b/src/data/berry.ts index d0c9c311e16..e962219ca46 100644 --- a/src/data/berry.ts +++ b/src/data/berry.ts @@ -36,25 +36,25 @@ export function getBerryPredicate(berryType: BerryType): BerryPredicate { return (pokemon: Pokemon) => { const threshold = new Utils.NumberHolder(0.25); const battleStat = (berryType - BerryType.LIECHI) as BattleStat; - applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); + applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, threshold); return pokemon.getHpRatio() < threshold.value && pokemon.summonData.battleStats[battleStat] < 6; }; case BerryType.LANSAT: return (pokemon: Pokemon) => { const threshold = new Utils.NumberHolder(0.25); - applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); + applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, threshold); return pokemon.getHpRatio() < 0.25 && !pokemon.getTag(BattlerTagType.CRIT_BOOST); }; case BerryType.STARF: return (pokemon: Pokemon) => { const threshold = new Utils.NumberHolder(0.25); - applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); + applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, threshold); return pokemon.getHpRatio() < 0.25; }; case BerryType.LEPPA: return (pokemon: Pokemon) => { const threshold = new Utils.NumberHolder(0.25); - applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); + applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, threshold); return !!pokemon.getMoveset().find(m => !m?.getPpRatio()); }; } @@ -70,8 +70,8 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc { if (pokemon.battleData) { pokemon.battleData.berriesEaten.push(berryType); } - const hpHealed = new Utils.NumberHolder(Utils.toDmgValue(pokemon.getMaxHp() / 4)); - applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, hpHealed); + const hpHealed = new Utils.NumberHolder(Math.floor(pokemon.getMaxHp() / 4)); + applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, hpHealed); pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(), hpHealed.value, i18next.t("battle:hpHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), berryName: getBerryName(berryType) }), true)); }; @@ -97,7 +97,7 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc { } const battleStat = (berryType - BerryType.LIECHI) as BattleStat; const statLevels = new Utils.NumberHolder(1); - applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statLevels); + applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, statLevels); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ battleStat ], statLevels.value)); }; case BerryType.LANSAT: @@ -113,7 +113,7 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc { pokemon.battleData.berriesEaten.push(berryType); } const statLevels = new Utils.NumberHolder(2); - applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statLevels); + applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, statLevels); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ BattleStat.RAND ], statLevels.value)); }; case BerryType.LEPPA: diff --git a/src/data/move.ts b/src/data/move.ts index b1b82009f3e..acb61042e70 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -590,7 +590,7 @@ export default class Move implements Localizable { case MoveFlags.IGNORE_ABILITIES: if (user.hasAbilityWithAttr(MoveAbilityBypassAbAttr)) { const abilityEffectsIgnored = new Utils.BooleanHolder(false); - applyAbAttrs(MoveAbilityBypassAbAttr, user, abilityEffectsIgnored, false, this); + applyAbAttrs(MoveAbilityBypassAbAttr, user, abilityEffectsIgnored, this); if (abilityEffectsIgnored.value) { return true; } @@ -686,11 +686,11 @@ export default class Move implements Localizable { * @param target {@linkcode Pokemon} The Pokémon being targeted by the move. * @returns The calculated accuracy of the move. */ - calculateBattleAccuracy(user: Pokemon, target: Pokemon, simulated: boolean = false) { + calculateBattleAccuracy(user: Pokemon, target: Pokemon) { const moveAccuracy = new Utils.NumberHolder(this.accuracy); applyMoveAttrs(VariableAccuracyAttr, user, target, this, moveAccuracy); - applyPreDefendAbAttrs(WonderSkinAbAttr, target, user, this, { value: false }, simulated, moveAccuracy); + applyPreDefendAbAttrs(WonderSkinAbAttr, target, user, this, { value: false }, moveAccuracy); if (moveAccuracy.value === -1) { return moveAccuracy.value; @@ -724,7 +724,7 @@ export default class Move implements Localizable { * @param target {@linkcode Pokemon} The Pokémon being targeted by the move. * @returns The calculated power of the move. */ - calculateBattlePower(source: Pokemon, target: Pokemon, simulated: boolean = false): number { + calculateBattlePower(source: Pokemon, target: Pokemon): number { if (this.category === MoveCategory.STATUS) { return -1; } @@ -732,17 +732,17 @@ export default class Move implements Localizable { const power = new Utils.NumberHolder(this.power); const typeChangeMovePowerMultiplier = new Utils.NumberHolder(1); - applyPreAttackAbAttrs(MoveTypeChangeAttr, source, target, this, simulated, typeChangeMovePowerMultiplier); + applyPreAttackAbAttrs(MoveTypeChangeAttr, source, target, this, typeChangeMovePowerMultiplier); const sourceTeraType = source.getTeraType(); if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === this.type && power.value < 60 && this.priority <= 0 && !this.hasAttr(MultiHitAttr) && !source.scene.findModifier(m => m instanceof PokemonMultiHitModifier && m.pokemonId === source.id)) { power.value = 60; } - applyPreAttackAbAttrs(VariableMovePowerAbAttr, source, target, this, simulated, power); + applyPreAttackAbAttrs(VariableMovePowerAbAttr, source, target, this, power); if (source.getAlly()) { - applyPreAttackAbAttrs(AllyMoveCategoryPowerBoostAbAttr, source.getAlly(), target, this, simulated, power); + applyPreAttackAbAttrs(AllyMoveCategoryPowerBoostAbAttr, source.getAlly(), target, this, power); } const fieldAuras = new Set( @@ -752,11 +752,11 @@ export default class Move implements Localizable { ); for (const aura of fieldAuras) { // The only relevant values are `move` and the `power` holder - aura.applyPreAttack(null, null, simulated, null, this, [power]); + aura.applyPreAttack(null, null, null, this, [power]); } const alliedField: Pokemon[] = source instanceof PlayerPokemon ? source.scene.getPlayerField() : source.scene.getEnemyField(); - alliedField.forEach(p => applyPreAttackAbAttrs(UserFieldMoveTypePowerBoostAbAttr, p, target, this, simulated, power)); + alliedField.forEach(p => applyPreAttackAbAttrs(UserFieldMoveTypePowerBoostAbAttr, p, target, this, power)); power.value *= typeChangeMovePowerMultiplier.value; @@ -984,9 +984,9 @@ export class MoveEffectAttr extends MoveAttr { */ getMoveChance(user: Pokemon, target: Pokemon, move: Move, selfEffect?: Boolean, showAbility?: Boolean): integer { const moveChance = new Utils.NumberHolder(move.chance); - applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, false, moveChance, move, target, selfEffect, showAbility); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, moveChance, move, target, selfEffect, showAbility); if (!selfEffect) { - applyPreDefendAbAttrs(IgnoreMoveEffectsAbAttr, target, user, null, null, false, moveChance); + applyPreDefendAbAttrs(IgnoreMoveEffectsAbAttr, target, user, null, null, moveChance); } return moveChance.value; } @@ -1162,7 +1162,7 @@ export class TargetHalfHpDamageAttr extends FixedDamageAttr { } apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - (args[0] as Utils.IntegerHolder).value = Utils.toDmgValue(target.hp / 2); + (args[0] as Utils.IntegerHolder).value = Math.max(Math.floor(target.hp / 2), 1); return true; } @@ -1208,7 +1208,7 @@ export class CounterDamageAttr extends FixedDamageAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const damage = user.turnData.attacksReceived.filter(ar => this.moveFilter(allMoves[ar.move])).reduce((total: integer, ar: AttackMoveResult) => total + ar.damage, 0); - (args[0] as Utils.IntegerHolder).value = Utils.toDmgValue(damage * this.multiplier); + (args[0] as Utils.IntegerHolder).value = Math.floor(Math.max(damage * this.multiplier, 1)); return true; } @@ -1234,7 +1234,7 @@ export class RandomLevelDamageAttr extends FixedDamageAttr { } getDamage(user: Pokemon, target: Pokemon, move: Move): number { - return Utils.toDmgValue(user.level * (user.randSeedIntRange(50, 150) * 0.01)); + return Math.max(Math.floor(user.level * (user.randSeedIntRange(50, 150) * 0.01)), 1); } } @@ -1293,9 +1293,8 @@ export class RecoilAttr extends MoveEffectAttr { return false; } - const damageValue = (!this.useHp ? user.turnData.damageDealt : user.getMaxHp()) * this.damageRatio; - const minValue = user.turnData.damageDealt ? 1 : 0; - const recoilDamage = Utils.toDmgValue(damageValue, minValue); + const recoilDamage = Math.max(Math.floor((!this.useHp ? user.turnData.damageDealt : user.getMaxHp()) * this.damageRatio), + user.turnData.damageDealt ? 1 : 0); if (!recoilDamage) { return false; } @@ -1416,7 +1415,7 @@ export class HalfSacrificialAttr extends MoveEffectAttr { // Check to see if the Pokemon has an ability that blocks non-direct damage applyAbAttrs(BlockNonDirectDamageAbAttr, user, cancelled); if (!cancelled.value) { - user.damageAndUpdate(Utils.toDmgValue(user.getMaxHp()/2), HitResult.OTHER, false, true, true); + user.damageAndUpdate(Math.ceil(user.getMaxHp()/2), HitResult.OTHER, false, true, true); user.scene.queueMessage(i18next.t("moveTriggers:cutHpPowerUpMove", {pokemonName: getPokemonNameWithAffix(user)})); // Queue recoil message } return true; @@ -1467,7 +1466,7 @@ export class HealAttr extends MoveEffectAttr { */ addHealPhase(target: Pokemon, healRatio: number) { target.scene.unshiftPhase(new PokemonHealPhase(target.scene, target.getBattlerIndex(), - Utils.toDmgValue(target.getMaxHp() * healRatio), i18next.t("moveTriggers:healHp", {pokemonName: getPokemonNameWithAffix(target)}), true, !this.showAnim)); + Math.max(Math.floor(target.getMaxHp() * healRatio), 1), i18next.t("moveTriggers:healHp", {pokemonName: getPokemonNameWithAffix(target)}), true, !this.showAnim)); } getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { @@ -1751,7 +1750,7 @@ export class HitHealAttr extends MoveEffectAttr { message = i18next.t("battle:drainMessage", {pokemonName: getPokemonNameWithAffix(target)}); } else { // Default healing formula used by draining moves like Absorb, Draining Kiss, Bitter Blade, etc. - healAmount = Utils.toDmgValue(user.turnData.currDamageDealt * this.healRatio); + healAmount = Math.max(Math.floor(user.turnData.currDamageDealt * this.healRatio), 1); message = i18next.t("battle:regainHealth", {pokemonName: getPokemonNameWithAffix(user)}); } if (reverseDrain) { @@ -1884,7 +1883,7 @@ export class MultiHitAttr extends MoveAttr { { const rand = user.randSeedInt(16); const hitValue = new Utils.IntegerHolder(rand); - applyAbAttrs(MaxMultiHitAbAttr, user, null, false, hitValue); + applyAbAttrs(MaxMultiHitAbAttr, user, null, hitValue); if (hitValue.value >= 10) { return 2; } else if (hitValue.value >= 4) { @@ -1955,7 +1954,7 @@ export class StatusEffectAttr extends MoveEffectAttr { } if ((!pokemon.status || (pokemon.status.effect === this.effect && moveChance < 0)) && pokemon.trySetStatus(this.effect, true, user, this.cureTurn)) { - applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, move, null, false, this.effect); + applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, move, null, this.effect); return true; } } @@ -2711,7 +2710,7 @@ export class CutHpStatBoostAttr extends StatChangeAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise { return new Promise(resolve => { - user.damageAndUpdate(Utils.toDmgValue(user.getMaxHp() / this.cutRatio), HitResult.OTHER, false, true); + user.damageAndUpdate(Math.floor(user.getMaxHp() / this.cutRatio), HitResult.OTHER, false, true); user.updateInfo().then(() => { const ret = super.apply(user, target, move, args); if (this.messageCallback) { @@ -3191,7 +3190,7 @@ export class CompareWeightPowerAttr extends VariablePowerAttr { export class HpPowerAttr extends VariablePowerAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - (args[0] as Utils.NumberHolder).value = Utils.toDmgValue(150 * user.getHpRatio()); + (args[0] as Utils.NumberHolder).value = Math.max(Math.floor(150 * user.getHpRatio()), 1); return true; } @@ -3219,7 +3218,7 @@ export class OpponentHighHpPowerAttr extends VariablePowerAttr { * @returns true */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - (args[0] as Utils.NumberHolder).value = Utils.toDmgValue(this.maxBasePower * target.getHpRatio()); + (args[0] as Utils.NumberHolder).value = Math.max(Math.floor(this.maxBasePower * target.getHpRatio()), 1); return true; } @@ -3413,7 +3412,7 @@ export class PresentPowerAttr extends VariablePowerAttr { // If this move is multi-hit, disable all other hits user.stopMultiHit(); target.scene.unshiftPhase(new PokemonHealPhase(target.scene, target.getBattlerIndex(), - Utils.toDmgValue(target.getMaxHp() / 4), i18next.t("moveTriggers:regainedHealth", {pokemonName: getPokemonNameWithAffix(target)}), true)); + Math.max(Math.floor(target.getMaxHp() / 4), 1), i18next.t("moveTriggers:regainedHealth", {pokemonName: getPokemonNameWithAffix(target)}), true)); } return true; @@ -3785,30 +3784,6 @@ export class TeraBlastCategoryAttr extends VariableMoveCategoryAttr { } } -/** - * Increases the power of Tera Blast if the user is Terastallized into Stellar type - * @extends VariablePowerAttr - */ -export class TeraBlastPowerAttr extends VariablePowerAttr { - apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - /** - * @param user {@linkcode Pokemon} Pokemon using the move - * @param target {@linkcode Pokemon} N/A - * @param move {@linkcode Move} {@linkcode Move.TERA_BLAST} - * @param {any[]} args N/A - * @returns true or false - */ - const power = args[0] as Utils.NumberHolder; - if (user.isTerastallized() && move.type === Type.STELLAR) { - //200 instead of 100 to reflect lack of stellar being 2x dmg on any type - power.value = 200; - return true; - } - - return false; - } -} - /** * Change the move category to status when used on the ally * @extends VariableMoveCategoryAttr @@ -4062,28 +4037,6 @@ export class HiddenPowerTypeAttr extends VariableMoveTypeAttr { } } -/** - * Changes the type of Tera Blast to match the user's tera type - * @extends VariableMoveTypeAttr - */ -export class TeraBlastTypeAttr extends VariableMoveTypeAttr { - apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - /** - * @param user {@linkcode Pokemon} the user's type is checked - * @param target {@linkcode Pokemon} N/A - * @param move {@linkcode Move} {@linkcode Move.TeraBlastTypeAttr} - * @param {any[]} args N/A - * @returns true or false - */ - if (user.isTerastallized()) { - move.type = user.getTeraType(); //changes move type to tera type - return true; - } - - return false; - } -} - export class MatchUserTypeAttr extends VariableMoveTypeAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const userTypes = user.getTypes(true); @@ -4233,9 +4186,9 @@ const crashDamageFunc = (user: Pokemon, move: Move) => { return false; } - user.damageAndUpdate(Utils.toDmgValue(user.getMaxHp() / 2), HitResult.OTHER, false, true); + user.damageAndUpdate(Math.floor(user.getMaxHp() / 2), HitResult.OTHER, false, true); user.scene.queueMessage(i18next.t("moveTriggers:keptGoingAndCrashed", {pokemonName: getPokemonNameWithAffix(user)})); - user.turnData.damageTaken += Utils.toDmgValue(user.getMaxHp() / 2); + user.turnData.damageTaken += Math.floor(user.getMaxHp() / 2); return true; }; @@ -4485,39 +4438,6 @@ export class GulpMissileTagAttr extends MoveEffectAttr { } } -/** - * Attribute to implement Jaw Lock's linked trapping effect between the user and target - * @extends AddBattlerTagAttr - */ -export class JawLockAttr extends AddBattlerTagAttr { - constructor() { - super(BattlerTagType.TRAPPED); - } - - apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - if (!super.canApply(user, target, move, args)) { - return false; - } - - // If either the user or the target already has the tag, do not apply - if (user.getTag(TrappedTag) || target.getTag(TrappedTag)) { - return false; - } - - const moveChance = this.getMoveChance(user, target, move, this.selfTarget); - if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { - /** - * Add the tag to both the user and the target. - * The target's tag source is considered to be the user and vice versa - */ - return target.addTag(BattlerTagType.TRAPPED, 1, move.id, user.id) - && user.addTag(BattlerTagType.TRAPPED, 1, move.id, target.id); - } - - return false; - } -} - export class CurseAttr extends MoveEffectAttr { apply(user: Pokemon, target: Pokemon, move:Move, args: any[]): boolean { @@ -4945,7 +4865,7 @@ export class RevivalBlessingAttr extends MoveEffectAttr { const pokemon = faintedPokemon[user.randSeedInt(faintedPokemon.length)]; const slotIndex = user.scene.getEnemyParty().findIndex(p => pokemon.id === p.id); pokemon.resetStatus(); - pokemon.heal(Math.min(Utils.toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp())); + pokemon.heal(Math.min(Math.max(Math.ceil(Math.floor(0.5 * pokemon.getMaxHp())), 1), pokemon.getMaxHp())); user.scene.queueMessage(`${getPokemonNameWithAffix(pokemon)} was revived!`,0,true); if (user.scene.currentBattle.double && user.scene.getEnemyParty().length > 1) { @@ -8393,7 +8313,8 @@ export function initMoves() { .attr(HighCritAttr) .attr(BypassRedirectAttr), new AttackMove(Moves.JAW_LOCK, Type.DARK, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 8) - .attr(JawLockAttr) + .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, false, 1, 1, false, true) + .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, true, false, 1, 1, false, true) .bitingMove(), new SelfStatusMove(Moves.STUFF_CHEEKS, Type.NORMAL, -1, 10, -1, 0, 8) // TODO: Stuff Cheeks should not be selectable when the user does not have a berry, see wiki .attr(EatBerryAttr) @@ -8838,10 +8759,7 @@ export function initMoves() { End Unused */ new AttackMove(Moves.TERA_BLAST, Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 9) .attr(TeraBlastCategoryAttr) - .attr(TeraBlastTypeAttr) - .attr(TeraBlastPowerAttr) - .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], -1, true, (user, target, move) => user.isTerastallized() && user.isOfType(Type.STELLAR)) - .partial(), + .unimplemented(), new SelfStatusMove(Moves.SILK_TRAP, Type.BUG, -1, 10, -1, 4, 9) .attr(ProtectAttr, BattlerTagType.SILK_TRAP), new AttackMove(Moves.AXE_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 120, 90, 10, 30, 0, 9) diff --git a/src/data/terrain.ts b/src/data/terrain.ts index d4789078af7..e29344ffea2 100644 --- a/src/data/terrain.ts +++ b/src/data/terrain.ts @@ -59,7 +59,7 @@ export class Terrain { case TerrainType.PSYCHIC: if (!move.hasAttr(ProtectAttr)) { const priority = new Utils.IntegerHolder(move.priority); - applyAbAttrs(ChangeMovePriorityAbAttr, user, null, false, move, priority); + applyAbAttrs(ChangeMovePriorityAbAttr, user, null, move, priority); // Cancels move if the move has positive priority and targets a Pokemon grounded on the Psychic Terrain return priority.value > 0 && user.getOpponents().some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded()); } diff --git a/src/field/arena.ts b/src/field/arena.ts index 2ef6ce7dab3..eb3770d61d5 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -584,10 +584,6 @@ export class Arena { return this.getTagOnSide(tagType, ArenaTagSide.BOTH); } - hasTag(tagType: ArenaTagType) : boolean { - return !!this.getTag(tagType); - } - getTagOnSide(tagType: ArenaTagType | Constructor, side: ArenaTagSide): ArenaTag | undefined { return typeof(tagType) === "string" ? this.tags.find(t => t.tagType === tagType && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side)) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 030297a2126..6a445a83b4e 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -694,7 +694,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { break; } } - applyAbAttrs(IgnoreOpponentStatChangesAbAttr, opponent, null, false, statLevel); + applyAbAttrs(IgnoreOpponentStatChangesAbAttr, opponent, null, statLevel); if (move) { applyMoveAttrs(IgnoreOpponentStatChangesAttr, this, opponent, move, statLevel); } @@ -978,6 +978,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // this.scene potentially can be undefined for a fainted pokemon in doubles // use optional chaining to avoid runtime errors + if (forDefend && (this.getTag(GroundedTag) || this.scene?.arena.getTag(ArenaTagType.GRAVITY))) { + const flyingIndex = types.indexOf(Type.FLYING); + if (flyingIndex > -1) { + types.splice(flyingIndex, 1); + } + } if (!types.length) { // become UNKNOWN if no types are present types.push(Type.UNKNOWN); @@ -1122,10 +1128,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const suppressed = new Utils.BooleanHolder(false); this.scene.getField(true).filter(p => p !== this).map(p => { if (p.getAbility().hasAttr(SuppressFieldAbilitiesAbAttr) && p.canApplyAbility()) { - p.getAbility().getAttrs(SuppressFieldAbilitiesAbAttr).map(a => a.apply(this, false, false, suppressed, [ability])); + p.getAbility().getAttrs(SuppressFieldAbilitiesAbAttr).map(a => a.apply(this, false, suppressed, [ability])); } if (p.getPassiveAbility().hasAttr(SuppressFieldAbilitiesAbAttr) && p.canApplyAbility(true)) { - p.getPassiveAbility().getAttrs(SuppressFieldAbilitiesAbAttr).map(a => a.apply(this, true, false, suppressed, [ability])); + p.getPassiveAbility().getAttrs(SuppressFieldAbilitiesAbAttr).map(a => a.apply(this, true, suppressed, [ability])); } }); if (suppressed.value) { @@ -1177,7 +1183,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { getWeight(): number { const weight = new Utils.NumberHolder(this.species.weight); // This will trigger the ability overlay so only call this function when necessary - applyAbAttrs(WeightMultiplierAbAttr, this, null, false, weight); + applyAbAttrs(WeightMultiplierAbAttr, this, null, weight); return weight.value; } @@ -1237,10 +1243,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const cancelled = new Utils.BooleanHolder(false); applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier); if (!typeless && !ignoreAbility) { - applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, true, typeMultiplier); + applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, typeMultiplier, true); } if (!cancelled.value && !ignoreAbility) { - applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, true, typeMultiplier); + applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, typeMultiplier, true); } return (!cancelled.value ? Number(typeMultiplier.value) : 0) as TypeDamageMultiplier; @@ -1266,22 +1272,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.isTerastallized() ? 2 : 1; } const types = this.getTypes(true, true); - const arena = this.scene.arena; - - // Handle flying v ground type immunity without removing flying type so effective types are still effective - // Related to https://github.com/pagefaultgames/pokerogue/issues/524 - if (moveType === Type.GROUND && (this.isGrounded() || arena.hasTag(ArenaTagType.GRAVITY))) { - const flyingIndex = types.indexOf(Type.FLYING); - if (flyingIndex > -1) { - types.splice(flyingIndex, 1); - } - } let multiplier = types.map(defType => { if (source) { const ignoreImmunity = new Utils.BooleanHolder(false); if (source.isActive(true) && source.hasAbilityWithAttr(IgnoreTypeImmunityAbAttr)) { - applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, false, moveType, defType); + applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, moveType, defType); } if (ignoreImmunity.value) { return 1; @@ -1297,7 +1293,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { }).reduce((acc, cur) => acc * cur, 1) as TypeDamageMultiplier; // Handle strong winds lowering effectiveness of types super effective against pure flying - if (!ignoreStrongWinds && arena.weather?.weatherType === WeatherType.STRONG_WINDS && !arena.weather.isEffectSuppressed(this.scene) && this.isOfType(Type.FLYING) && getTypeDamageMultiplier(moveType, Type.FLYING) === 2) { + if (!ignoreStrongWinds && this.scene.arena.weather?.weatherType === WeatherType.STRONG_WINDS && !this.scene.arena.weather.isEffectSuppressed(this.scene) && this.isOfType(Type.FLYING) && getTypeDamageMultiplier(moveType, Type.FLYING) === 2) { multiplier /= 2; if (!simulated) { this.scene.queueMessage(i18next.t("weather:strongWindsEffectMessage")); @@ -1922,9 +1918,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const userAccuracyLevel = new Utils.IntegerHolder(this.summonData.battleStats[BattleStat.ACC]); const targetEvasionLevel = new Utils.IntegerHolder(target.summonData.battleStats[BattleStat.EVA]); - applyAbAttrs(IgnoreOpponentStatChangesAbAttr, target, null, false, userAccuracyLevel); - applyAbAttrs(IgnoreOpponentStatChangesAbAttr, this, null, false, targetEvasionLevel); - applyAbAttrs(IgnoreOpponentEvasionAbAttr, this, null, false, targetEvasionLevel); + applyAbAttrs(IgnoreOpponentStatChangesAbAttr, target, null, userAccuracyLevel); + applyAbAttrs(IgnoreOpponentStatChangesAbAttr, this, null, targetEvasionLevel); + applyAbAttrs(IgnoreOpponentEvasionAbAttr, this, null, targetEvasionLevel); applyMoveAttrs(IgnoreOpponentStatChangesAttr, this, target, sourceMove, targetEvasionLevel); this.scene.applyModifiers(TempBattleStatBoosterModifier, this.isPlayer(), TempBattleStat.ACC, userAccuracyLevel); @@ -1939,7 +1935,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { : 3 / (3 + Math.min(targetEvasionLevel.value - userAccuracyLevel.value, 6)); } - applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, this, BattleStat.ACC, accuracyMultiplier, false, sourceMove); + applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, this, BattleStat.ACC, accuracyMultiplier, sourceMove); const evasionMultiplier = new Utils.NumberHolder(1); applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, target, BattleStat.EVA, evasionMultiplier); @@ -1949,12 +1945,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return accuracyMultiplier.value; } - /** - * Apply the results of a move to this pokemon - * @param {Pokemon} source The pokemon using the move - * @param {PokemonMove} battlerMove The move being used - * @returns {HitResult} The result of the attack - */ apply(source: Pokemon, move: Move): HitResult { let result: HitResult; const damage = new Utils.NumberHolder(0); @@ -1990,12 +1980,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const sourceTeraType = source.getTeraType(); if (!typeless) { - applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, false, typeMultiplier); + applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, typeMultiplier); applyMoveAttrs(NeutralDamageAgainstFlyingTypeMultiplierAttr, source, this, move, typeMultiplier); } if (!cancelled.value) { - applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, false, typeMultiplier); - defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, move, cancelled, false, typeMultiplier)); + applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, typeMultiplier); + defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, move, cancelled, typeMultiplier)); } if (cancelled.value) { @@ -2018,7 +2008,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const critOnly = new Utils.BooleanHolder(false); const critAlways = source.getTag(BattlerTagType.ALWAYS_CRIT); applyMoveAttrs(CritOnlyAttr, source, this, move, critOnly); - applyAbAttrs(ConditionalCritAbAttr, source, null, false, critOnly, this, move); + applyAbAttrs(ConditionalCritAbAttr, source, null, critOnly, this, move); if (critOnly.value || critAlways) { isCritical = true; } else { @@ -2028,7 +2018,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { 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 (applyAbAttrs(BonusCritAbAttr, source, null, bonusCrit)) { // TODO: resolve ts-ignore. This is a promise. Checking a promise is bogus. if (bonusCrit.value) { critLevel.value += 1; } @@ -2046,7 +2036,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (isCritical) { const noCritTag = this.scene.arena.getTagOnSide(NoCritTag, defendingSide); const blockCrit = new Utils.BooleanHolder(false); - applyAbAttrs(BlockCritAbAttr, this, null, false, blockCrit); + applyAbAttrs(BlockCritAbAttr, this, null, blockCrit); if (noCritTag || blockCrit.value) { isCritical = false; } @@ -2054,7 +2044,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { 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 criticalMultiplier = new Utils.NumberHolder(isCritical ? 1.5 : 1); - applyAbAttrs(MultCritAbAttr, source, null, false, criticalMultiplier); + applyAbAttrs(MultCritAbAttr, source, null, criticalMultiplier); const screenMultiplier = new Utils.NumberHolder(1); if (!isCritical) { this.scene.arena.applyTagsForSide(WeakenMoveScreenTag, defendingSide, move.category, this.scene.currentBattle.double, screenMultiplier); @@ -2069,7 +2059,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { stabMultiplier.value += 0.5; } - applyAbAttrs(StabBoostAbAttr, source, null, false, stabMultiplier); + applyAbAttrs(StabBoostAbAttr, source, null, stabMultiplier); if (sourceTeraType !== Type.UNKNOWN && matchesSourceType) { stabMultiplier.value = Math.min(stabMultiplier.value + 0.5, 2.25); @@ -2087,12 +2077,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { numTargets = effectPhase.getTargets().length; } const twoStrikeMultiplier = new Utils.NumberHolder(1); - applyPreAttackAbAttrs(AddSecondStrikeAbAttr, source, this, move, false, numTargets, new Utils.IntegerHolder(0), twoStrikeMultiplier); + applyPreAttackAbAttrs(AddSecondStrikeAbAttr, source, this, move, numTargets, new Utils.IntegerHolder(0), twoStrikeMultiplier); if (!isTypeImmune) { const levelMultiplier = (2 * source.level / 5 + 2); const randomMultiplier = ((this.scene.randBattleSeedInt(16) + 85) / 100); - damage.value = Utils.toDmgValue((((levelMultiplier * power * sourceAtk.value / targetDef.value) / 50) + 2) + damage.value = Math.ceil((((levelMultiplier * power * sourceAtk.value / targetDef.value) / 50) + 2) * stabMultiplier.value * typeMultiplier.value * arenaAttackTypeMultiplier.value @@ -2106,14 +2096,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (isPhysical && source.status && source.status.effect === StatusEffect.BURN) { if (!move.hasAttr(BypassBurnDamageReductionAttr)) { const burnDamageReductionCancelled = new Utils.BooleanHolder(false); - applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled, false); + applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled); if (!burnDamageReductionCancelled.value) { - damage.value = Utils.toDmgValue(damage.value / 2); + damage.value = Math.floor(damage.value / 2); } } } - applyPreAttackAbAttrs(DamageBoostAbAttr, source, this, move, false, damage); + applyPreAttackAbAttrs(DamageBoostAbAttr, source, this, move, damage); /** * For each {@link HitsTagAttr} the move has, doubles the damage of the move if: @@ -2129,7 +2119,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } if (this.scene.arena.terrain?.terrainType === TerrainType.MISTY && this.isGrounded() && move.type === Type.DRAGON) { - damage.value = Utils.toDmgValue(damage.value / 2); + damage.value = Math.floor(damage.value / 2); } const fixedDamage = new Utils.IntegerHolder(0); @@ -2171,7 +2161,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.scene.applyModifiers(EnemyDamageReducerModifier, false, damage); } - applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, this, source, move, cancelled, false, damage); + applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, this, source, move, cancelled, damage); } // This attribute may modify damage arbitrarily, so be careful about changing its order of application. @@ -2184,7 +2174,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (damage.value) { if (this.isFullHp()) { - applyPreDefendAbAttrs(PreDefendFullHpEndureAbAttr, this, source, move, cancelled, false, damage); + applyPreDefendAbAttrs(PreDefendFullHpEndureAbAttr, this, source, move, cancelled, damage); } else if (!this.isPlayer() && damage.value >= this.hp) { this.scene.applyModifiers(EnemyEndureChanceModifier, false, this); } @@ -2251,11 +2241,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { break; case MoveCategory.STATUS: if (!typeless) { - applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, false, typeMultiplier); + applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, typeMultiplier); } if (!cancelled.value) { - applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, false, typeMultiplier); - defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, move, cancelled, false, typeMultiplier)); + applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, typeMultiplier); + defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, move, cancelled, typeMultiplier)); } if (!typeMultiplier.value) { this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: getPokemonNameWithAffix(this) })); @@ -2347,22 +2337,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return maxForms.includes(this.getFormKey()) || (!!this.getFusionFormKey() && maxForms.includes(this.getFusionFormKey()!)); } - canAddTag(tagType: BattlerTagType): boolean { - if (this.getTag(tagType)) { - return false; - } - - const stubTag = new BattlerTag(tagType, 0, 0); - - const cancelled = new Utils.BooleanHolder(false); - applyPreApplyBattlerTagAbAttrs(BattlerTagImmunityAbAttr, this, stubTag, cancelled, true); - - const userField = this.getAlliedField(); - userField.forEach(pokemon => applyPreApplyBattlerTagAbAttrs(UserFieldBattlerTagImmunityAbAttr, pokemon, stubTag, cancelled, true)); - - return !cancelled.value; - } - addTag(tagType: BattlerTagType, turnCount: integer = 0, sourceMove?: Moves, sourceId?: integer): boolean { const existingTag = this.getTag(tagType); if (existingTag) { @@ -2749,7 +2723,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // Check if the source Pokemon has an ability that cancels the Poison/Toxic immunity const cancelImmunity = new Utils.BooleanHolder(false); if (sourcePokemon) { - applyAbAttrs(IgnoreTypeStatusEffectImmunityAbAttr, sourcePokemon, cancelImmunity, false, effect, defType); + applyAbAttrs(IgnoreTypeStatusEffectImmunityAbAttr, sourcePokemon, cancelImmunity, effect, defType); if (cancelImmunity.value) { return false; } @@ -2821,7 +2795,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (effect === StatusEffect.SLEEP) { statusCureTurn = new Utils.IntegerHolder(this.randSeedIntRange(2, 4)); - applyAbAttrs(ReduceStatusEffectDurationAbAttr, this, null, false, effect, statusCureTurn); + applyAbAttrs(ReduceStatusEffectDurationAbAttr, this, null, effect, statusCureTurn); this.setFrameRate(4); @@ -3455,7 +3429,7 @@ export class PlayerPokemon extends Pokemon { pokemon.resetTurnData(); pokemon.resetStatus(); - pokemon.heal(Math.min(Utils.toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp())); + pokemon.heal(Math.min(Math.max(Math.ceil(Math.floor(0.5 * pokemon.getMaxHp())), 1), pokemon.getMaxHp())); this.scene.queueMessage(`${pokemon.name} was revived!`,0,true); if (this.scene.currentBattle.double && this.scene.getParty().length > 1) { @@ -4382,7 +4356,7 @@ export class PokemonMove { } getMovePp(): integer { - return this.getMove().pp + this.ppUp * Utils.toDmgValue(this.getMove().pp / 5); + return this.getMove().pp + this.ppUp * Math.max(Math.floor(this.getMove().pp / 5), 1); } getPpRatio(): number { diff --git a/src/locales/ca_ES/battle-scene.ts b/src/locales/ca_ES/battle-scene.ts deleted file mode 100644 index 573e1791724..00000000000 --- a/src/locales/ca_ES/battle-scene.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SimpleTranslationEntries } from "#app/interfaces/locales"; - -export const battleScene: SimpleTranslationEntries = { - "moneyOwned": "₽{{formattedMoney}}" -} as const; diff --git a/src/locales/ca_ES/config.ts b/src/locales/ca_ES/config.ts index 36aee87fc75..831ab5d99f5 100644 --- a/src/locales/ca_ES/config.ts +++ b/src/locales/ca_ES/config.ts @@ -6,7 +6,6 @@ import { arenaFlyout } from "./arena-flyout"; import { arenaTag } from "./arena-tag"; import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; -import { battleScene } from "./battle-scene"; import { battleInfo } from "./battle-info"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battlerTags } from "./battler-tags"; @@ -61,7 +60,6 @@ export const caESConfig = { arenaFlyout: arenaFlyout, arenaTag: arenaTag, battle: battle, - battleScene: battleScene, battleInfo: battleInfo, battleMessageUiHandler: battleMessageUiHandler, battlePokemonForm: battlePokemonForm, diff --git a/src/locales/de/battle-scene.ts b/src/locales/de/battle-scene.ts deleted file mode 100644 index bfa96445f6c..00000000000 --- a/src/locales/de/battle-scene.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { SimpleTranslationEntries } from "#app/interfaces/locales"; - -export const battleScene: SimpleTranslationEntries = { - "moneyOwned": "{{formattedMoney}} ₽" - -} as const; diff --git a/src/locales/de/battler-tags.ts b/src/locales/de/battler-tags.ts index da0150836b0..27d5f14c597 100644 --- a/src/locales/de/battler-tags.ts +++ b/src/locales/de/battler-tags.ts @@ -69,5 +69,5 @@ export const battlerTags: SimpleTranslationEntries = { "saltCuredLapse": "{{pokemonNameWithAffix}} wurde durch {{moveName}} verletzt!", "cursedOnAdd": "{{pokemonNameWithAffix}} nimmt einen Teil seiner KP und legt einen Fluch auf {{pokemonName}}!", "cursedLapse": "{{pokemonNameWithAffix}} wurde durch den Fluch verletzt!", - "stockpilingOnAdd": "{{pokemonNameWithAffix}} hortet {{stockpiledCount}}!", + "stockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!", } as const; diff --git a/src/locales/de/config.ts b/src/locales/de/config.ts index 080c9ecc598..d0779c9eec4 100644 --- a/src/locales/de/config.ts +++ b/src/locales/de/config.ts @@ -4,7 +4,6 @@ import { arenaFlyout } from "./arena-flyout"; import { arenaTag } from "./arena-tag"; import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; -import { battleScene } from "./battle-scene"; import { battleInfo } from "./battle-info"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battlerTags } from "./battler-tags"; @@ -61,7 +60,6 @@ export const deConfig = { arenaFlyout: arenaFlyout, arenaTag: arenaTag, battle: battle, - battleScene: battleScene, battleInfo: battleInfo, battleMessageUiHandler: battleMessageUiHandler, battlePokemonForm: battlePokemonForm, diff --git a/src/locales/de/starter-select-ui-handler.ts b/src/locales/de/starter-select-ui-handler.ts index c96af29a3c0..284152bbd33 100644 --- a/src/locales/de/starter-select-ui-handler.ts +++ b/src/locales/de/starter-select-ui-handler.ts @@ -7,7 +7,7 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; */ export const starterSelectUiHandler: SimpleTranslationEntries = { "confirmStartTeam": "Mit diesen Pokémon losziehen?", - "confirmExit": "Willst du zurück?", + "confirmExit": "Do you want to exit?", "invalidParty": "Das ist kein gültiges Team!", "gen1": "I", "gen2": "II", @@ -28,8 +28,8 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "toggleIVs": "DVs anzeigen/verbergen", "manageMoves": "Attacken ändern", "manageNature": "Wesen ändern", - "addToFavorites": "Zu Favoriten hinzufügen", - "removeFromFavorites": "Von Favoriten entfernen", + "addToFavorites": "Add to Favorites", + "removeFromFavorites": "Remove from Favorites", "useCandies": "Bonbons verwenden", "selectNature": "Wähle das neue Wesen.", "selectMoveSwapOut": "Wähle die zu ersetzende Attacke.", diff --git a/src/locales/en/battle-scene.ts b/src/locales/en/battle-scene.ts deleted file mode 100644 index 573e1791724..00000000000 --- a/src/locales/en/battle-scene.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SimpleTranslationEntries } from "#app/interfaces/locales"; - -export const battleScene: SimpleTranslationEntries = { - "moneyOwned": "₽{{formattedMoney}}" -} as const; diff --git a/src/locales/en/config.ts b/src/locales/en/config.ts index d456b0540cc..a98dd750fbe 100644 --- a/src/locales/en/config.ts +++ b/src/locales/en/config.ts @@ -6,7 +6,6 @@ import { arenaFlyout } from "./arena-flyout"; import { arenaTag } from "./arena-tag"; import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; -import { battleScene } from "./battle-scene"; import { battleInfo } from "./battle-info"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battlerTags } from "./battler-tags"; @@ -61,7 +60,6 @@ export const enConfig = { arenaFlyout: arenaFlyout, arenaTag: arenaTag, battle: battle, - battleScene: battleScene, battleInfo: battleInfo, battleMessageUiHandler: battleMessageUiHandler, battlePokemonForm: battlePokemonForm, diff --git a/src/locales/es/battle-scene.ts b/src/locales/es/battle-scene.ts deleted file mode 100644 index 995ca744302..00000000000 --- a/src/locales/es/battle-scene.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SimpleTranslationEntries } from "#app/interfaces/locales"; - -export const battleScene: SimpleTranslationEntries = { - "moneyOwned": "{{formattedMoney}} ₽" -} as const; diff --git a/src/locales/es/config.ts b/src/locales/es/config.ts index 6c038188da2..ce9ad19aac3 100644 --- a/src/locales/es/config.ts +++ b/src/locales/es/config.ts @@ -4,7 +4,6 @@ import { arenaFlyout } from "./arena-flyout"; import { arenaTag } from "./arena-tag"; import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; -import { battleScene } from "./battle-scene"; import { battleInfo } from "./battle-info"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battlerTags } from "./battler-tags"; @@ -61,7 +60,6 @@ export const esConfig = { arenaFlyout: arenaFlyout, arenaTag: arenaTag, battle: battle, - battleScene: battleScene, battleInfo: battleInfo, battleMessageUiHandler: battleMessageUiHandler, battlePokemonForm: battlePokemonForm, diff --git a/src/locales/fr/battle-scene.ts b/src/locales/fr/battle-scene.ts deleted file mode 100644 index 995ca744302..00000000000 --- a/src/locales/fr/battle-scene.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SimpleTranslationEntries } from "#app/interfaces/locales"; - -export const battleScene: SimpleTranslationEntries = { - "moneyOwned": "{{formattedMoney}} ₽" -} as const; diff --git a/src/locales/fr/config.ts b/src/locales/fr/config.ts index a2ab67eefe0..246ae9a073f 100644 --- a/src/locales/fr/config.ts +++ b/src/locales/fr/config.ts @@ -4,7 +4,6 @@ import { arenaFlyout } from "./arena-flyout"; import { arenaTag } from "./arena-tag"; import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; -import { battleScene } from "./battle-scene"; import { battleInfo } from "./battle-info"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battlerTags } from "./battler-tags"; @@ -61,7 +60,6 @@ export const frConfig = { arenaFlyout: arenaFlyout, arenaTag: arenaTag, battle: battle, - battleScene: battleScene, battleInfo: battleInfo, battleMessageUiHandler: battleMessageUiHandler, battlePokemonForm: battlePokemonForm, diff --git a/src/locales/it/ability-trigger.ts b/src/locales/it/ability-trigger.ts index c834fa28fbe..95db5cbf26c 100644 --- a/src/locales/it/ability-trigger.ts +++ b/src/locales/it/ability-trigger.ts @@ -25,39 +25,39 @@ export const abilityTriggers: SimpleTranslationEntries = { "postAttackStealHeldItem": "{{pokemonNameWithAffix}} ruba\n{{stolenItemType}} di {{defenderName}}!", "postDefendStealHeldItem": "{{pokemonNameWithAffix}} ruba\n{{stolenItemType}} di {{attackerName}}!", "copyFaintedAllyAbility": "L'abilità {{abilityName}} di {{pokemonNameWithAffix}} è passata all'alleato!", - "intimidateImmunity": "{{abilityName}} impedisce a {{pokemonNameWithAffix}} di\nessere intimidito!", - "postSummonAllyHeal": "{{pokemonNameWithAffix}} beve il\ntè che {{pokemonName}} gli ha preparato!", - "postSummonClearAllyStats": "Le statistiche di {{pokemonNameWithAffix}}\ntornano alla normalità!", - "postSummonTransform": "{{pokemonNameWithAffix}} assume le sembianze\ndi {{targetName}}!", - "protectStat": "{{abilityName}} di {{pokemonNameWithAffix}}\npreviene la riduzione del/della suo/a {{statName}}!", - "statusEffectImmunityWithName": "{{abilityName}} di {{pokemonNameWithAffix}}\nnon gli fa subire il/lo/la {{statusEffectName}}!", - "statusEffectImmunity": "{{abilityName}} di {{pokemonNameWithAffix}}\npreviene i problemi di stato!", - "battlerTagImmunity": "{{abilityName}} di {{pokemonNameWithAffix}}\npreviene {{battlerTagName}}!", - "forewarn": "{{pokemonNameWithAffix}} è stato messo in guardia da {{moveName}}!", - "frisk": "{{pokemonNameWithAffix}} perquisice {{opponentName}}\ne trova la sua abilità, {{opponentAbilityName}}!", - "postWeatherLapseHeal": "{{pokemonNameWithAffix}} recupera alcuni PS\ncon {{abilityName}}!", - "postWeatherLapseDamage": "{{pokemonNameWithAffix}} subisce danni\na causa della sua abilità, {{abilityName}}!", - "postTurnLootCreateEatenBerry": "{{pokemonNameWithAffix}} raccoglie una {{berryName}}!", - "postTurnHeal": "{{pokemonNameWithAffix}} recupera alcuni PS\ncon {{abilityName}}!", - "fetchBall": "{{pokemonNameWithAffix}} ha trovato una\n{{pokeballName}}!", - "healFromBerryUse": "{{abilityName}} di {{pokemonNameWithAffix}}\nristabilisce parte dei PS!", - "arenaTrap": "L’abilità {{abilityName}} di {{pokemonNameWithAffix}}\nimpedisce la sostituzione!", - "postBattleLoot": "{{pokemonNameWithAffix}} ha raccolto\nil/l'/lo/la {{itemName}}!", - "postFaintContactDamage": "{{abilityName}} di {{pokemonNameWithAffix}}\nferisce il Pokémon che lo ha attaccato!", - "postFaintHpDamage": "{{abilityName}} di {{pokemonNameWithAffix}}\nferisce il Pokémon che lo ha attaccato!", - "postSummonPressure": "{{pokemonNameWithAffix}} fa pressione!", - "postSummonMoldBreaker": "{{pokemonNameWithAffix}} ha l’abilità Rompiforma!", - "postSummonAnticipation": "{{pokemonNameWithAffix}} rabbrividisce!", - "postSummonTurboblaze": "{{pokemonNameWithAffix}} emana un’aura infuocata!", - "postSummonTeravolt": "{{pokemonNameWithAffix}} emana un’aura repulsiva!", - "postSummonDarkAura": "L’abilità Auratetra di {{pokemonNameWithAffix}} è attiva.", - "postSummonFairyAura": "L’abilità Aurafolletto di {{pokemonNameWithAffix}} è attiva.", - "postSummonNeutralizingGas": "Il Gas Reagente di {{pokemonNameWithAffix}}\nsi diffonde tutt’intorno!", - "postSummonAsOneGlastrier": "{{pokemonNameWithAffix}} ha due abilità!", - "postSummonAsOneSpectrier": "{{pokemonNameWithAffix}} ha due abilità!", - "postSummonVesselOfRuin": "La/l'{{statName}} dei Pokémon intorno si indebolisce a causa\ndell'abilità Vaso Nefasto di {{pokemonNameWithAffix}}!", - "postSummonSwordOfRuin": "La/l'{{statName}} dei Pokémon intorno si indebolisce a causa\ndell'abilità Spada Nefasta di {{pokemonNameWithAffix}}!", - "postSummonTabletsOfRuin": "La/l'{{statName}} dei Pokémon intorno si indebolisce a causa\ndell'abilità Amuleto Nefasto di {{pokemonNameWithAffix}}!", - "postSummonBeadsOfRuin": "La/l'{{statName}} dei Pokémon intorno si indebolisce a causa\ndell'abilità Monile Nefasto di {{pokemonNameWithAffix}}!", + "intimidateImmunity": "{{pokemonNameWithAffix}}'s {{abilityName}} prevented it from being Intimidated!", + "postSummonAllyHeal": "{{pokemonNameWithAffix}} drank down all the\nmatcha that {{pokemonName}} made!", + "postSummonClearAllyStats": "{{pokemonNameWithAffix}}'s stat changes\nwere removed!", + "postSummonTransform": "{{pokemonNameWithAffix}} transformed\ninto {{targetName}}!", + "protectStat": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents lowering its {{statName}}!", + "statusEffectImmunityWithName": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents {{statusEffectName}}!", + "statusEffectImmunity": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents status problems!", + "battlerTagImmunity": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents {{battlerTagName}}!", + "forewarn": "{{pokemonNameWithAffix}} was forewarned about {{moveName}}!", + "frisk": "{{pokemonNameWithAffix}} frisked {{opponentName}}'s {{opponentAbilityName}}!", + "postWeatherLapseHeal": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP a little!", + "postWeatherLapseDamage": "{{pokemonNameWithAffix}} is hurt\nby its {{abilityName}}!", + "postTurnLootCreateEatenBerry": "{{pokemonNameWithAffix}} harvested one {{berryName}}!", + "postTurnHeal": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP a little!", + "fetchBall": "{{pokemonNameWithAffix}} found a\n{{pokeballName}}!", + "healFromBerryUse": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP!", + "arenaTrap": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents switching!", + "postBattleLoot": "{{pokemonNameWithAffix}} picked up\n{{itemName}}!", + "postFaintContactDamage": "{{pokemonNameWithAffix}}'s {{abilityName}}\nhurt its attacker!", + "postFaintHpDamage": "{{pokemonNameWithAffix}}'s {{abilityName}}\nhurt its attacker!", + "postSummonPressure": "{{pokemonNameWithAffix}} is exerting its Pressure!", + "postSummonMoldBreaker": "{{pokemonNameWithAffix}} breaks the mold!", + "postSummonAnticipation": "{{pokemonNameWithAffix}} shuddered!", + "postSummonTurboblaze": "{{pokemonNameWithAffix}} is radiating a blazing aura!", + "postSummonTeravolt": "{{pokemonNameWithAffix}} is radiating a bursting aura!", + "postSummonDarkAura": "{{pokemonNameWithAffix}} is radiating a Dark Aura!", + "postSummonFairyAura": "{{pokemonNameWithAffix}} is radiating a Fairy Aura!", + "postSummonNeutralizingGas": "{{pokemonNameWithAffix}}'s Neutralizing Gas filled the area!", + "postSummonAsOneGlastrier": "{{pokemonNameWithAffix}} has two Abilities!", + "postSummonAsOneSpectrier": "{{pokemonNameWithAffix}} has two Abilities!", + "postSummonVesselOfRuin": "{{pokemonNameWithAffix}}'s Vessel of Ruin lowered the {{statName}}\nof all surrounding Pokémon!", + "postSummonSwordOfRuin": "{{pokemonNameWithAffix}}'s Sword of Ruin lowered the {{statName}}\nof all surrounding Pokémon!", + "postSummonTabletsOfRuin": "{{pokemonNameWithAffix}}'s Tablets of Ruin lowered the {{statName}}\nof all surrounding Pokémon!", + "postSummonBeadsOfRuin": "{{pokemonNameWithAffix}}'s Beads of Ruin lowered the {{statName}}\nof all surrounding Pokémon!", "preventBerryUse": "{{pokemonNameWithAffix}} non riesce a\nmangiare le bacche per l'agitazione!", } as const; diff --git a/src/locales/it/achv.ts b/src/locales/it/achv.ts index 756d95e6431..91222b81579 100644 --- a/src/locales/it/achv.ts +++ b/src/locales/it/achv.ts @@ -170,8 +170,8 @@ export const PGMachv: AchievementTranslationEntries = { description: "Vinci in modalità classica", }, "UNEVOLVED_CLASSIC_VICTORY": { - name: "Alternanza scuola-lavoro", - description: "Completa la modalità classica con almeno un membro della squadra non evoluto completamente." + name: "Bring Your Child To Work Day", + description: "Beat the game in Classic Mode with at least one unevolved party member." }, "MONO_GEN_ONE": { @@ -269,8 +269,8 @@ export const PGMachv: AchievementTranslationEntries = { name: "Follettini e follettine", }, "FRESH_START": { - name: "Buona la prima!", - description: "Completa la modalità sfida 'Un nuovo inizio'." + name: "First Try!", + description: "Complete the Fresh Start challenge." } } as const; diff --git a/src/locales/it/battle-scene.ts b/src/locales/it/battle-scene.ts deleted file mode 100644 index 995ca744302..00000000000 --- a/src/locales/it/battle-scene.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SimpleTranslationEntries } from "#app/interfaces/locales"; - -export const battleScene: SimpleTranslationEntries = { - "moneyOwned": "{{formattedMoney}} ₽" -} as const; diff --git a/src/locales/it/battle.ts b/src/locales/it/battle.ts index 347a9968e96..bd7227eacb6 100644 --- a/src/locales/it/battle.ts +++ b/src/locales/it/battle.ts @@ -74,22 +74,22 @@ export const battle: SimpleTranslationEntries = { "fainted": "{{pokemonNameWithAffix}} non è più in\ngrado di combattere!", "statsAnd": "e", "stats": "statistiche", - "statRose_one": "La statistica {{stats}} di {{pokemonNameWithAffix}} è aumentata!", - "statRose_other": "Le statistiche {{stats}} di {{pokemonNameWithAffix}} sono aumentate!", - "statSharplyRose_one": "La statistica {{stats}} di {{pokemonNameWithAffix}} è aumentata molto!", - "statSharplyRose_other": "Le statistiche {{stats}} di {{pokemonNameWithAffix}} sono aumentate molto!", - "statRoseDrastically_one": "La statistica {{stats}} di {{pokemonNameWithAffix}} è aumentata drasticamente!", - "statRoseDrastically_other": "Le statistiche {{stats}} di {{pokemonNameWithAffix}} sono aumentate drasticamente!", - "statWontGoAnyHigher_one": "La statistica {{stats}} di {{pokemonNameWithAffix}} non può aumentare di più!", - "statWontGoAnyHigher_other": "Le statistiche {{stats}} di {{pokemonNameWithAffix}} non possono aumentare di più!", - "statFell_one": "La statistica {{stats}} di {{pokemonNameWithAffix}} è diminuita!", - "statFell_other": "Le statistiche {{stats}} di {{pokemonNameWithAffix}} sono diminuite!", - "statHarshlyFell_one": "La statistica {{stats}} di {{pokemonNameWithAffix}} è diminuita molto!", - "statHarshlyFell_other": "Le statistiche {{stats}} di {{pokemonNameWithAffix}} sono diminuite molto!", - "statSeverelyFell_one": "La statistica {{stats}} di {{pokemonNameWithAffix}} è diminuita drasticamente!", - "statSeverelyFell_other": "Le statistiche {{stats}} di {{pokemonNameWithAffix}} sono diminuite drasticamente!", - "statWontGoAnyLower_one": "La statistica {{stats}} di {{pokemonNameWithAffix}} non può diminuire di più!", - "statWontGoAnyLower_other": "Le statistiche {{stats}} di {{pokemonNameWithAffix}} non possono diminuire di più!", + "statRose_one": "{{pokemonNameWithAffix}}'s {{stats}} è aumentato/a!", + "statRose_other": "{{pokemonNameWithAffix}}'s {{stats}} rose!", + "statSharplyRose_one": "{{pokemonNameWithAffix}}'s {{stats}} è aumentato/a molto!", + "statSharplyRose_other": "{{pokemonNameWithAffix}}'s {{stats}} sharply rose!", + "statRoseDrastically_one": "{{pokemonNameWithAffix}}'s {{stats}} è aumentato/a drasticamente!", + "statRoseDrastically_other": "{{pokemonNameWithAffix}}'s {{stats}} rose drastically!", + "statWontGoAnyHigher_one": "{{pokemonNameWithAffix}}'s {{stats}} non può aumentare più di così!", + "statWontGoAnyHigher_other": "{{pokemonNameWithAffix}}'s {{stats}} won't go any higher!", + "statFell_one": "{{pokemonNameWithAffix}}'s {{stats}} è diminuito/a!", + "statFell_other": "{{pokemonNameWithAffix}}'s {{stats}} fell!", + "statHarshlyFell_one": "{{pokemonNameWithAffix}}'s {{stats}} è diminuito/a molto!", + "statHarshlyFell_other": "{{pokemonNameWithAffix}}'s {{stats}} harshly fell!", + "statSeverelyFell_one": "{{pokemonNameWithAffix}}'s {{stats}} è diminuito/a drasticamente!", + "statSeverelyFell_other": "{{pokemonNameWithAffix}}'s {{stats}} severely fell!", + "statWontGoAnyLower_one": "{{pokemonNameWithAffix}}'s {{stats}} non può diminuire più di così!", + "statWontGoAnyLower_other": "{{pokemonNameWithAffix}}'s {{stats}} won't go any lower!", "transformedIntoType": "{{pokemonName}} diventa\ndi tipo {{type}} type!", "retryBattle": "Vuoi riprovare dall'inizio della lotta?", "unlockedSomething": "{{unlockedThing}}\nè stato/a sbloccato/a.", diff --git a/src/locales/it/battler-tags.ts b/src/locales/it/battler-tags.ts index 518e9194521..7dd3ebc6fb1 100644 --- a/src/locales/it/battler-tags.ts +++ b/src/locales/it/battler-tags.ts @@ -1,14 +1,14 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battlerTags: SimpleTranslationEntries = { - "trappedDesc": "intrappolando", - "flinchedDesc": "tentennando", - "confusedDesc": "confuso", - "infatuatedDesc": "infatuato", - "seedDesc": "pieno di semi", - "nightmareDesc": "incubi", - "ingrainDesc": "radici", - "drowsyDesc": "assonnato", + "trappedDesc": "trapping", + "flinchedDesc": "flinching", + "confusedDesc": "confusion", + "infatuatedDesc": "infatuation", + "seedDesc": "seeding", + "nightmareDesc": "nightmares", + "ingrainDesc": "roots", + "drowsyDesc": "drowsiness", "rechargingLapse": "{{pokemonNameWithAffix}} deve\nricaricarsi!", "trappedOnAdd": "{{pokemonNameWithAffix}} non può\npiù fuggire!", "trappedOnRemove": "{{pokemonNameWithAffix}} è stato liberato\nda {{moveName}}", diff --git a/src/locales/it/challenges.ts b/src/locales/it/challenges.ts index dde5bd0d4e7..784791f5425 100644 --- a/src/locales/it/challenges.ts +++ b/src/locales/it/challenges.ts @@ -2,7 +2,7 @@ import { TranslationEntries } from "#app/interfaces/locales"; export const challenges: TranslationEntries = { "title": "Modificatori delle sfide", - "illegalEvolution": "{{pokemon}} non è più utilizzabile\nsecondo le regole della sfida!", + "illegalEvolution": "{{pokemon}} changed into an ineligble pokémon\nfor this challenge!", "singleGeneration": { "name": "Mono gen", "desc": "Puoi usare solo Pokémon di {{gen}} generazione.", @@ -23,8 +23,8 @@ export const challenges: TranslationEntries = { "desc_default": "Puoi usare solo Pokémon del tipo selezionato." }, "freshStart": { - "name": "Un nuovo inizio", - "desc": "Puoi usare solo gli starter originali, e come se avessi appena cominciato Pokérogue.", + "name": "Fresh Start", + "desc": "You can only use the original starters, and only as if you had just started PokéRogue.", "value.0": "Off", "value.1": "On", } diff --git a/src/locales/it/config.ts b/src/locales/it/config.ts index d6265061a9f..ceb52665796 100644 --- a/src/locales/it/config.ts +++ b/src/locales/it/config.ts @@ -4,7 +4,6 @@ import { arenaFlyout } from "./arena-flyout"; import { arenaTag } from "./arena-tag"; import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; -import { battleScene } from "./battle-scene"; import { battleInfo } from "./battle-info"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battlerTags } from "./battler-tags"; @@ -61,7 +60,6 @@ export const itConfig = { arenaFlyout: arenaFlyout, arenaTag: arenaTag, battle: battle, - battleScene: battleScene, battleInfo: battleInfo, battleMessageUiHandler: battleMessageUiHandler, battlePokemonForm: battlePokemonForm, diff --git a/src/locales/it/menu-ui-handler.ts b/src/locales/it/menu-ui-handler.ts index 3454de24f87..0cfea8d67b7 100644 --- a/src/locales/it/menu-ui-handler.ts +++ b/src/locales/it/menu-ui-handler.ts @@ -25,5 +25,5 @@ export const menuUiHandler: SimpleTranslationEntries = { "unlinkGoogle": "Scollega Google", "cancel": "Annulla", "losingProgressionWarning": "Perderai tutti i progressi dall'inizio della battaglia. Confermi?", - "noEggs": "Non stai schiudendo\nuova al momento!" + "noEggs": "You are not hatching\nany eggs at the moment!" } as const; diff --git a/src/locales/it/menu.ts b/src/locales/it/menu.ts index 3787ceb0e70..9766708f7ae 100644 --- a/src/locales/it/menu.ts +++ b/src/locales/it/menu.ts @@ -17,7 +17,7 @@ export const menu: SimpleTranslationEntries = { "username": "Nome utente", "password": "Password", "login": "Accedi", - "orUse": "O usa", + "orUse": "Or use", "register": "Registrati", "emptyUsername": "Nome utente mancante!", "invalidLoginUsername": "Nome utente non valido!", @@ -39,9 +39,9 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Classifica settimanale", "noRankings": "Nessuna classifica", "positionIcon": "#", - "usernameScoreboard": "Nome utente", - "score": "Punteggio", - "wave": "Onda", + "usernameScoreboard": "Username", + "score": "Score", + "wave": "Wave", "loading": "Caricamento…", "loadingAsset": "Caricamento asset: {{assetName}}", "playersOnline": "Giocatori online", diff --git a/src/locales/it/modifier-type.ts b/src/locales/it/modifier-type.ts index 0b166d268a5..6f054e4e566 100644 --- a/src/locales/it/modifier-type.ts +++ b/src/locales/it/modifier-type.ts @@ -101,7 +101,7 @@ export const modifierType: ModifierTypeTranslationEntries = { }, "TmModifierTypeWithInfo": { name: "MT{{moveId}} - {{moveName}}", - description: "Insegna {{moveName}} a un Pokémon\n(Tieni premuto C o Shift per maggiori informazioni).", + description: "Insegna {{moveName}} a un Pokémon\n(Hold C or Shift for more info).", }, "EvolutionItemModifierType": { description: "Fa evolvere determinate specie di Pokémon.", @@ -153,7 +153,7 @@ export const modifierType: ModifierTypeTranslationEntries = { "REVIVER_SEED": { name: "Revitalseme", description: "Il possessore recupera 1/2 di PS in caso di KO causato da un colpo diretto." }, - "WHITE_HERB": { name: "Erbachiara", description: "Strumento da dare a un Pokémon. Ripristina le statistiche ridotte in lotta." }, + "WHITE_HERB": { name: "Erbachiara", description: "An item to be held by a Pokémon. It will restore any lowered stat in battle." }, "ETHER": { name: "Etere" }, "MAX_ETHER": { name: "Etere max" }, diff --git a/src/locales/it/modifier.ts b/src/locales/it/modifier.ts index 94512efef0d..810524a9e5e 100644 --- a/src/locales/it/modifier.ts +++ b/src/locales/it/modifier.ts @@ -1,14 +1,14 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const modifier: SimpleTranslationEntries = { - "surviveDamageApply": "{{pokemonNameWithAffix}} resiste\ngrazie al/alla suo/a {{typeName}}!", - "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}}!", - "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}}!", - "enemyTurnHealApply": "{{pokemonNameWithAffix}}\nristabilisce parte dei PS!", + "surviveDamageApply": "{{pokemonNameWithAffix}} hung on\nusing its {{typeName}}!", + "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}}!", + "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}}!", + "enemyTurnHealApply": "{{pokemonNameWithAffix}}\nrestored some HP!", "bypassSpeedChanceApply": "{{pokemonName}} agisce più rapidamente del normale grazie al suo {{itemName}}!", } as const; diff --git a/src/locales/it/move-trigger.ts b/src/locales/it/move-trigger.ts index 92ce6a76a74..198fc269785 100644 --- a/src/locales/it/move-trigger.ts +++ b/src/locales/it/move-trigger.ts @@ -57,10 +57,10 @@ export const moveTriggers: SimpleTranslationEntries = { "sacrificialFullRestore": "{{pokemonName}} riceve i benefici\neffetti di Curardore!", "invertStats": "Le modifiche alle statistiche di {{pokemonName}}\nvengono invertite!", "resetStats": "Tutte le modifiche alle statistiche sono state annullate!", - "statEliminated": "Tutte le modifiche alle statistiche sono state annullate!", + "statEliminated": "All stat changes were eliminated!", "faintCountdown": "{{pokemonName}}\nandrà KO dopo {{turnCount}} turni.", "copyType": "{{pokemonName}} assume il tipo\ndi {{targetPokemonName}}!", "suppressAbilities": "L’abilità di {{pokemonName}}\nperde ogni efficacia!", "swapArenaTags": "{{pokemonName}} ha invertito gli effetti attivi\nnelle due metà del campo!", - "exposedMove": "{{pokemonName}} ha identificato\n{{targetPokemonName}}!", + "exposedMove": "{{pokemonName}} identified\n{{targetPokemonName}}!", } as const; diff --git a/src/locales/it/move.ts b/src/locales/it/move.ts index 1c510d4df6d..a2c99218cec 100644 --- a/src/locales/it/move.ts +++ b/src/locales/it/move.ts @@ -2915,7 +2915,7 @@ export const move: MoveTranslationEntries = { }, zippyZap: { name: "Sprintaboom", - effect: "Un attacco elettrico ad altissima velocità. Questa mossa ha priorità alta e aumenta l'elusione dell'utilizzatore.", + effect: "The user attacks the target with bursts of electricity at high speed. This move always goes first and raises the user's evasiveness.", }, splishySplash: { name: "Surfasplash", diff --git a/src/locales/it/settings.ts b/src/locales/it/settings.ts index 278a02bef52..4cdb2a89a94 100644 --- a/src/locales/it/settings.ts +++ b/src/locales/it/settings.ts @@ -99,9 +99,9 @@ export const settings: SimpleTranslationEntries = { "showBgmBar": "Mostra Nomi Musica", "moveTouchControls": "Move Touch Controls", "shopOverlayOpacity": "Opacità Finestra Negozio", - "shopCursorTarget": "Target Cursore Negozio", - "items": "Oggetti", - "reroll": "Rerolla", - "shop": "Negozio", - "checkTeam": "Squadra" + "shopCursorTarget": "Shop Cursor Target", + "items": "Items", + "reroll": "Reroll", + "shop": "Shop", + "checkTeam": "Check Team" } as const; diff --git a/src/locales/ja/battle-scene.ts b/src/locales/ja/battle-scene.ts deleted file mode 100644 index d2f074416e1..00000000000 --- a/src/locales/ja/battle-scene.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SimpleTranslationEntries } from "#app/interfaces/locales"; - -export const battleScene: SimpleTranslationEntries = { - "moneyOwned": "{{formattedMoney}}円" -} as const; diff --git a/src/locales/ja/config.ts b/src/locales/ja/config.ts index 61be36c08df..6af79547a04 100644 --- a/src/locales/ja/config.ts +++ b/src/locales/ja/config.ts @@ -4,7 +4,6 @@ import { arenaFlyout } from "./arena-flyout"; import { arenaTag } from "./arena-tag"; import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; -import { battleScene } from "./battle-scene"; import { battleInfo } from "./battle-info"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battlerTags } from "./battler-tags"; @@ -62,7 +61,6 @@ export const jaConfig = { arenaFlyout: arenaFlyout, arenaTag: arenaTag, battle: battle, - battleScene: battleScene, battleInfo: battleInfo, battleMessageUiHandler: battleMessageUiHandler, battlePokemonForm: battlePokemonForm, diff --git a/src/locales/ko/battle-scene.ts b/src/locales/ko/battle-scene.ts deleted file mode 100644 index 573e1791724..00000000000 --- a/src/locales/ko/battle-scene.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SimpleTranslationEntries } from "#app/interfaces/locales"; - -export const battleScene: SimpleTranslationEntries = { - "moneyOwned": "₽{{formattedMoney}}" -} as const; diff --git a/src/locales/ko/config.ts b/src/locales/ko/config.ts index 2bc60f04bef..114950a4d35 100644 --- a/src/locales/ko/config.ts +++ b/src/locales/ko/config.ts @@ -4,7 +4,6 @@ import { arenaFlyout } from "./arena-flyout"; import { arenaTag } from "./arena-tag"; import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; -import { battleScene } from "./battle-scene"; import { battleInfo } from "./battle-info"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battlerTags } from "./battler-tags"; @@ -61,7 +60,6 @@ export const koConfig = { arenaFlyout: arenaFlyout, arenaTag: arenaTag, battle: battle, - battleScene: battleScene, battleInfo: battleInfo, battleMessageUiHandler: battleMessageUiHandler, battlePokemonForm: battlePokemonForm, diff --git a/src/locales/ko/move-trigger.ts b/src/locales/ko/move-trigger.ts index e93639689d8..cea60e25333 100644 --- a/src/locales/ko/move-trigger.ts +++ b/src/locales/ko/move-trigger.ts @@ -8,7 +8,7 @@ export const moveTriggers: SimpleTranslationEntries = { "goingAllOutForAttack": "{{pokemonName}}[[는]]\n전력을 다하기 시작했다!", "regainedHealth": "{{pokemonName}}[[는]]\n기력을 회복했다!", "keptGoingAndCrashed": "{{pokemonName}}[[는]]\n의욕이 넘쳐서 땅에 부딪쳤다!", - "fled": "{{pokemonName}}[[는]]\n도망쳤다!", + "fled": "{{pokemonName}}[[는]]\N도망쳤다!", "cannotBeSwitchedOut": "{{pokemonName}}[[를]]\n돌아오게 할 수 없습니다!", "swappedAbilitiesWithTarget": "{{pokemonName}}[[는]]\n서로의 특성을 교체했다!", "coinsScatteredEverywhere": "돈이 주위에 흩어졌다!", diff --git a/src/locales/ko/settings.ts b/src/locales/ko/settings.ts index 38b0679d911..0d964f95f87 100644 --- a/src/locales/ko/settings.ts +++ b/src/locales/ko/settings.ts @@ -99,9 +99,9 @@ export const settings: SimpleTranslationEntries = { "showBgmBar": "BGM 제목 보여주기", "moveTouchControls": "터치 컨트롤 이동", "shopOverlayOpacity": "상점 오버레이 투명도", - "shopCursorTarget": "상점 커서 위치", - "items": "아이템", - "reroll": "갱신", - "shop": "상점", - "checkTeam": "파티 확인" + "shopCursorTarget": "Shop Cursor Target", + "items": "Items", + "reroll": "Reroll", + "shop": "Shop", + "checkTeam": "Check Team" } as const; diff --git a/src/locales/pt_BR/battle-scene.ts b/src/locales/pt_BR/battle-scene.ts deleted file mode 100644 index 573e1791724..00000000000 --- a/src/locales/pt_BR/battle-scene.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SimpleTranslationEntries } from "#app/interfaces/locales"; - -export const battleScene: SimpleTranslationEntries = { - "moneyOwned": "₽{{formattedMoney}}" -} as const; diff --git a/src/locales/pt_BR/config.ts b/src/locales/pt_BR/config.ts index 9ebb4867ae4..b48fcfdc8d8 100644 --- a/src/locales/pt_BR/config.ts +++ b/src/locales/pt_BR/config.ts @@ -4,7 +4,6 @@ import { PGFachv, PGMachv } from "./achv"; import { arenaFlyout } from "./arena-flyout"; import { arenaTag } from "./arena-tag"; import { battle } from "./battle"; -import { battleScene } from "./battle-scene"; import { battleInfo } from "./battle-info"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battlerTags } from "./battler-tags"; @@ -61,7 +60,6 @@ export const ptBrConfig = { arenaFlyout: arenaFlyout, arenaTag: arenaTag, battle: battle, - battleScene: battleScene, battleInfo: battleInfo, battleMessageUiHandler: battleMessageUiHandler, battlePokemonForm: battlePokemonForm, diff --git a/src/locales/zh_CN/battle-scene.ts b/src/locales/zh_CN/battle-scene.ts deleted file mode 100644 index 573e1791724..00000000000 --- a/src/locales/zh_CN/battle-scene.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SimpleTranslationEntries } from "#app/interfaces/locales"; - -export const battleScene: SimpleTranslationEntries = { - "moneyOwned": "₽{{formattedMoney}}" -} as const; diff --git a/src/locales/zh_CN/config.ts b/src/locales/zh_CN/config.ts index 99b4e56ffc2..24c8b870ffa 100644 --- a/src/locales/zh_CN/config.ts +++ b/src/locales/zh_CN/config.ts @@ -4,7 +4,6 @@ import { arenaFlyout } from "./arena-flyout"; import { arenaTag } from "./arena-tag"; import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; -import { battleScene } from "./battle-scene"; import { battleInfo } from "./battle-info"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battlerTags } from "./battler-tags"; @@ -61,7 +60,6 @@ export const zhCnConfig = { arenaFlyout: arenaFlyout, arenaTag: arenaTag, battle: battle, - battleScene: battleScene, battleInfo: battleInfo, battleMessageUiHandler: battleMessageUiHandler, battlePokemonForm: battlePokemonForm, diff --git a/src/locales/zh_CN/settings.ts b/src/locales/zh_CN/settings.ts index d727ac2bef5..cd3116a9723 100644 --- a/src/locales/zh_CN/settings.ts +++ b/src/locales/zh_CN/settings.ts @@ -99,9 +99,9 @@ export const settings: SimpleTranslationEntries = { "showBgmBar": "显示音乐名称", "moveTouchControls": "移动触摸控制", "shopOverlayOpacity": "商店显示不透明度", - "shopCursorTarget": "商店指针位置", - "items": "道具", - "reroll": "刷新", - "shop": "购买", - "checkTeam": "检查队伍" + "shopCursorTarget": "Shop Cursor Target", + "items": "Items", + "reroll": "Reroll", + "shop": "Shop", + "checkTeam": "Check Team" } as const; diff --git a/src/locales/zh_TW/battle-scene.ts b/src/locales/zh_TW/battle-scene.ts deleted file mode 100644 index 573e1791724..00000000000 --- a/src/locales/zh_TW/battle-scene.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SimpleTranslationEntries } from "#app/interfaces/locales"; - -export const battleScene: SimpleTranslationEntries = { - "moneyOwned": "₽{{formattedMoney}}" -} as const; diff --git a/src/locales/zh_TW/config.ts b/src/locales/zh_TW/config.ts index 269ea3003b9..004ed1da1ab 100644 --- a/src/locales/zh_TW/config.ts +++ b/src/locales/zh_TW/config.ts @@ -4,7 +4,6 @@ import { arenaFlyout } from "./arena-flyout"; import { arenaTag } from "./arena-tag"; import { PGFachv, PGMachv } from "./achv"; import { battle } from "./battle"; -import { battleScene } from "./battle-scene"; import { battleInfo } from "./battle-info"; import { battleMessageUiHandler } from "./battle-message-ui-handler"; import { battlerTags } from "./battler-tags"; @@ -61,7 +60,6 @@ export const zhTwConfig = { arenaFlyout: arenaFlyout, arenaTag: arenaTag, battle: battle, - battleScene: battleScene, battleInfo: battleInfo, battleMessageUiHandler: battleMessageUiHandler, battlePokemonForm: battlePokemonForm, diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 99f4540f493..8a6598f5849 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -1160,7 +1160,7 @@ export class TurnHealModifier extends PokemonHeldItemModifier { if (!pokemon.isFullHp()) { const scene = pokemon.scene; scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / 16) * this.stackCount, i18next.t("modifier:turnHealApply", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), typeName: this.type.name }), true)); + Math.max(Math.floor(pokemon.getMaxHp() / 16) * this.stackCount, 1), i18next.t("modifier:turnHealApply", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), typeName: this.type.name }), true)); return true; } @@ -1251,7 +1251,7 @@ export class HitHealModifier extends PokemonHeldItemModifier { if (pokemon.turnData.damageDealt && !pokemon.isFullHp()) { const scene = pokemon.scene; scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.turnData.damageDealt / 8) * this.stackCount, i18next.t("modifier:hitHealApply", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), typeName: this.type.name }), true)); + Math.max(Math.floor(pokemon.turnData.damageDealt / 8) * this.stackCount, 1), i18next.t("modifier:hitHealApply", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), typeName: this.type.name }), true)); } return true; @@ -1386,7 +1386,7 @@ export class PokemonInstantReviveModifier extends PokemonHeldItemModifier { const pokemon = args[0] as Pokemon; pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / 2), i18next.t("modifier:pokemonInstantReviveApply", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), typeName: this.type.name }), false, false, true)); + Math.max(Math.floor(pokemon.getMaxHp() / 2), 1), i18next.t("modifier:pokemonInstantReviveApply", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), typeName: this.type.name }), false, false, true)); pokemon.resetStatus(true, false, true); return true; diff --git a/src/phases/attempt-run-phase.ts b/src/phases/attempt-run-phase.ts index 17625c57fc6..9781ca6d360 100644 --- a/src/phases/attempt-run-phase.ts +++ b/src/phases/attempt-run-phase.ts @@ -23,7 +23,7 @@ export class AttemptRunPhase extends PokemonPhase { const enemySpeed = enemyField.reduce((total: integer, enemyPokemon: Pokemon) => total + enemyPokemon.getStat(Stat.SPD), 0) / enemyField.length; const escapeChance = new Utils.IntegerHolder((((playerPokemon.getStat(Stat.SPD) * 128) / enemySpeed) + (30 * this.scene.currentBattle.escapeAttempts++)) % 256); - applyAbAttrs(RunSuccessAbAttr, playerPokemon, null, false, escapeChance); + applyAbAttrs(RunSuccessAbAttr, playerPokemon, null, escapeChance); if (playerPokemon.randSeedInt(256) < escapeChance.value) { this.scene.playSound("flee"); diff --git a/src/phases/command-phase.ts b/src/phases/command-phase.ts index 68ede826d95..5d466e5d3b6 100644 --- a/src/phases/command-phase.ts +++ b/src/phases/command-phase.ts @@ -189,7 +189,7 @@ export class CommandPhase extends FieldPhase { const batonPass = isSwitch && args[0] as boolean; const trappedAbMessages: string[] = []; if (!batonPass) { - enemyField.forEach(enemyPokemon => applyCheckTrappedAbAttrs(CheckTrappedAbAttr, enemyPokemon, trapped, playerPokemon, trappedAbMessages, true)); + enemyField.forEach(enemyPokemon => applyCheckTrappedAbAttrs(CheckTrappedAbAttr, enemyPokemon, trapped, playerPokemon, true, trappedAbMessages)); } if (batonPass || (!trapTag && !trapped.value)) { this.scene.currentBattle.turnCommands[this.fieldIndex] = isSwitch diff --git a/src/phases/encounter-phase.ts b/src/phases/encounter-phase.ts index dfa198c8339..739bb1d93f1 100644 --- a/src/phases/encounter-phase.ts +++ b/src/phases/encounter-phase.ts @@ -67,7 +67,7 @@ export class EncounterPhase extends BattlePhase { battle.enemyParty[e].ivs = new Array(6).fill(31); } this.scene.getParty().slice(0, !battle.double ? 1 : 2).reverse().forEach(playerPokemon => { - applyAbAttrs(SyncEncounterNatureAbAttr, playerPokemon, null, false, battle.enemyParty[e]); + applyAbAttrs(SyncEncounterNatureAbAttr, playerPokemon, null, battle.enemyParty[e]); }); } } diff --git a/src/phases/enemy-command-phase.ts b/src/phases/enemy-command-phase.ts index 0b62fcbe813..d7f553681c2 100644 --- a/src/phases/enemy-command-phase.ts +++ b/src/phases/enemy-command-phase.ts @@ -47,7 +47,7 @@ export class EnemyCommandPhase extends FieldPhase { const trapTag = enemyPokemon.findTag(t => t instanceof TrappedTag) as TrappedTag; const trapped = new Utils.BooleanHolder(false); - opponents.forEach(playerPokemon => applyCheckTrappedAbAttrs(CheckTrappedAbAttr, playerPokemon, trapped, enemyPokemon, [], true)); + opponents.forEach(playerPokemon => applyCheckTrappedAbAttrs(CheckTrappedAbAttr, playerPokemon, trapped, enemyPokemon, true, [])); if (!trapTag && !trapped.value) { const partyMemberScores = trainer.getPartyMemberMatchupScores(enemyPokemon.trainerSlot, true); diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index 12018656458..a5ac913cc5d 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -74,7 +74,7 @@ export class MoveEffectPhase extends PokemonPhase { // Assume single target for multi hit applyMoveAttrs(MultiHitAttr, user, this.getTarget() ?? null, move, hitCount); // If Parental Bond is applicable, double the hit count - applyPreAttackAbAttrs(AddSecondStrikeAbAttr, user, null, move, false, targets.length, hitCount, new Utils.IntegerHolder(0)); + applyPreAttackAbAttrs(AddSecondStrikeAbAttr, user, null, move, targets.length, hitCount, new Utils.IntegerHolder(0)); // If Multi-Lens is applicable, multiply the hit count by 1 + the number of Multi-Lenses held by the user if (move instanceof AttackMove && !move.hasAttr(FixedDamageAttr)) { this.scene.applyModifiers(PokemonMultiHitModifier, user.isPlayer(), user, hitCount, new Utils.IntegerHolder(0)); diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index 2aed0bb9495..b9656df856b 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -90,7 +90,7 @@ export class MovePhase extends BattlePhase { : null; if (moveTarget) { const oldTarget = moveTarget.value; - this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, false, this.move.moveId, moveTarget)); + this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, this.move.moveId, moveTarget)); this.pokemon.getOpponents().forEach(p => { const redirectTag = p.getTag(CenterOfAttentionTag) as CenterOfAttentionTag; if (redirectTag && (!redirectTag.powder || (!this.pokemon.isOfType(Type.GRASS) && !this.pokemon.hasAbility(Abilities.OVERCOAT)))) { diff --git a/src/phases/post-turn-status-effect-phase.ts b/src/phases/post-turn-status-effect-phase.ts index 47db32303a5..8b533f2e90a 100644 --- a/src/phases/post-turn-status-effect-phase.ts +++ b/src/phases/post-turn-status-effect-phase.ts @@ -34,7 +34,7 @@ export class PostTurnStatusEffectPhase extends PokemonPhase { break; case StatusEffect.BURN: damage.value = Math.max(pokemon.getMaxHp() >> 4, 1); - applyAbAttrs(ReduceBurnDamageAbAttr, pokemon, null, false, damage); + applyAbAttrs(ReduceBurnDamageAbAttr, pokemon, null, damage); break; } if (damage.value) { diff --git a/src/phases/stat-change-phase.ts b/src/phases/stat-change-phase.ts index fec3da9bc9a..3469cc62942 100644 --- a/src/phases/stat-change-phase.ts +++ b/src/phases/stat-change-phase.ts @@ -68,7 +68,7 @@ export class StatChangePhase extends PokemonPhase { const levels = new Utils.IntegerHolder(this.levels); if (!this.ignoreAbilities) { - applyAbAttrs(StatChangeMultiplierAbAttr, pokemon, null, false, levels); + applyAbAttrs(StatChangeMultiplierAbAttr, pokemon, null, levels); } const battleStats = this.getPokemon().summonData.battleStats; @@ -90,7 +90,7 @@ export class StatChangePhase extends PokemonPhase { if (levels.value > 0 && this.canBeCopied) { for (const opponent of pokemon.getOpponents()) { - applyAbAttrs(StatChangeCopyAbAttr, opponent, null, false, this.stats, levels.value); + applyAbAttrs(StatChangeCopyAbAttr, opponent, null, this.stats, levels.value); } } diff --git a/src/phases/turn-start-phase.ts b/src/phases/turn-start-phase.ts index e4064fc784a..1320cb6235c 100644 --- a/src/phases/turn-start-phase.ts +++ b/src/phases/turn-start-phase.ts @@ -34,8 +34,8 @@ export class TurnStartPhase extends FieldPhase { this.scene.getField(true).filter(p => p.summonData).map(p => { const bypassSpeed = new Utils.BooleanHolder(false); const canCheckHeldItems = new Utils.BooleanHolder(true); - applyAbAttrs(BypassSpeedChanceAbAttr, p, null, false, bypassSpeed); - applyAbAttrs(PreventBypassSpeedChanceAbAttr, p, null, false, bypassSpeed, canCheckHeldItems); + applyAbAttrs(BypassSpeedChanceAbAttr, p, null, bypassSpeed); + applyAbAttrs(PreventBypassSpeedChanceAbAttr, p, null, bypassSpeed, canCheckHeldItems); if (canCheckHeldItems.value) { this.scene.applyModifiers(BypassSpeedChanceModifier, p.isPlayer(), p, bypassSpeed); } @@ -64,8 +64,8 @@ export class TurnStartPhase extends FieldPhase { applyMoveAttrs(IncrementMovePriorityAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a)!, null, aMove, aPriority); //TODO: is the bang correct here? applyMoveAttrs(IncrementMovePriorityAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b)!, null, bMove, bPriority); //TODO: is the bang correct here? - applyAbAttrs(ChangeMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a)!, null, false, aMove, aPriority); //TODO: is the bang correct here? - applyAbAttrs(ChangeMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b)!, null, false, bMove, bPriority); //TODO: is the bang correct here? + applyAbAttrs(ChangeMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a)!, null, aMove, aPriority); //TODO: is the bang correct here? + applyAbAttrs(ChangeMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b)!, null, bMove, bPriority); //TODO: is the bang correct here? if (aPriority.value !== bPriority.value) { const bracketDifference = Math.ceil(aPriority.value) - Math.ceil(bPriority.value); diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index b786787f83e..33f00d22555 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -26,7 +26,6 @@ const unicodeRanges = { kana: "U+3040-30FF", CJKCommon: "U+2E80-2EFF,U+3000-303F,U+31C0-31EF,U+3200-32FF,U+3400-4DBF,U+F900-FAFF,U+FE30-FE4F", CJKIdeograph: "U+4E00-9FFF", - specialCharacters: "U+266A,U+2605,U+2665,U+2663" //♪.★,♥,♣ }; const rangesByLanguage = { korean: [unicodeRanges.CJKCommon, unicodeRanges.hangul].join(","), @@ -35,15 +34,6 @@ const rangesByLanguage = { }; const fonts: Array = [ - // unicode (special character from PokePT) - { - face: new FontFace("emerald", "url(./fonts/PokePT_Wansung.woff2)", { unicodeRange: unicodeRanges.specialCharacters }), - }, - { - face: new FontFace("pkmnems", "url(./fonts/PokePT_Wansung.woff2)", { unicodeRange: unicodeRanges.specialCharacters }), - extraOptions: { sizeAdjust: "133%" }, - }, - // unicode (korean) { face: new FontFace("emerald", "url(./fonts/PokePT_Wansung.woff2)", { unicodeRange: rangesByLanguage.korean }), }, diff --git a/src/test/abilities/ability_timing.test.ts b/src/test/abilities/ability_timing.test.ts index 3238f880992..c117c62d45b 100644 --- a/src/test/abilities/ability_timing.test.ts +++ b/src/test/abilities/ability_timing.test.ts @@ -1,15 +1,15 @@ -import { CommandPhase } from "#app/phases/command-phase"; -import { MessagePhase } from "#app/phases/message-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; import i18next, { initI18n } from "#app/plugins/i18n"; +import GameManager from "#test/utils/gameManager"; import { Mode } from "#app/ui/ui"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { MessagePhase } from "#app/phases/message-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; describe("Ability Timing", () => { diff --git a/src/test/abilities/aura_break.test.ts b/src/test/abilities/aura_break.test.ts index 7de300c157a..bca400bc0e3 100644 --- a/src/test/abilities/aura_break.test.ts +++ b/src/test/abilities/aura_break.test.ts @@ -1,18 +1,19 @@ -import { allMoves } from "#app/data/move"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import { allMoves } from "#app/data/move.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; describe("Abilities - Aura Break", () => { let phaserGame: Phaser.Game; let game: GameManager; - const auraBreakMultiplier = 9 / 16 * 4 / 3; + const auraBreakMultiplier = 9/16 * 4/3; beforeAll(() => { phaserGame = new Phaser.Game({ @@ -41,7 +42,7 @@ describe("Abilities - Aura Break", () => { vi.spyOn(moveToCheck, "calculateBattlePower"); await game.startBattle([Species.PIKACHU]); - game.move.select(Moves.MOONBLAST); + game.doAttack(getMovePosition(game.scene, 0, Moves.MOONBLAST)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(expect.closeTo(basePower * auraBreakMultiplier)); @@ -55,7 +56,7 @@ describe("Abilities - Aura Break", () => { vi.spyOn(moveToCheck, "calculateBattlePower"); await game.startBattle([Species.PIKACHU]); - game.move.select(Moves.DARK_PULSE); + game.doAttack(getMovePosition(game.scene, 0, Moves.DARK_PULSE)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(expect.closeTo(basePower * auraBreakMultiplier)); diff --git a/src/test/abilities/battery.test.ts b/src/test/abilities/battery.test.ts index 020866509d6..766c1c30ecc 100644 --- a/src/test/abilities/battery.test.ts +++ b/src/test/abilities/battery.test.ts @@ -1,13 +1,14 @@ -import { allMoves } from "#app/data/move"; -import { Abilities } from "#app/enums/abilities"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { allMoves } from "#app/data/move.js"; +import { Abilities } from "#app/enums/abilities.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Abilities - Battery", () => { let phaserGame: Phaser.Game; @@ -42,8 +43,8 @@ describe("Abilities - Battery", () => { await game.startBattle([Species.PIKACHU, Species.CHARJABUG]); - game.move.select(Moves.DAZZLING_GLEAM); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.DAZZLING_GLEAM)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(basePower * batteryMultiplier); @@ -57,8 +58,8 @@ describe("Abilities - Battery", () => { await game.startBattle([Species.PIKACHU, Species.CHARJABUG]); - game.move.select(Moves.BREAKING_SWIPE); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.BREAKING_SWIPE)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(basePower); @@ -72,8 +73,8 @@ describe("Abilities - Battery", () => { await game.startBattle([Species.CHARJABUG, Species.PIKACHU]); - game.move.select(Moves.DAZZLING_GLEAM); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.DAZZLING_GLEAM)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(basePower); diff --git a/src/test/abilities/battle_bond.test.ts b/src/test/abilities/battle_bond.test.ts index 71e9438db8f..c28a00e821d 100644 --- a/src/test/abilities/battle_bond.test.ts +++ b/src/test/abilities/battle_bond.test.ts @@ -1,10 +1,11 @@ -import { Status, StatusEffect } from "#app/data/status-effect"; -import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { Status, StatusEffect } from "#app/data/status-effect.js"; +import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; const TIMEOUT = 20 * 1000; @@ -52,7 +53,7 @@ describe("Abilities - BATTLE BOND", () => { greninja!.status = new Status(StatusEffect.FAINT); expect(greninja!.isFainted()).toBe(true); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.doKillOpponents(); await game.phaseInterceptor.to(TurnEndPhase); game.doSelectModifier(); diff --git a/src/test/abilities/costar.test.ts b/src/test/abilities/costar.test.ts index 9a4baeef1fb..9410ee55069 100644 --- a/src/test/abilities/costar.test.ts +++ b/src/test/abilities/costar.test.ts @@ -1,13 +1,14 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { Abilities } from "#app/enums/abilities"; -import { Moves } from "#app/enums/moves"; -import { Species } from "#app/enums/species"; -import { CommandPhase } from "#app/phases/command-phase"; -import { MessagePhase } from "#app/phases/message-phase"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { Moves } from "#app/enums/moves.js"; +import { Species } from "#app/enums/species.js"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { MessagePhase } from "#app/phases/message-phase.js"; const TIMEOUT = 20 * 1000; @@ -43,15 +44,15 @@ describe("Abilities - COSTAR", () => { let [leftPokemon, rightPokemon] = game.scene.getPlayerField(); - game.move.select(Moves.NASTY_PLOT); + game.doAttack(getMovePosition(game.scene, 0, Moves.NASTY_PLOT)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.toNextTurn(); expect(leftPokemon.summonData.battleStats[BattleStat.SPATK]).toBe(+2); expect(rightPokemon.summonData.battleStats[BattleStat.SPATK]).toBe(0); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(CommandPhase); game.doSwitchPokemon(2); await game.phaseInterceptor.to(MessagePhase); @@ -75,7 +76,7 @@ describe("Abilities - COSTAR", () => { expect(leftPokemon.summonData.battleStats[BattleStat.ATK]).toBe(-2); expect(leftPokemon.summonData.battleStats[BattleStat.ATK]).toBe(-2); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(CommandPhase); game.doSwitchPokemon(2); await game.phaseInterceptor.to(MessagePhase); diff --git a/src/test/abilities/disguise.test.ts b/src/test/abilities/disguise.test.ts index 58087b408a5..969375c397e 100644 --- a/src/test/abilities/disguise.test.ts +++ b/src/test/abilities/disguise.test.ts @@ -1,17 +1,17 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { StatusEffect } from "#app/data/status-effect"; -import { CommandPhase } from "#app/phases/command-phase"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; -import { Mode } from "#app/ui/ui"; -import { toDmgValue } from "#app/utils"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { StatusEffect } from "#app/data/status-effect.js"; +import { BattleStat } from "#app/data/battle-stat.js"; import { SPLASH_ONLY } from "../utils/testUtils"; +import { Mode } from "#app/ui/ui.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; +import { CommandPhase } from "#app/phases/command-phase.js"; const TIMEOUT = 20 * 1000; @@ -47,11 +47,11 @@ describe("Abilities - Disguise", () => { const mimikyu = game.scene.getEnemyPokemon()!; const maxHp = mimikyu.getMaxHp(); - const disguiseDamage = toDmgValue(maxHp / 8); + const disguiseDamage = Math.floor(maxHp / 8); expect(mimikyu.formIndex).toBe(disguisedForm); - game.move.select(Moves.SHADOW_SNEAK); + game.doAttack(getMovePosition(game.scene, 0, Moves.SHADOW_SNEAK)); await game.phaseInterceptor.to(MoveEndPhase); @@ -66,7 +66,7 @@ describe("Abilities - Disguise", () => { expect(mimikyu.formIndex).toBe(disguisedForm); - game.move.select(Moves.VACUUM_WAVE); + game.doAttack(getMovePosition(game.scene, 0, Moves.VACUUM_WAVE)); await game.phaseInterceptor.to(MoveEndPhase); @@ -80,11 +80,11 @@ describe("Abilities - Disguise", () => { const mimikyu = game.scene.getEnemyPokemon()!; const maxHp = mimikyu.getMaxHp(); - const disguiseDamage = toDmgValue(maxHp / 8); + const disguiseDamage = Math.floor(maxHp / 8); expect(mimikyu.formIndex).toBe(disguisedForm); - game.move.select(Moves.SURGING_STRIKES); + game.doAttack(getMovePosition(game.scene, 0, Moves.SURGING_STRIKES)); // First hit await game.phaseInterceptor.to(MoveEffectPhase); @@ -103,7 +103,7 @@ describe("Abilities - Disguise", () => { const mimikyu = game.scene.getEnemyPokemon()!; expect(mimikyu.hp).toBe(mimikyu.getMaxHp()); - game.move.select(Moves.TOXIC_THREAD); + game.doAttack(getMovePosition(game.scene, 0, Moves.TOXIC_THREAD)); await game.phaseInterceptor.to(TurnEndPhase); @@ -121,9 +121,9 @@ describe("Abilities - Disguise", () => { const mimikyu = game.scene.getPlayerPokemon()!; const maxHp = mimikyu.getMaxHp(); - const disguiseDamage = toDmgValue(maxHp / 8); + const disguiseDamage = Math.floor(maxHp / 8); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); @@ -148,7 +148,7 @@ describe("Abilities - Disguise", () => { const mimikyu = game.scene.getParty()[1]!; expect(mimikyu.formIndex).toBe(bustedForm); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.doKillOpponents(); await game.toNextWave(); @@ -168,7 +168,7 @@ describe("Abilities - Disguise", () => { expect(mimikyu.formIndex).toBe(bustedForm); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.doKillOpponents(); await game.toNextWave(); @@ -188,11 +188,11 @@ describe("Abilities - Disguise", () => { expect(mimikyu1.formIndex).toBe(bustedForm); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.killPokemon(mimikyu1); game.doSelectPartyPokemon(1); await game.toNextTurn(); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.doKillOpponents(); game.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => { // TODO: Make tests run in set mode instead of switch mode game.setMode(Mode.MESSAGE); diff --git a/src/test/abilities/dry_skin.test.ts b/src/test/abilities/dry_skin.test.ts index b337e4d96f7..1e3860da985 100644 --- a/src/test/abilities/dry_skin.test.ts +++ b/src/test/abilities/dry_skin.test.ts @@ -1,11 +1,12 @@ -import { Species } from "#app/enums/species"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { Species } from "#app/enums/species.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Abilities - Dry Skin", () => { let phaserGame: Phaser.Game; @@ -42,13 +43,13 @@ describe("Abilities - Dry Skin", () => { // first turn let previousEnemyHp = enemy.hp; - game.move.select(Moves.SUNNY_DAY); + game.doAttack(getMovePosition(game.scene, 0, Moves.SUNNY_DAY)); await game.phaseInterceptor.to(TurnEndPhase); expect(enemy.hp).toBeLessThan(previousEnemyHp); // second turn previousEnemyHp = enemy.hp; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(enemy.hp).toBeLessThan(previousEnemyHp); }); @@ -65,13 +66,13 @@ describe("Abilities - Dry Skin", () => { // first turn let previousEnemyHp = enemy.hp; - game.move.select(Moves.RAIN_DANCE); + game.doAttack(getMovePosition(game.scene, 0, Moves.RAIN_DANCE)); await game.phaseInterceptor.to(TurnEndPhase); expect(enemy.hp).toBeGreaterThan(previousEnemyHp); // second turn previousEnemyHp = enemy.hp; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(enemy.hp).toBeGreaterThan(previousEnemyHp); }); @@ -86,7 +87,7 @@ describe("Abilities - Dry Skin", () => { enemy.hp = initialHP; // first turn - game.move.select(Moves.FLAMETHROWER); + game.doAttack(getMovePosition(game.scene, 0, Moves.FLAMETHROWER)); await game.phaseInterceptor.to(TurnEndPhase); const fireDamageTakenWithDrySkin = initialHP - enemy.hp; @@ -95,7 +96,7 @@ describe("Abilities - Dry Skin", () => { game.override.enemyAbility(Abilities.NONE); // second turn - game.move.select(Moves.FLAMETHROWER); + game.doAttack(getMovePosition(game.scene, 0, Moves.FLAMETHROWER)); await game.phaseInterceptor.to(TurnEndPhase); const fireDamageTakenWithoutDrySkin = initialHP - enemy.hp; @@ -112,7 +113,7 @@ describe("Abilities - Dry Skin", () => { enemy.hp = 1; - game.move.select(Moves.WATER_GUN); + game.doAttack(getMovePosition(game.scene, 0, Moves.WATER_GUN)); await game.phaseInterceptor.to(TurnEndPhase); expect(enemy.hp).toBeGreaterThan(1); }); @@ -128,7 +129,7 @@ describe("Abilities - Dry Skin", () => { enemy.hp = 1; game.override.enemyMoveset([Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT]); - game.move.select(Moves.WATER_GUN); + game.doAttack(getMovePosition(game.scene, 0, Moves.WATER_GUN)); await game.phaseInterceptor.to(TurnEndPhase); expect(enemy.hp).toBe(1); }); @@ -144,14 +145,14 @@ describe("Abilities - Dry Skin", () => { enemy.hp = 1; // first turn - game.move.select(Moves.WATER_SHURIKEN); + game.doAttack(getMovePosition(game.scene, 0, Moves.WATER_SHURIKEN)); await game.phaseInterceptor.to(TurnEndPhase); const healthGainedFromWaterShuriken = enemy.hp - 1; enemy.hp = 1; // second turn - game.move.select(Moves.WATER_GUN); + game.doAttack(getMovePosition(game.scene, 0, Moves.WATER_GUN)); await game.phaseInterceptor.to(TurnEndPhase); const healthGainedFromWaterGun = enemy.hp - 1; diff --git a/src/test/abilities/flash_fire.test.ts b/src/test/abilities/flash_fire.test.ts index de40873998f..28c59903b68 100644 --- a/src/test/abilities/flash_fire.test.ts +++ b/src/test/abilities/flash_fire.test.ts @@ -1,15 +1,16 @@ -import { BattlerIndex } from "#app/battle"; -import { StatusEffect } from "#app/data/status-effect"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { Species } from "#app/enums/species"; -import { MovePhase } from "#app/phases/move-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { Species } from "#app/enums/species.js"; +import GameManager from "#test/utils/gameManager"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { StatusEffect } from "#app/data/status-effect.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { BattlerIndex } from "#app/battle.js"; +import { MovePhase } from "#app/phases/move-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Abilities - Flash Fire", () => { let phaserGame: Phaser.Game; @@ -37,35 +38,35 @@ describe("Abilities - Flash Fire", () => { }); - it("immune to Fire-type moves", async () => { + it("immune to Fire-type moves", async() => { game.override.enemyMoveset(Array(4).fill(Moves.EMBER)).moveset(SPLASH_ONLY); await game.startBattle([Species.BLISSEY]); const blissey = game.scene.getPlayerPokemon()!; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(blissey.hp).toBe(blissey.getMaxHp()); }, 20000); - it("not activate if the Pokémon is protected from the Fire-type move", async () => { + it("not activate if the Pokémon is protected from the Fire-type move", async() => { game.override.enemyMoveset(Array(4).fill(Moves.EMBER)).moveset([Moves.PROTECT]); await game.startBattle([Species.BLISSEY]); const blissey = game.scene.getPlayerPokemon()!; - game.move.select(Moves.PROTECT); + game.doAttack(getMovePosition(game.scene, 0, Moves.PROTECT)); await game.phaseInterceptor.to(TurnEndPhase); expect(blissey!.getTag(BattlerTagType.FIRE_BOOST)).toBeUndefined(); }, 20000); - it("activated by Will-O-Wisp", async () => { + it("activated by Will-O-Wisp", async() => { game.override.enemyMoveset(Array(4).fill(Moves.WILL_O_WISP)).moveset(SPLASH_ONLY); await game.startBattle([Species.BLISSEY]); const blissey = game.scene.getPlayerPokemon()!; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.move.forceHit(); await game.phaseInterceptor.to(MovePhase, false); await game.move.forceHit(); @@ -74,25 +75,25 @@ describe("Abilities - Flash Fire", () => { expect(blissey!.getTag(BattlerTagType.FIRE_BOOST)).toBeDefined(); }, 20000); - it("activated after being frozen", async () => { + it("activated after being frozen", async() => { game.override.enemyMoveset(Array(4).fill(Moves.EMBER)).moveset(SPLASH_ONLY); game.override.statusEffect(StatusEffect.FREEZE); await game.startBattle([Species.BLISSEY]); const blissey = game.scene.getPlayerPokemon()!; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(blissey!.getTag(BattlerTagType.FIRE_BOOST)).toBeDefined(); }, 20000); - it("not passing with baton pass", async () => { + it("not passing with baton pass", async() => { game.override.enemyMoveset(Array(4).fill(Moves.EMBER)).moveset([Moves.BATON_PASS]); await game.startBattle([Species.BLISSEY, Species.CHANSEY]); // ensure use baton pass after enemy moved - game.move.select(Moves.BATON_PASS); + game.doAttack(getMovePosition(game.scene, 0, Moves.BATON_PASS)); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); game.doSelectPartyPokemon(1); @@ -103,7 +104,7 @@ describe("Abilities - Flash Fire", () => { expect(chansey!.getTag(BattlerTagType.FIRE_BOOST)).toBeUndefined(); }, 20000); - it("boosts Fire-type move when the ability is activated", async () => { + it("boosts Fire-type move when the ability is activated", async() => { game.override.enemyMoveset(Array(4).fill(Moves.FIRE_PLEDGE)).moveset([Moves.EMBER, Moves.SPLASH]); game.override.enemyAbility(Abilities.FLASH_FIRE).ability(Abilities.NONE); await game.startBattle([Species.BLISSEY]); @@ -112,7 +113,7 @@ describe("Abilities - Flash Fire", () => { blissey.hp = initialHP; // first turn - game.move.select(Moves.EMBER); + game.doAttack(getMovePosition(game.scene, 0, Moves.EMBER)); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.phaseInterceptor.to(TurnEndPhase); const originalDmg = initialHP - blissey.hp; @@ -121,7 +122,7 @@ describe("Abilities - Flash Fire", () => { blissey.hp = initialHP; // second turn - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); const flashFireDmg = initialHP - blissey.hp; diff --git a/src/test/abilities/gulp_missile.test.ts b/src/test/abilities/gulp_missile.test.ts index a451d290906..d033604fe00 100644 --- a/src/test/abilities/gulp_missile.test.ts +++ b/src/test/abilities/gulp_missile.test.ts @@ -1,18 +1,19 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { StatusEffect } from "#app/enums/status-effect"; -import Pokemon from "#app/field/pokemon"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { TurnStartPhase } from "#app/phases/turn-start-phase"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; import GameManager from "#app/test/utils/gameManager"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; 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 { BattleStat } from "#app/data/battle-stat.js"; +import { StatusEffect } from "#app/enums/status-effect.js"; +import Pokemon from "#app/field/pokemon.js"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import { TurnStartPhase } from "#app/phases/turn-start-phase.js"; describe("Abilities - Gulp Missile", () => { let phaserGame: Phaser.Game; @@ -29,7 +30,7 @@ describe("Abilities - Gulp Missile", () => { * @returns The effect damage of Gulp Missile */ const getEffectDamage = (pokemon: Pokemon): number => { - return Math.max(1, Math.floor(pokemon.getMaxHp() * 1 / 4)); + return Math.max(1, Math.floor(pokemon.getMaxHp() * 1/4)); }; beforeAll(() => { @@ -57,9 +58,9 @@ describe("Abilities - Gulp Missile", () => { await game.startBattle([Species.CRAMORANT]); const cramorant = game.scene.getPlayerPokemon()!; - game.move.select(Moves.DIVE); + game.doAttack(getMovePosition(game.scene, 0, Moves.DIVE)); await game.toNextTurn(); - game.move.select(Moves.DIVE); + game.doAttack(getMovePosition(game.scene, 0, Moves.DIVE)); await game.phaseInterceptor.to(MoveEndPhase); expect(cramorant.getHpRatio()).toBeGreaterThanOrEqual(.5); @@ -74,7 +75,7 @@ describe("Abilities - Gulp Missile", () => { vi.spyOn(cramorant, "getHpRatio").mockReturnValue(.49); expect(cramorant.getHpRatio()).toBe(.49); - game.move.select(Moves.SURF); + game.doAttack(getMovePosition(game.scene, 0, Moves.SURF)); await game.phaseInterceptor.to(MoveEndPhase); expect(cramorant.getTag(BattlerTagType.GULP_MISSILE_PIKACHU)).toBeDefined(); @@ -85,7 +86,7 @@ describe("Abilities - Gulp Missile", () => { await game.startBattle([Species.CRAMORANT, Species.MAGIKARP]); const cramorant = game.scene.getPlayerPokemon()!; - game.move.select(Moves.SURF); + game.doAttack(getMovePosition(game.scene, 0, Moves.SURF)); await game.toNextTurn(); game.doSwitchPokemon(1); @@ -100,7 +101,7 @@ describe("Abilities - Gulp Missile", () => { await game.startBattle([Species.CRAMORANT]); const cramorant = game.scene.getPlayerPokemon()!; - game.move.select(Moves.DIVE); + game.doAttack(getMovePosition(game.scene, 0, Moves.DIVE)); await game.phaseInterceptor.to(MoveEndPhase); expect(cramorant.getTag(BattlerTagType.GULP_MISSILE_ARROKUDA)).toBeDefined(); @@ -114,7 +115,7 @@ describe("Abilities - Gulp Missile", () => { const enemy = game.scene.getEnemyPokemon()!; vi.spyOn(enemy, "damageAndUpdate"); - game.move.select(Moves.SURF); + game.doAttack(getMovePosition(game.scene, 0, Moves.SURF)); await game.phaseInterceptor.to(TurnEndPhase); expect(enemy.damageAndUpdate).toHaveReturnedWith(getEffectDamage(enemy)); @@ -127,7 +128,7 @@ describe("Abilities - Gulp Missile", () => { const cramorant = game.scene.getPlayerPokemon()!; vi.spyOn(cramorant, "getHpRatio").mockReturnValue(.55); - game.move.select(Moves.SURF); + game.doAttack(getMovePosition(game.scene, 0, Moves.SURF)); await game.phaseInterceptor.to(MoveEndPhase); expect(cramorant.getTag(BattlerTagType.GULP_MISSILE_ARROKUDA)).toBeDefined(); @@ -149,7 +150,7 @@ describe("Abilities - Gulp Missile", () => { vi.spyOn(enemy, "damageAndUpdate"); vi.spyOn(cramorant, "getHpRatio").mockReturnValue(.55); - game.move.select(Moves.SURF); + game.doAttack(getMovePosition(game.scene, 0, Moves.SURF)); await game.phaseInterceptor.to(MoveEndPhase); expect(cramorant.getTag(BattlerTagType.GULP_MISSILE_ARROKUDA)).toBeDefined(); @@ -173,7 +174,7 @@ describe("Abilities - Gulp Missile", () => { vi.spyOn(enemy, "damageAndUpdate"); vi.spyOn(cramorant, "getHpRatio").mockReturnValue(.45); - game.move.select(Moves.SURF); + game.doAttack(getMovePosition(game.scene, 0, Moves.SURF)); await game.phaseInterceptor.to(MoveEndPhase); expect(cramorant.getTag(BattlerTagType.GULP_MISSILE_PIKACHU)).toBeDefined(); @@ -193,7 +194,7 @@ describe("Abilities - Gulp Missile", () => { const cramorant = game.scene.getPlayerPokemon()!; - game.move.select(Moves.DIVE); + game.doAttack(getMovePosition(game.scene, 0, Moves.DIVE)); await game.phaseInterceptor.to(BerryPhase, false); expect(cramorant.getTag(BattlerTagType.GULP_MISSILE_ARROKUDA)).toBeDefined(); @@ -209,7 +210,7 @@ describe("Abilities - Gulp Missile", () => { vi.spyOn(cramorant, "getHpRatio").mockReturnValue(.55); - game.move.select(Moves.SURF); + game.doAttack(getMovePosition(game.scene, 0, Moves.SURF)); await game.phaseInterceptor.to(MoveEndPhase); const enemyHpPreEffect = enemy.hp; @@ -231,7 +232,7 @@ describe("Abilities - Gulp Missile", () => { const cramorant = game.scene.getPlayerPokemon()!; vi.spyOn(cramorant, "getHpRatio").mockReturnValue(.55); - game.move.select(Moves.SURF); + game.doAttack(getMovePosition(game.scene, 0, Moves.SURF)); await game.phaseInterceptor.to(MoveEndPhase); expect(cramorant.getTag(BattlerTagType.GULP_MISSILE_ARROKUDA)).toBeDefined(); @@ -251,7 +252,7 @@ describe("Abilities - Gulp Missile", () => { const cramorant = game.scene.getPlayerPokemon()!; vi.spyOn(cramorant, "getHpRatio").mockReturnValue(.55); - game.move.select(Moves.SURF); + game.doAttack(getMovePosition(game.scene, 0, Moves.SURF)); await game.phaseInterceptor.to(MoveEndPhase); expect(cramorant.getTag(BattlerTagType.GULP_MISSILE_ARROKUDA)).toBeDefined(); @@ -268,7 +269,7 @@ describe("Abilities - Gulp Missile", () => { game.override.enemyAbility(Abilities.TRACE); await game.startBattle([Species.CRAMORANT]); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnStartPhase); expect(game.scene.getEnemyPokemon()?.hasAbility(Abilities.GULP_MISSILE)).toBe(false); diff --git a/src/test/abilities/heatproof.test.ts b/src/test/abilities/heatproof.test.ts index e2a558e6d99..64a45c5023f 100644 --- a/src/test/abilities/heatproof.test.ts +++ b/src/test/abilities/heatproof.test.ts @@ -1,13 +1,13 @@ -import { Species } from "#app/enums/species"; -import { StatusEffect } from "#app/enums/status-effect"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { toDmgValue } from "#app/utils"; +import { Species } from "#app/enums/species.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { StatusEffect } from "#app/enums/status-effect.js"; describe("Abilities - Heatproof", () => { let phaserGame: Phaser.Game; @@ -45,14 +45,14 @@ describe("Abilities - Heatproof", () => { const initialHP = 1000; enemy.hp = initialHP; - game.move.select(Moves.FLAMETHROWER); + game.doAttack(getMovePosition(game.scene, 0, Moves.FLAMETHROWER)); await game.phaseInterceptor.to(TurnEndPhase); const heatproofDamage = initialHP - enemy.hp; enemy.hp = initialHP; game.override.enemyAbility(Abilities.BALL_FETCH); - game.move.select(Moves.FLAMETHROWER); + game.doAttack(getMovePosition(game.scene, 0, Moves.FLAMETHROWER)); await game.phaseInterceptor.to(TurnEndPhase); const regularDamage = initialHP - enemy.hp; @@ -68,10 +68,10 @@ describe("Abilities - Heatproof", () => { const enemy = game.scene.getEnemyPokemon()!; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.toNextTurn(); // Normal burn damage is /16 - expect(enemy.hp).toBe(enemy.getMaxHp() - toDmgValue(enemy.getMaxHp() / 32)); + expect(enemy.hp).toBe(enemy.getMaxHp() - Math.floor(enemy.getMaxHp() / 32)); }); }); diff --git a/src/test/abilities/hustle.test.ts b/src/test/abilities/hustle.test.ts index b7c3b723c4b..8f5547a5518 100644 --- a/src/test/abilities/hustle.test.ts +++ b/src/test/abilities/hustle.test.ts @@ -1,14 +1,15 @@ -import { allMoves } from "#app/data/move"; -import { Abilities } from "#app/enums/abilities"; -import { Stat } from "#app/enums/stat"; -import { DamagePhase } from "#app/phases/damage-phase"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import { allMoves } from "#app/data/move.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { Stat } from "#app/enums/stat.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { DamagePhase } from "#app/phases/damage-phase.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; describe("Abilities - Hustle", () => { let phaserGame: Phaser.Game; @@ -43,7 +44,7 @@ describe("Abilities - Hustle", () => { vi.spyOn(pikachu, "getBattleStat"); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.move.forceHit(); await game.phaseInterceptor.to(DamagePhase); @@ -56,7 +57,7 @@ describe("Abilities - Hustle", () => { vi.spyOn(pikachu, "getAccuracyMultiplier"); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(MoveEffectPhase); expect(pikachu.getAccuracyMultiplier).toHaveReturnedWith(0.8); @@ -70,7 +71,7 @@ describe("Abilities - Hustle", () => { vi.spyOn(pikachu, "getBattleStat"); vi.spyOn(pikachu, "getAccuracyMultiplier"); - game.move.select(Moves.GIGA_DRAIN); + game.doAttack(getMovePosition(game.scene, 0, Moves.GIGA_DRAIN)); await game.phaseInterceptor.to(DamagePhase); expect(pikachu.getBattleStat).toHaveReturnedWith(spatk); @@ -88,7 +89,7 @@ describe("Abilities - Hustle", () => { vi.spyOn(pikachu, "getAccuracyMultiplier"); vi.spyOn(allMoves[Moves.FISSURE], "calculateBattleAccuracy"); - game.move.select(Moves.FISSURE); + game.doAttack(getMovePosition(game.scene, 0, Moves.FISSURE)); await game.phaseInterceptor.to(DamagePhase); expect(enemyPokemon.turnData.damageTaken).toBe(enemyPokemon.getMaxHp()); diff --git a/src/test/abilities/hyper_cutter.test.ts b/src/test/abilities/hyper_cutter.test.ts index 28fcc2f6085..9637a80ddb4 100644 --- a/src/test/abilities/hyper_cutter.test.ts +++ b/src/test/abilities/hyper_cutter.test.ts @@ -3,6 +3,7 @@ import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -39,16 +40,16 @@ describe("Abilities - Hyper Cutter", () => { const enemy = game.scene.getEnemyPokemon()!; - game.move.select(Moves.OCTOLOCK); + game.doAttack(getMovePosition(game.scene, 0, Moves.OCTOLOCK)); await game.toNextTurn(); - game.move.select(Moves.DEFOG); + game.doAttack(getMovePosition(game.scene, 0, Moves.DEFOG)); await game.toNextTurn(); - game.move.select(Moves.NOBLE_ROAR); + game.doAttack(getMovePosition(game.scene, 0, Moves.NOBLE_ROAR)); await game.toNextTurn(); - game.move.select(Moves.SAND_ATTACK); + game.doAttack(getMovePosition(game.scene, 0, Moves.SAND_ATTACK)); await game.toNextTurn(); game.override.moveset([Moves.STRING_SHOT]); - game.move.select(Moves.STRING_SHOT); + game.doAttack(getMovePosition(game.scene, 0, Moves.STRING_SHOT)); await game.toNextTurn(); expect(enemy.summonData.battleStats[BattleStat.ATK]).toEqual(0); diff --git a/src/test/abilities/ice_face.test.ts b/src/test/abilities/ice_face.test.ts index fbc660c27c2..905e0dfdaf7 100644 --- a/src/test/abilities/ice_face.test.ts +++ b/src/test/abilities/ice_face.test.ts @@ -1,15 +1,16 @@ -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { BattlerTagType } from "#enums/battler-tag-type"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; describe("Abilities - Ice Face", () => { let phaserGame: Phaser.Game; @@ -38,7 +39,7 @@ describe("Abilities - Ice Face", () => { it("takes no damage from physical move and transforms to Noice", async () => { await game.startBattle([Species.HITMONLEE]); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(MoveEndPhase); @@ -54,7 +55,7 @@ describe("Abilities - Ice Face", () => { game.override.enemyLevel(1); await game.startBattle([Species.HITMONLEE]); - game.move.select(Moves.SURGING_STRIKES); + game.doAttack(getMovePosition(game.scene, 0, Moves.SURGING_STRIKES)); const eiscue = game.scene.getEnemyPokemon()!; expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBeDefined(); @@ -80,7 +81,7 @@ describe("Abilities - Ice Face", () => { it("takes damage from special moves", async () => { await game.startBattle([Species.MAGIKARP]); - game.move.select(Moves.ICE_BEAM); + game.doAttack(getMovePosition(game.scene, 0, Moves.ICE_BEAM)); await game.phaseInterceptor.to(MoveEndPhase); @@ -94,7 +95,7 @@ describe("Abilities - Ice Face", () => { it("takes effects from status moves", async () => { await game.startBattle([Species.MAGIKARP]); - game.move.select(Moves.TOXIC_THREAD); + game.doAttack(getMovePosition(game.scene, 0, Moves.TOXIC_THREAD)); await game.phaseInterceptor.to(MoveEndPhase); @@ -110,7 +111,7 @@ describe("Abilities - Ice Face", () => { await game.startBattle([Species.MAGIKARP]); - game.move.select(Moves.QUICK_ATTACK); + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK)); await game.phaseInterceptor.to(MoveEndPhase); @@ -132,7 +133,7 @@ describe("Abilities - Ice Face", () => { await game.startBattle([Species.EISCUE, Species.NINJASK]); - game.move.select(Moves.SNOWSCAPE); + game.doAttack(getMovePosition(game.scene, 0, Moves.SNOWSCAPE)); await game.phaseInterceptor.to(TurnEndPhase); let eiscue = game.scene.getPlayerPokemon()!; @@ -159,7 +160,7 @@ describe("Abilities - Ice Face", () => { await game.startBattle([Species.EISCUE]); - game.move.select(Moves.HAIL); + game.doAttack(getMovePosition(game.scene, 0, Moves.HAIL)); const eiscue = game.scene.getPlayerPokemon()!; await game.phaseInterceptor.to(QuietFormChangePhase); @@ -178,7 +179,7 @@ describe("Abilities - Ice Face", () => { await game.startBattle([Species.EISCUE, Species.MAGIKARP]); - game.move.select(Moves.ICE_BEAM); + game.doAttack(getMovePosition(game.scene, 0, Moves.ICE_BEAM)); await game.phaseInterceptor.to(TurnEndPhase); let eiscue = game.scene.getPlayerPokemon()!; @@ -212,7 +213,7 @@ describe("Abilities - Ice Face", () => { expect(eiscue.formIndex).toBe(noiceForm); expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBeUndefined(); - game.move.select(Moves.ICE_BEAM); + game.doAttack(getMovePosition(game.scene, 0, Moves.ICE_BEAM)); await game.doKillOpponents(); await game.phaseInterceptor.to(TurnEndPhase); game.doSelectModifier(); @@ -227,7 +228,7 @@ describe("Abilities - Ice Face", () => { await game.startBattle([Species.MAGIKARP]); - game.move.select(Moves.GASTRO_ACID); + game.doAttack(getMovePosition(game.scene, 0, Moves.GASTRO_ACID)); await game.phaseInterceptor.to(TurnEndPhase); @@ -243,7 +244,7 @@ describe("Abilities - Ice Face", () => { await game.startBattle([Species.MAGIKARP]); - game.move.select(Moves.SKILL_SWAP); + game.doAttack(getMovePosition(game.scene, 0, Moves.SKILL_SWAP)); await game.phaseInterceptor.to(TurnEndPhase); @@ -259,7 +260,7 @@ describe("Abilities - Ice Face", () => { await game.startBattle([Species.MAGIKARP]); - game.move.select(Moves.SIMPLE_BEAM); + game.doAttack(getMovePosition(game.scene, 0, Moves.SIMPLE_BEAM)); await game.phaseInterceptor.to(TurnInitPhase); diff --git a/src/test/abilities/intimidate.test.ts b/src/test/abilities/intimidate.test.ts index 93b663d06da..842b33108a3 100644 --- a/src/test/abilities/intimidate.test.ts +++ b/src/test/abilities/intimidate.test.ts @@ -1,21 +1,22 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { Mode } from "#app/ui/ui"; import { BattleStat } from "#app/data/battle-stat"; +import { generateStarter, getMovePosition } from "#test/utils/gameManagerUtils"; +import { Command } from "#app/ui/command-ui-handler"; import { Status, StatusEffect } from "#app/data/status-effect"; import { GameModes, getGameMode } from "#app/game-mode"; -import { CommandPhase } from "#app/phases/command-phase"; -import { DamagePhase } from "#app/phases/damage-phase"; -import { EncounterPhase } from "#app/phases/encounter-phase"; -import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; -import { SelectStarterPhase } from "#app/phases/select-starter-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; -import { Mode } from "#app/ui/ui"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { generateStarter } from "#test/utils/gameManagerUtils"; import { SPLASH_ONLY } from "#test/utils/testUtils"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { DamagePhase } from "#app/phases/damage-phase.js"; +import { EncounterPhase } from "#app/phases/encounter-phase.js"; +import { EnemyCommandPhase } from "#app/phases/enemy-command-phase.js"; +import { SelectStarterPhase } from "#app/phases/select-starter-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; describe("Abilities - Intimidate", () => { let phaserGame: Phaser.Game; @@ -216,7 +217,13 @@ describe("Abilities - Intimidate", () => { let battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; expect(battleStatsPokemon[BattleStat.ATK]).toBe(-1); - game.move.select(Moves.AERIAL_ACE); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.AERIAL_ACE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(DamagePhase); await game.killPokemon(game.scene.currentBattle.enemyParty[0]); expect(game.scene.currentBattle.enemyParty[0].isFainted()).toBe(true); @@ -236,7 +243,13 @@ describe("Abilities - Intimidate", () => { let battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; expect(battleStatsPokemon[BattleStat.ATK]).toBe(-1); - game.move.select(Moves.AERIAL_ACE); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.AERIAL_ACE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); console.log("===to new turn==="); await game.toNextTurn(); battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; @@ -255,7 +268,13 @@ describe("Abilities - Intimidate", () => { let battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; expect(battleStatsPokemon[BattleStat.ATK]).toBe(-1); - game.move.select(Moves.AERIAL_ACE); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.AERIAL_ACE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); console.log("===to new turn==="); await game.toNextTurn(); battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; @@ -263,7 +282,13 @@ describe("Abilities - Intimidate", () => { battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats; expect(battleStatsOpponent[BattleStat.ATK]).toBe(0); - game.move.select(Moves.AERIAL_ACE); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.AERIAL_ACE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); console.log("===to new turn==="); await game.toNextTurn(); battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; @@ -282,7 +307,13 @@ describe("Abilities - Intimidate", () => { let battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; expect(battleStatsPokemon[BattleStat.ATK]).toBe(-1); - game.move.select(Moves.AERIAL_ACE); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.AERIAL_ACE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); console.log("===to new turn==="); await game.toNextTurn(); battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; @@ -290,7 +321,13 @@ describe("Abilities - Intimidate", () => { battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats; expect(battleStatsOpponent[BattleStat.ATK]).toBe(-1); - game.move.select(Moves.AERIAL_ACE); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.AERIAL_ACE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); console.log("===to new turn==="); await game.toNextTurn(); battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; diff --git a/src/test/abilities/intrepid_sword.test.ts b/src/test/abilities/intrepid_sword.test.ts index 18d6c04adbc..c1c05b59997 100644 --- a/src/test/abilities/intrepid_sword.test.ts +++ b/src/test/abilities/intrepid_sword.test.ts @@ -1,10 +1,10 @@ import { BattleStat } from "#app/data/battle-stat"; -import { CommandPhase } from "#app/phases/command-phase"; +import GameManager from "#test/utils/gameManager"; import { Abilities } from "#enums/abilities"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { CommandPhase } from "#app/phases/command-phase.js"; describe("Abilities - Intrepid Sword", () => { diff --git a/src/test/abilities/libero.test.ts b/src/test/abilities/libero.test.ts index 16597e90285..d35cb8b6e2d 100644 --- a/src/test/abilities/libero.test.ts +++ b/src/test/abilities/libero.test.ts @@ -1,17 +1,18 @@ -import { allMoves } from "#app/data/move"; -import { Type } from "#app/data/type"; -import { Weather, WeatherType } from "#app/data/weather"; -import { PlayerPokemon } from "#app/field/pokemon"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { allMoves } from "#app/data/move.js"; +import { Type } from "#app/data/type.js"; +import { Weather, WeatherType } from "#app/data/weather.js"; +import { PlayerPokemon } from "#app/field/pokemon.js"; import { Abilities } from "#enums/abilities"; import { BattlerTagType } from "#enums/battler-tag-type"; import { Biome } from "#enums/biome"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -48,7 +49,7 @@ describe("Abilities - Libero", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.SPLASH); @@ -66,12 +67,12 @@ describe("Abilities - Libero", () => { let leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.SPLASH); - game.move.select(Moves.AGILITY); + game.doAttack(getMovePosition(game.scene, 0, Moves.AGILITY)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied.filter((a) => a === Abilities.LIBERO)).toHaveLength(1); @@ -88,7 +89,7 @@ describe("Abilities - Libero", () => { leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.SPLASH); @@ -107,7 +108,7 @@ describe("Abilities - Libero", () => { expect(leadPokemon).not.toBe(undefined); game.scene.arena.weather = new Weather(WeatherType.SUNNY); - game.move.select(Moves.WEATHER_BALL); + game.doAttack(getMovePosition(game.scene, 0, Moves.WEATHER_BALL)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied).toContain(Abilities.LIBERO); @@ -130,7 +131,7 @@ describe("Abilities - Libero", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied).toContain(Abilities.LIBERO); @@ -153,7 +154,7 @@ describe("Abilities - Libero", () => { expect(leadPokemon).not.toBe(undefined); game.scene.arena.biomeType = Biome.MOUNTAIN; - game.move.select(Moves.NATURE_POWER); + game.doAttack(getMovePosition(game.scene, 0, Moves.NATURE_POWER)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.AIR_SLASH); @@ -171,7 +172,7 @@ describe("Abilities - Libero", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.DIG); + game.doAttack(getMovePosition(game.scene, 0, Moves.DIG)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.DIG); @@ -190,7 +191,7 @@ describe("Abilities - Libero", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.move.forceMiss(); await game.phaseInterceptor.to(TurnEndPhase); @@ -212,7 +213,7 @@ describe("Abilities - Libero", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TACKLE); @@ -231,7 +232,7 @@ describe("Abilities - Libero", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TACKLE); @@ -250,7 +251,7 @@ describe("Abilities - Libero", () => { expect(leadPokemon).not.toBe(undefined); leadPokemon.summonData.types = [allMoves[Moves.SPLASH].defaultType]; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.LIBERO); @@ -270,7 +271,7 @@ describe("Abilities - Libero", () => { vi.spyOn(leadPokemon, "isTerastallized").mockReturnValue(true); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.LIBERO); @@ -288,7 +289,7 @@ describe("Abilities - Libero", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.STRUGGLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.STRUGGLE)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.LIBERO); @@ -306,7 +307,7 @@ describe("Abilities - Libero", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.BURN_UP); + game.doAttack(getMovePosition(game.scene, 0, Moves.BURN_UP)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.LIBERO); @@ -325,7 +326,7 @@ describe("Abilities - Libero", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.TRICK_OR_TREAT); + game.doAttack(getMovePosition(game.scene, 0, Moves.TRICK_OR_TREAT)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TRICK_OR_TREAT); @@ -343,7 +344,7 @@ describe("Abilities - Libero", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.CURSE); + game.doAttack(getMovePosition(game.scene, 0, Moves.CURSE)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.CURSE); diff --git a/src/test/abilities/magic_guard.test.ts b/src/test/abilities/magic_guard.test.ts index 64c1746c7d9..c7404f83a54 100644 --- a/src/test/abilities/magic_guard.test.ts +++ b/src/test/abilities/magic_guard.test.ts @@ -1,16 +1,17 @@ -import { ArenaTagSide, getArenaTag } from "#app/data/arena-tag"; -import { StatusEffect, getStatusEffectCatchRateMultiplier } from "#app/data/status-effect"; -import { WeatherType } from "#app/data/weather"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -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 { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { Species } from "#enums/species"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import { Moves } from "#enums/moves"; +import { ArenaTagType } from "#enums/arena-tag-type"; +import { ArenaTagSide, getArenaTag } from "#app/data/arena-tag"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Abilities } from "#enums/abilities"; +import { WeatherType } from "#app/data/weather.js"; +import { StatusEffect, getStatusEffectCatchRateMultiplier } from "#app/data/status-effect"; +import { BattlerTagType } from "#enums/battler-tag-type"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; const TIMEOUT = 20 * 1000; // 20 sec timeout @@ -57,7 +58,7 @@ describe("Abilities - Magic Guard", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).toBeDefined(); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); @@ -81,7 +82,7 @@ describe("Abilities - Magic Guard", () => { const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); @@ -98,14 +99,14 @@ describe("Abilities - Magic Guard", () => { it( "ability effect should not persist when the ability is replaced", async () => { - game.override.enemyMoveset([Moves.WORRY_SEED, Moves.WORRY_SEED, Moves.WORRY_SEED, Moves.WORRY_SEED]); + game.override.enemyMoveset([Moves.WORRY_SEED,Moves.WORRY_SEED,Moves.WORRY_SEED,Moves.WORRY_SEED]); game.override.statusEffect(StatusEffect.POISON); await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); @@ -125,7 +126,7 @@ describe("Abilities - Magic Guard", () => { await game.startBattle([Species.MAGIKARP]); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -149,7 +150,7 @@ describe("Abilities - Magic Guard", () => { await game.startBattle([Species.MAGIKARP]); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -179,7 +180,7 @@ describe("Abilities - Magic Guard", () => { await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -205,7 +206,7 @@ describe("Abilities - Magic Guard", () => { await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -232,7 +233,7 @@ describe("Abilities - Magic Guard", () => { const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.CURSE); + game.doAttack(getMovePosition(game.scene, 0, Moves.CURSE)); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -256,7 +257,7 @@ describe("Abilities - Magic Guard", () => { const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.HIGH_JUMP_KICK); + game.doAttack(getMovePosition(game.scene, 0, Moves.HIGH_JUMP_KICK)); await game.move.forceMiss(); await game.phaseInterceptor.to(TurnEndPhase); @@ -275,7 +276,7 @@ describe("Abilities - Magic Guard", () => { const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.TAKE_DOWN); + game.doAttack(getMovePosition(game.scene, 0, Moves.TAKE_DOWN)); await game.phaseInterceptor.to(TurnEndPhase); @@ -293,7 +294,7 @@ describe("Abilities - Magic Guard", () => { const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.STRUGGLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.STRUGGLE)); await game.phaseInterceptor.to(TurnEndPhase); @@ -312,7 +313,7 @@ describe("Abilities - Magic Guard", () => { const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.STEEL_BEAM); + game.doAttack(getMovePosition(game.scene, 0, Moves.STEEL_BEAM)); await game.phaseInterceptor.to(TurnEndPhase); @@ -328,7 +329,7 @@ describe("Abilities - Magic Guard", () => { it("Magic Guard does not prevent self-damage from confusion", async () => { await game.startBattle([Species.MAGIKARP]); - game.move.select(Moves.CHARM); + game.doAttack(getMovePosition(game.scene, 0, Moves.CHARM)); await game.phaseInterceptor.to(TurnEndPhase); }); @@ -340,7 +341,7 @@ describe("Abilities - Magic Guard", () => { const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.BELLY_DRUM); + game.doAttack(getMovePosition(game.scene, 0, Moves.BELLY_DRUM)); await game.phaseInterceptor.to(TurnEndPhase); @@ -352,7 +353,7 @@ describe("Abilities - Magic Guard", () => { }, TIMEOUT ); - it("Magic Guard prevents damage from abilities with PostTurnHurtIfSleepingAbAttr", async () => { + it("Magic Guard prevents damage from abilities with PostTurnHurtIfSleepingAbAttr", async() => { //Tests the ability Bad Dreams game.override.statusEffect(StatusEffect.SLEEP); //enemy pokemon is given Spore just in case player pokemon somehow awakens during test @@ -363,7 +364,7 @@ describe("Abilities - Magic Guard", () => { const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); @@ -377,7 +378,7 @@ describe("Abilities - Magic Guard", () => { }, TIMEOUT ); - it("Magic Guard prevents damage from abilities with PostFaintContactDamageAbAttr", async () => { + it("Magic Guard prevents damage from abilities with PostFaintContactDamageAbAttr", async() => { //Tests the abilities Innards Out/Aftermath game.override.moveset([Moves.TACKLE]); game.override.enemyAbility(Abilities.AFTERMATH); @@ -389,7 +390,7 @@ describe("Abilities - Magic Guard", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; enemyPokemon.hp = 1; - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(TurnEndPhase); /** @@ -402,7 +403,7 @@ describe("Abilities - Magic Guard", () => { }, TIMEOUT ); - it("Magic Guard prevents damage from abilities with PostDefendContactDamageAbAttr", async () => { + it("Magic Guard prevents damage from abilities with PostDefendContactDamageAbAttr", async() => { //Tests the abilities Iron Barbs/Rough Skin game.override.moveset([Moves.TACKLE]); game.override.enemyAbility(Abilities.IRON_BARBS); @@ -413,7 +414,7 @@ describe("Abilities - Magic Guard", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(TurnEndPhase); /** @@ -426,7 +427,7 @@ describe("Abilities - Magic Guard", () => { }, TIMEOUT ); - it("Magic Guard prevents damage from abilities with ReverseDrainAbAttr", async () => { + it("Magic Guard prevents damage from abilities with ReverseDrainAbAttr", async() => { //Tests the ability Liquid Ooze game.override.moveset([Moves.ABSORB]); game.override.enemyAbility(Abilities.LIQUID_OOZE); @@ -437,7 +438,7 @@ describe("Abilities - Magic Guard", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.ABSORB); + game.doAttack(getMovePosition(game.scene, 0, Moves.ABSORB)); await game.phaseInterceptor.to(TurnEndPhase); /** @@ -450,14 +451,14 @@ describe("Abilities - Magic Guard", () => { }, TIMEOUT ); - it("Magic Guard prevents HP loss from abilities with PostWeatherLapseDamageAbAttr", async () => { + it("Magic Guard prevents HP loss from abilities with PostWeatherLapseDamageAbAttr", async() => { //Tests the abilities Solar Power/Dry Skin game.override.passiveAbility(Abilities.SOLAR_POWER); game.override.weather(WeatherType.SUNNY); await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); /** diff --git a/src/test/abilities/moxie.test.ts b/src/test/abilities/moxie.test.ts index 6a1838c9a98..6550dcab526 100644 --- a/src/test/abilities/moxie.test.ts +++ b/src/test/abilities/moxie.test.ts @@ -1,13 +1,17 @@ import { BattleStat } from "#app/data/battle-stat"; import { Stat } from "#app/data/pokemon-stat"; -import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; -import { VictoryPhase } from "#app/phases/victory-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Command } from "#app/ui/command-ui-handler"; +import { Mode } from "#app/ui/ui"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { EnemyCommandPhase } from "#app/phases/enemy-command-phase.js"; +import { VictoryPhase } from "#app/phases/victory-phase.js"; describe("Abilities - Moxie", () => { @@ -33,10 +37,10 @@ describe("Abilities - Moxie", () => { game.override.ability(Abilities.MOXIE); game.override.startingLevel(2000); game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); - it("MOXIE", async () => { + it("MOXIE", async() => { const moveToUse = Moves.AERIAL_ACE; await game.startBattle([ Species.MIGHTYENA, @@ -46,7 +50,13 @@ describe("Abilities - Moxie", () => { let battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; expect(battleStatsPokemon[Stat.ATK]).toBe(0); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(VictoryPhase); battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; expect(battleStatsPokemon[BattleStat.ATK]).toBe(1); diff --git a/src/test/abilities/mycelium_might.test.ts b/src/test/abilities/mycelium_might.test.ts index 83396f7950f..2fcdc28b279 100644 --- a/src/test/abilities/mycelium_might.test.ts +++ b/src/test/abilities/mycelium_might.test.ts @@ -1,10 +1,11 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { MovePhase } from "#app/phases/move-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { MovePhase } from "#app/phases/move-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; +import { BattleStat } from "#app/data/battle-stat"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -41,14 +42,14 @@ describe("Abilities - Mycelium Might", () => { * https://www.smogon.com/forums/threads/scarlet-violet-battle-mechanics-research.3709545/page-24 **/ - it("will move last in its priority bracket and ignore protective abilities", async () => { - await game.startBattle([Species.REGIELEKI]); + it("If a Pokemon with Mycelium Might uses a status move, it will always move last but the status move will ignore protective abilities", async() => { + await game.startBattle([ Species.REGIELEKI ]); const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const enemyPokemon = game.scene.getEnemyPokemon(); const enemyIndex = enemyPokemon?.getBattlerIndex(); - game.move.select(Moves.BABY_DOLL_EYES); + game.doAttack(getMovePosition(game.scene, 0, Moves.BABY_DOLL_EYES)); await game.phaseInterceptor.to(MovePhase, false); // The opponent Pokemon (without Mycelium Might) goes first despite having lower speed than the player Pokemon. @@ -63,15 +64,15 @@ describe("Abilities - Mycelium Might", () => { expect(enemyPokemon?.summonData.battleStats[BattleStat.ATK]).toBe(-1); }, 20000); - it("will still go first if a status move that is in a higher priority bracket than the opponent's move is used", async () => { + it("Pokemon with Mycelium Might will go first if a status move that is in a higher priority bracket than the opponent's move is used", async() => { game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); - await game.startBattle([Species.REGIELEKI]); + await game.startBattle([ Species.REGIELEKI ]); const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const enemyPokemon = game.scene.getEnemyPokemon(); const enemyIndex = enemyPokemon?.getBattlerIndex(); - game.move.select(Moves.BABY_DOLL_EYES); + game.doAttack(getMovePosition(game.scene, 0, Moves.BABY_DOLL_EYES)); await game.phaseInterceptor.to(MovePhase, false); // The player Pokemon (with M.M.) goes first because its move is still within a higher priority bracket than its opponent. @@ -85,13 +86,13 @@ describe("Abilities - Mycelium Might", () => { expect(enemyPokemon?.summonData.battleStats[BattleStat.ATK]).toBe(-1); }, 20000); - it("will not affect non-status moves", async () => { - await game.startBattle([Species.REGIELEKI]); + it("Order is established normally if the Pokemon uses a non-status move", async() => { + await game.startBattle([ Species.REGIELEKI ]); const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); - game.move.select(Moves.QUICK_ATTACK); + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK)); await game.phaseInterceptor.to(MovePhase, false); // The player Pokemon (with M.M.) goes first because it has a higher speed and did not use a status move. diff --git a/src/test/abilities/parental_bond.test.ts b/src/test/abilities/parental_bond.test.ts index 1404f597ccf..ef0ad7785d2 100644 --- a/src/test/abilities/parental_bond.test.ts +++ b/src/test/abilities/parental_bond.test.ts @@ -1,21 +1,21 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { StatusEffect } from "#app/data/status-effect"; -import { Type } from "#app/data/type"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { CommandPhase } from "#app/phases/command-phase"; -import { DamagePhase } from "#app/phases/damage-phase"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { toDmgValue } from "#app/utils"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { StatusEffect } from "#app/data/status-effect.js"; +import { Type } from "#app/data/type.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { DamagePhase } from "#app/phases/damage-phase.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -60,7 +60,7 @@ describe("Abilities - Parental Bond", () => { let enemyStartingHp = enemyPokemon.hp; - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(MoveEffectPhase, false); @@ -73,7 +73,7 @@ describe("Abilities - Parental Bond", () => { const secondStrikeDamage = enemyStartingHp - enemyPokemon.hp; expect(leadPokemon.turnData.hitCount).toBe(2); - expect(secondStrikeDamage).toBe(toDmgValue(0.25 * firstStrikeDamage)); + expect(secondStrikeDamage).toBe(Math.ceil(0.25 * firstStrikeDamage)); }, TIMEOUT ); @@ -91,7 +91,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.POWER_UP_PUNCH); + game.doAttack(getMovePosition(game.scene, 0, Moves.POWER_UP_PUNCH)); await game.phaseInterceptor.to(BerryPhase, false); @@ -113,7 +113,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.BABY_DOLL_EYES); + game.doAttack(getMovePosition(game.scene, 0, Moves.BABY_DOLL_EYES)); await game.phaseInterceptor.to(BerryPhase, false); expect(enemyPokemon.summonData.battleStats[BattleStat.ATK]).toBe(-1); @@ -133,7 +133,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.DOUBLE_HIT); + game.doAttack(getMovePosition(game.scene, 0, Moves.DOUBLE_HIT)); await game.move.forceHit(); await game.phaseInterceptor.to(BerryPhase, false); @@ -155,7 +155,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.SELF_DESTRUCT); + game.doAttack(getMovePosition(game.scene, 0, Moves.SELF_DESTRUCT)); await game.phaseInterceptor.to(DamagePhase, false); @@ -176,7 +176,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.ROLLOUT); + game.doAttack(getMovePosition(game.scene, 0, Moves.ROLLOUT)); await game.move.forceHit(); await game.phaseInterceptor.to(DamagePhase, false); @@ -200,7 +200,7 @@ describe("Abilities - Parental Bond", () => { const enemyStartingHp = enemyPokemon.hp; - game.move.select(Moves.DRAGON_RAGE); + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_RAGE)); await game.phaseInterceptor.to(BerryPhase, false); expect(enemyPokemon.hp).toBe(enemyStartingHp - 80); @@ -211,7 +211,7 @@ describe("Abilities - Parental Bond", () => { "ability should not apply multiplier to counter moves", async () => { game.override.moveset([Moves.COUNTER]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); await game.startBattle([Species.CHARIZARD]); @@ -224,14 +224,14 @@ describe("Abilities - Parental Bond", () => { const playerStartingHp = leadPokemon.hp; const enemyStartingHp = enemyPokemon.hp; - game.move.select(Moves.COUNTER); + game.doAttack(getMovePosition(game.scene, 0, Moves.COUNTER)); await game.phaseInterceptor.to(DamagePhase); const playerDamage = playerStartingHp - leadPokemon.hp; await game.phaseInterceptor.to(BerryPhase, false); - expect(enemyPokemon.hp).toBe(enemyStartingHp - 4 * playerDamage); + expect(enemyPokemon.hp).toBe(enemyStartingHp - 4*playerDamage); }, TIMEOUT ); @@ -251,10 +251,10 @@ describe("Abilities - Parental Bond", () => { expect(enemyPokemon.length).toBe(2); enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); - game.move.select(Moves.EARTHQUAKE); + game.doAttack(getMovePosition(game.scene, 0, Moves.EARTHQUAKE)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.EARTHQUAKE, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.EARTHQUAKE)); await game.phaseInterceptor.to(BerryPhase, false); playerPokemon.forEach(p => expect(p.turnData.hitCount).toBe(1)); @@ -274,7 +274,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.EARTHQUAKE); + game.doAttack(getMovePosition(game.scene, 0, Moves.EARTHQUAKE)); await game.phaseInterceptor.to(DamagePhase, false); expect(leadPokemon.turnData.hitCount).toBe(2); @@ -294,7 +294,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.MIND_BLOWN); + game.doAttack(getMovePosition(game.scene, 0, Moves.MIND_BLOWN)); await game.phaseInterceptor.to(DamagePhase, false); @@ -303,7 +303,7 @@ describe("Abilities - Parental Bond", () => { // This test will time out if the user faints await game.phaseInterceptor.to(BerryPhase, false); - expect(leadPokemon.hp).toBe(toDmgValue(leadPokemon.getMaxHp() / 2)); + expect(leadPokemon.hp).toBe(Math.floor(leadPokemon.getMaxHp()/2)); }, TIMEOUT ); @@ -320,7 +320,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.BURN_UP); + game.doAttack(getMovePosition(game.scene, 0, Moves.BURN_UP)); await game.phaseInterceptor.to(DamagePhase); @@ -338,7 +338,7 @@ describe("Abilities - Parental Bond", () => { "Moves boosted by this ability and Multi-Lens should strike 4 times", async () => { game.override.moveset([Moves.TACKLE]); - game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]); + game.override.startingHeldItems([{name: "MULTI_LENS", count: 1}]); await game.startBattle([Species.CHARIZARD]); @@ -348,7 +348,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(DamagePhase); @@ -360,7 +360,7 @@ describe("Abilities - Parental Bond", () => { "Super Fang boosted by this ability and Multi-Lens should strike twice", async () => { game.override.moveset([Moves.SUPER_FANG]); - game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]); + game.override.startingHeldItems([{name: "MULTI_LENS", count: 1}]); await game.startBattle([Species.CHARIZARD]); @@ -372,7 +372,7 @@ describe("Abilities - Parental Bond", () => { const enemyStartingHp = enemyPokemon.hp; - game.move.select(Moves.SUPER_FANG); + game.doAttack(getMovePosition(game.scene, 0, Moves.SUPER_FANG)); await game.move.forceHit(); await game.phaseInterceptor.to(DamagePhase); @@ -389,7 +389,7 @@ describe("Abilities - Parental Bond", () => { "Seismic Toss boosted by this ability and Multi-Lens should strike twice", async () => { game.override.moveset([Moves.SEISMIC_TOSS]); - game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]); + game.override.startingHeldItems([{name: "MULTI_LENS", count: 1}]); await game.startBattle([Species.CHARIZARD]); @@ -401,7 +401,7 @@ describe("Abilities - Parental Bond", () => { const enemyStartingHp = enemyPokemon.hp; - game.move.select(Moves.SEISMIC_TOSS); + game.doAttack(getMovePosition(game.scene, 0, Moves.SEISMIC_TOSS)); await game.move.forceHit(); await game.phaseInterceptor.to(DamagePhase); @@ -427,7 +427,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.HYPER_BEAM); + game.doAttack(getMovePosition(game.scene, 0, Moves.HYPER_BEAM)); await game.move.forceHit(); await game.phaseInterceptor.to(DamagePhase); @@ -455,7 +455,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.ANCHOR_SHOT); + game.doAttack(getMovePosition(game.scene, 0, Moves.ANCHOR_SHOT)); await game.move.forceHit(); await game.phaseInterceptor.to(DamagePhase); @@ -485,7 +485,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.SMACK_DOWN); + game.doAttack(getMovePosition(game.scene, 0, Moves.SMACK_DOWN)); await game.move.forceHit(); await game.phaseInterceptor.to(DamagePhase); @@ -512,7 +512,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.U_TURN); + game.doAttack(getMovePosition(game.scene, 0, Moves.U_TURN)); await game.move.forceHit(); await game.phaseInterceptor.to(MoveEffectPhase); @@ -536,7 +536,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.WAKE_UP_SLAP); + game.doAttack(getMovePosition(game.scene, 0, Moves.WAKE_UP_SLAP)); await game.move.forceHit(); await game.phaseInterceptor.to(DamagePhase); @@ -554,7 +554,7 @@ describe("Abilities - Parental Bond", () => { "ability should not cause user to hit into King's Shield more than once", async () => { game.override.moveset([Moves.TACKLE]); - game.override.enemyMoveset([Moves.KINGS_SHIELD, Moves.KINGS_SHIELD, Moves.KINGS_SHIELD, Moves.KINGS_SHIELD]); + game.override.enemyMoveset([Moves.KINGS_SHIELD,Moves.KINGS_SHIELD,Moves.KINGS_SHIELD,Moves.KINGS_SHIELD]); await game.startBattle([Species.CHARIZARD]); @@ -564,7 +564,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(BerryPhase, false); @@ -586,7 +586,7 @@ describe("Abilities - Parental Bond", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).not.toBe(undefined); - game.move.select(Moves.WATER_GUN); + game.doAttack(getMovePosition(game.scene, 0, Moves.WATER_GUN)); await game.phaseInterceptor.to(BerryPhase, false); @@ -599,7 +599,7 @@ describe("Abilities - Parental Bond", () => { async () => { game.override.battleType("double"); game.override.moveset([Moves.EARTHQUAKE, Moves.SPLASH]); - game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]); + game.override.startingHeldItems([{name: "MULTI_LENS", count: 1}]); await game.startBattle([Species.CHARIZARD, Species.PIDGEOT]); @@ -613,10 +613,10 @@ describe("Abilities - Parental Bond", () => { const enemyStartingHp = enemyPokemon.map(p => p.hp); - game.move.select(Moves.EARTHQUAKE); + game.doAttack(getMovePosition(game.scene, 0, Moves.EARTHQUAKE)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(MoveEffectPhase, false); @@ -625,7 +625,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to(BerryPhase, false); - enemyPokemon.forEach((p, i) => expect(enemyStartingHp[i] - p.hp).toBe(2 * enemyFirstHitDamage[i])); + enemyPokemon.forEach((p, i) => expect(enemyStartingHp[i] - p.hp).toBe(2*enemyFirstHitDamage[i])); }, TIMEOUT ); diff --git a/src/test/abilities/pastel_veil.test.ts b/src/test/abilities/pastel_veil.test.ts index ba90c7e3b3f..cb6be666d5f 100644 --- a/src/test/abilities/pastel_veil.test.ts +++ b/src/test/abilities/pastel_veil.test.ts @@ -1,14 +1,15 @@ -import { BattlerIndex } from "#app/battle"; -import { StatusEffect } from "#app/data/status-effect"; -import { Abilities } from "#app/enums/abilities"; -import { CommandPhase } from "#app/phases/command-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { Moves } from "#enums/moves"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -import { SPLASH_ONLY } from "../utils/testUtils"; +import GameManager from "#test/utils/gameManager"; +import { Species } from "#enums/species"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { StatusEffect } from "#app/data/status-effect.js"; +import { allAbilities } from "#app/data/ability.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { BattlerIndex } from "#app/battle.js"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Abilities - Pastel Veil", () => { let phaserGame: Phaser.Game; @@ -26,49 +27,50 @@ describe("Abilities - Pastel Veil", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override - .battleType("double") - .moveset([Moves.TOXIC_THREAD, Moves.SPLASH]) - .enemyAbility(Abilities.BALL_FETCH) - .enemySpecies(Species.SUNKERN) - .enemyMoveset(SPLASH_ONLY); + game.override.battleType("double"); + game.override.moveset([Moves.SPLASH]); + game.override.enemyAbility(Abilities.BALL_FETCH); + game.override.enemySpecies(Species.MAGIKARP); + game.override.enemyMoveset([Moves.TOXIC_THREAD, Moves.TOXIC_THREAD, Moves.TOXIC_THREAD, Moves.TOXIC_THREAD]); }); it("prevents the user and its allies from being afflicted by poison", async () => { - await game.startBattle([Species.MAGIKARP, Species.GALAR_PONYTA]); - const ponyta = game.scene.getPlayerField()[1]; - const magikarp = game.scene.getPlayerField()[0]; - ponyta.abilityIndex = 1; + await game.startBattle([Species.GALAR_PONYTA, Species.MAGIKARP]); + const ponyta = game.scene.getPlayerField()[0]; + + vi.spyOn(ponyta, "getAbility").mockReturnValue(allAbilities[Abilities.PASTEL_VEIL]); expect(ponyta.hasAbility(Abilities.PASTEL_VEIL)).toBe(true); - game.move.select(Moves.SPLASH); - game.move.select(Moves.TOXIC_THREAD, 1, BattlerIndex.PLAYER); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); - expect(magikarp.status?.effect).toBeUndefined(); + expect(game.scene.getPlayerField().every(p => p.status?.effect)).toBe(false); }); it("it heals the poisoned status condition of allies if user is sent out into battle", async () => { - await game.startBattle([Species.MAGIKARP, Species.FEEBAS, Species.GALAR_PONYTA]); - const ponyta = game.scene.getParty()[2]; - const magikarp = game.scene.getPlayerField()[0]; - ponyta.abilityIndex = 1; + await game.startBattle([Species.MAGIKARP, Species.MAGIKARP, Species.GALAR_PONYTA]); + const ponyta = game.scene.getParty().find(p => p.species.speciesId === Species.GALAR_PONYTA)!; + + vi.spyOn(ponyta, "getAbility").mockReturnValue(allAbilities[Abilities.PASTEL_VEIL]); expect(ponyta.hasAbility(Abilities.PASTEL_VEIL)).toBe(true); - game.move.select(Moves.SPLASH); - game.move.select(Moves.TOXIC_THREAD, 1, BattlerIndex.PLAYER); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); - expect(magikarp.status?.effect).toBe(StatusEffect.POISON); + expect(game.scene.getPlayerField().some(p => p.status?.effect === StatusEffect.POISON)).toBe(true); + + const poisonedMon = game.scene.getPlayerField().find(p => p.status?.effect === StatusEffect.POISON); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, (poisonedMon!.getBattlerIndex() as BattlerIndex.PLAYER | BattlerIndex.PLAYER_2), Moves.SPLASH)); game.doSwitchPokemon(2); await game.phaseInterceptor.to(TurnEndPhase); - expect(magikarp.status?.effect).toBeUndefined(); + expect(game.scene.getPlayerField().every(p => p.status?.effect)).toBe(false); }); }); diff --git a/src/test/abilities/power_construct.test.ts b/src/test/abilities/power_construct.test.ts index ec37bc96c2f..e6a319d229f 100644 --- a/src/test/abilities/power_construct.test.ts +++ b/src/test/abilities/power_construct.test.ts @@ -1,10 +1,11 @@ -import { Status, StatusEffect } from "#app/data/status-effect"; -import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { Status, StatusEffect } from "#app/data/status-effect.js"; +import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; const TIMEOUT = 20 * 1000; @@ -52,7 +53,7 @@ describe("Abilities - POWER CONSTRUCT", () => { zygarde!.status = new Status(StatusEffect.FAINT); expect(zygarde!.isFainted()).toBe(true); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.doKillOpponents(); await game.phaseInterceptor.to(TurnEndPhase); game.doSelectModifier(); diff --git a/src/test/abilities/power_spot.test.ts b/src/test/abilities/power_spot.test.ts index b83284c0bac..467fc677ac0 100644 --- a/src/test/abilities/power_spot.test.ts +++ b/src/test/abilities/power_spot.test.ts @@ -1,13 +1,14 @@ -import { allMoves } from "#app/data/move"; -import { Abilities } from "#app/enums/abilities"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { allMoves } from "#app/data/move.js"; +import { Abilities } from "#app/enums/abilities.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Abilities - Power Spot", () => { let phaserGame: Phaser.Game; @@ -41,8 +42,8 @@ describe("Abilities - Power Spot", () => { vi.spyOn(moveToCheck, "calculateBattlePower"); await game.startBattle([Species.REGIELEKI, Species.STONJOURNER]); - game.move.select(Moves.DAZZLING_GLEAM); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.DAZZLING_GLEAM)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(basePower * powerSpotMultiplier); @@ -55,8 +56,8 @@ describe("Abilities - Power Spot", () => { vi.spyOn(moveToCheck, "calculateBattlePower"); await game.startBattle([Species.REGIELEKI, Species.STONJOURNER]); - game.move.select(Moves.BREAKING_SWIPE); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.BREAKING_SWIPE)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(basePower * powerSpotMultiplier); @@ -69,8 +70,8 @@ describe("Abilities - Power Spot", () => { vi.spyOn(moveToCheck, "calculateBattlePower"); await game.startBattle([Species.STONJOURNER, Species.REGIELEKI]); - game.move.select(Moves.BREAKING_SWIPE); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.BREAKING_SWIPE)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(basePower); diff --git a/src/test/abilities/protean.test.ts b/src/test/abilities/protean.test.ts index a7c6799132f..ed63613945a 100644 --- a/src/test/abilities/protean.test.ts +++ b/src/test/abilities/protean.test.ts @@ -1,17 +1,18 @@ -import { allMoves } from "#app/data/move"; -import { Type } from "#app/data/type"; -import { Weather, WeatherType } from "#app/data/weather"; -import { PlayerPokemon } from "#app/field/pokemon"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { allMoves } from "#app/data/move.js"; +import { Type } from "#app/data/type.js"; +import { Weather, WeatherType } from "#app/data/weather.js"; +import { PlayerPokemon } from "#app/field/pokemon.js"; import { Abilities } from "#enums/abilities"; import { BattlerTagType } from "#enums/battler-tag-type"; import { Biome } from "#enums/biome"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -48,7 +49,7 @@ describe("Abilities - Protean", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.SPLASH); @@ -66,12 +67,12 @@ describe("Abilities - Protean", () => { let leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.SPLASH); - game.move.select(Moves.AGILITY); + game.doAttack(getMovePosition(game.scene, 0, Moves.AGILITY)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied.filter((a) => a === Abilities.PROTEAN)).toHaveLength(1); @@ -88,7 +89,7 @@ describe("Abilities - Protean", () => { leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.SPLASH); @@ -107,7 +108,7 @@ describe("Abilities - Protean", () => { expect(leadPokemon).not.toBe(undefined); game.scene.arena.weather = new Weather(WeatherType.SUNNY); - game.move.select(Moves.WEATHER_BALL); + game.doAttack(getMovePosition(game.scene, 0, Moves.WEATHER_BALL)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied).toContain(Abilities.PROTEAN); @@ -130,7 +131,7 @@ describe("Abilities - Protean", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied).toContain(Abilities.PROTEAN); @@ -153,7 +154,7 @@ describe("Abilities - Protean", () => { expect(leadPokemon).not.toBe(undefined); game.scene.arena.biomeType = Biome.MOUNTAIN; - game.move.select(Moves.NATURE_POWER); + game.doAttack(getMovePosition(game.scene, 0, Moves.NATURE_POWER)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.AIR_SLASH); @@ -171,7 +172,7 @@ describe("Abilities - Protean", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.DIG); + game.doAttack(getMovePosition(game.scene, 0, Moves.DIG)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.DIG); @@ -190,7 +191,7 @@ describe("Abilities - Protean", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.move.forceMiss(); await game.phaseInterceptor.to(TurnEndPhase); @@ -212,7 +213,7 @@ describe("Abilities - Protean", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TACKLE); @@ -231,7 +232,7 @@ describe("Abilities - Protean", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TACKLE); @@ -250,7 +251,7 @@ describe("Abilities - Protean", () => { expect(leadPokemon).not.toBe(undefined); leadPokemon.summonData.types = [allMoves[Moves.SPLASH].defaultType]; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.PROTEAN); @@ -270,7 +271,7 @@ describe("Abilities - Protean", () => { vi.spyOn(leadPokemon, "isTerastallized").mockReturnValue(true); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.PROTEAN); @@ -288,7 +289,7 @@ describe("Abilities - Protean", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.STRUGGLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.STRUGGLE)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.PROTEAN); @@ -306,7 +307,7 @@ describe("Abilities - Protean", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.BURN_UP); + game.doAttack(getMovePosition(game.scene, 0, Moves.BURN_UP)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.PROTEAN); @@ -325,7 +326,7 @@ describe("Abilities - Protean", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.TRICK_OR_TREAT); + game.doAttack(getMovePosition(game.scene, 0, Moves.TRICK_OR_TREAT)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TRICK_OR_TREAT); @@ -343,7 +344,7 @@ describe("Abilities - Protean", () => { const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - game.move.select(Moves.CURSE); + game.doAttack(getMovePosition(game.scene, 0, Moves.CURSE)); await game.phaseInterceptor.to(TurnEndPhase); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.CURSE); diff --git a/src/test/abilities/quick_draw.test.ts b/src/test/abilities/quick_draw.test.ts index 00d344ed333..6e3416b0724 100644 --- a/src/test/abilities/quick_draw.test.ts +++ b/src/test/abilities/quick_draw.test.ts @@ -1,11 +1,12 @@ import { allAbilities, BypassSpeedChanceAbAttr } from "#app/data/ability"; -import { FaintPhase } from "#app/phases/faint-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; +import { FaintPhase } from "#app/phases/faint-phase.js"; describe("Abilities - Quick Draw", () => { let phaserGame: Phaser.Game; @@ -46,7 +47,7 @@ describe("Abilities - Quick Draw", () => { pokemon.hp = 1; enemy.hp = 1; - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(FaintPhase, false); expect(pokemon.isFainted()).toBe(false); @@ -66,7 +67,7 @@ describe("Abilities - Quick Draw", () => { pokemon.hp = 1; enemy.hp = 1; - game.move.select(Moves.TAIL_WHIP); + game.doAttack(getMovePosition(game.scene, 0, Moves.TAIL_WHIP)); await game.phaseInterceptor.to(FaintPhase, false); expect(pokemon.isFainted()).toBe(true); @@ -86,7 +87,7 @@ describe("Abilities - Quick Draw", () => { pokemon.hp = 1; enemy.hp = 1; - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(FaintPhase, false); expect(pokemon.isFainted()).toBe(true); diff --git a/src/test/abilities/sand_spit.test.ts b/src/test/abilities/sand_spit.test.ts index 041e20faf7f..59d311adb80 100644 --- a/src/test/abilities/sand_spit.test.ts +++ b/src/test/abilities/sand_spit.test.ts @@ -1,10 +1,11 @@ -import { WeatherType } from "#app/enums/weather-type"; +import GameManager from "#test/utils/gameManager"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { WeatherType } from "#app/enums/weather-type.js"; describe("Abilities - Sand Spit", () => { @@ -34,21 +35,21 @@ describe("Abilities - Sand Spit", () => { game.override.moveset([Moves.SPLASH, Moves.COIL]); }); - it("should trigger when hit with damaging move", async () => { + it("should trigger when hit with damaging move", async() => { game.override.enemyMoveset(Array(4).fill(Moves.TACKLE)); await game.startBattle(); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.toNextTurn(); expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SANDSTORM); }, 20000); - it("should not trigger when targetted with status moves", async () => { + it("should not trigger when targetted with status moves", async() => { game.override.enemyMoveset(Array(4).fill(Moves.GROWL)); await game.startBattle(); - game.move.select(Moves.COIL); + game.doAttack(getMovePosition(game.scene, 0, Moves.COIL)); await game.toNextTurn(); expect(game.scene.arena.weather?.weatherType).not.toBe(WeatherType.SANDSTORM); diff --git a/src/test/abilities/sand_veil.test.ts b/src/test/abilities/sand_veil.test.ts index 2336e2b50de..010878db68d 100644 --- a/src/test/abilities/sand_veil.test.ts +++ b/src/test/abilities/sand_veil.test.ts @@ -1,15 +1,16 @@ -import { BattleStatMultiplierAbAttr, allAbilities } from "#app/data/ability"; -import { BattleStat } from "#app/data/battle-stat"; -import { WeatherType } from "#app/data/weather"; -import { CommandPhase } from "#app/phases/command-phase"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; +import { BattleStatMultiplierAbAttr, allAbilities } from "#app/data/ability.js"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { WeatherType } from "#app/data/weather.js"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -51,7 +52,7 @@ describe("Abilities - Sand Veil", () => { const sandVeilAttr = allAbilities[Abilities.SAND_VEIL].getAttrs(BattleStatMultiplierAbAttr)[0]; vi.spyOn(sandVeilAttr, "applyBattleStat").mockImplementation( - (pokemon, passive, simulated, battleStat, statValue, args) => { + (pokemon, passive, battleStat, statValue, args) => { if (battleStat === BattleStat.EVA && game.scene.arena.weather?.weatherType === WeatherType.SANDSTORM) { statValue.value *= -1; // will make all attacks miss return true; @@ -63,11 +64,11 @@ describe("Abilities - Sand Veil", () => { expect(leadPokemon[0].hasAbility(Abilities.SAND_VEIL)).toBe(true); expect(leadPokemon[1].hasAbility(Abilities.SAND_VEIL)).toBe(false); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(MoveEffectPhase, false); diff --git a/src/test/abilities/sap_sipper.test.ts b/src/test/abilities/sap_sipper.test.ts index f9c20e85eab..dfb4ab7e976 100644 --- a/src/test/abilities/sap_sipper.test.ts +++ b/src/test/abilities/sap_sipper.test.ts @@ -1,14 +1,15 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { TerrainType } from "#app/data/terrain"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { TerrainType } from "#app/data/terrain.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { BattlerTagType } from "#enums/battler-tag-type"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; // See also: TypeImmunityAbAttr describe("Abilities - Sap Sipper", () => { @@ -31,7 +32,7 @@ describe("Abilities - Sap Sipper", () => { game.override.disableCrits(); }); - it("raise attack 1 level and block effects when activated against a grass attack", async () => { + it("raise attack 1 level and block effects when activated against a grass attack", async() => { const moveToUse = Moves.LEAFAGE; const enemyAbility = Abilities.SAP_SIPPER; @@ -44,7 +45,7 @@ describe("Abilities - Sap Sipper", () => { const startingOppHp = game.scene.currentBattle.enemyParty[0].hp; - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); @@ -52,7 +53,7 @@ describe("Abilities - Sap Sipper", () => { expect(game.scene.getEnemyParty()[0].summonData.battleStats[BattleStat.ATK]).toBe(1); }); - it("raise attack 1 level and block effects when activated against a grass status move", async () => { + it("raise attack 1 level and block effects when activated against a grass status move", async() => { const moveToUse = Moves.SPORE; const enemyAbility = Abilities.SAP_SIPPER; @@ -63,7 +64,7 @@ describe("Abilities - Sap Sipper", () => { await game.startBattle(); - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); @@ -71,7 +72,7 @@ describe("Abilities - Sap Sipper", () => { expect(game.scene.getEnemyParty()[0].summonData.battleStats[BattleStat.ATK]).toBe(1); }); - it("do not activate against status moves that target the field", async () => { + it("do not activate against status moves that target the field", async() => { const moveToUse = Moves.GRASSY_TERRAIN; const enemyAbility = Abilities.SAP_SIPPER; @@ -82,7 +83,7 @@ describe("Abilities - Sap Sipper", () => { await game.startBattle(); - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); @@ -91,7 +92,7 @@ describe("Abilities - Sap Sipper", () => { expect(game.scene.getEnemyParty()[0].summonData.battleStats[BattleStat.ATK]).toBe(0); }); - it("activate once against multi-hit grass attacks", async () => { + it("activate once against multi-hit grass attacks", async() => { const moveToUse = Moves.BULLET_SEED; const enemyAbility = Abilities.SAP_SIPPER; @@ -104,7 +105,7 @@ describe("Abilities - Sap Sipper", () => { const startingOppHp = game.scene.currentBattle.enemyParty[0].hp; - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); @@ -112,7 +113,7 @@ describe("Abilities - Sap Sipper", () => { expect(game.scene.getEnemyParty()[0].summonData.battleStats[BattleStat.ATK]).toBe(1); }); - it("do not activate against status moves that target the user", async () => { + it("do not activate against status moves that target the user", async() => { const moveToUse = Moves.SPIKY_SHIELD; const ability = Abilities.SAP_SIPPER; @@ -124,7 +125,7 @@ describe("Abilities - Sap Sipper", () => { await game.startBattle(); - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(MoveEndPhase); @@ -138,7 +139,7 @@ describe("Abilities - Sap Sipper", () => { // TODO Add METRONOME outcome override // To run this testcase, manually modify the METRONOME move to always give SAP_SIPPER, then uncomment - it.todo("activate once against multi-hit grass attacks (metronome)", async () => { + it.todo("activate once against multi-hit grass attacks (metronome)", async() => { const moveToUse = Moves.METRONOME; const enemyAbility = Abilities.SAP_SIPPER; @@ -151,7 +152,7 @@ describe("Abilities - Sap Sipper", () => { const startingOppHp = game.scene.currentBattle.enemyParty[0].hp; - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); diff --git a/src/test/abilities/schooling.test.ts b/src/test/abilities/schooling.test.ts index ad9663bf8e5..62a7e98bc76 100644 --- a/src/test/abilities/schooling.test.ts +++ b/src/test/abilities/schooling.test.ts @@ -1,10 +1,11 @@ -import { Status, StatusEffect } from "#app/data/status-effect"; -import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { Status, StatusEffect } from "#app/data/status-effect.js"; +import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; const TIMEOUT = 20 * 1000; @@ -52,7 +53,7 @@ describe("Abilities - SCHOOLING", () => { wishiwashi.status = new Status(StatusEffect.FAINT); expect(wishiwashi.isFainted()).toBe(true); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.doKillOpponents(); await game.phaseInterceptor.to(TurnEndPhase); game.doSelectModifier(); diff --git a/src/test/abilities/screen_cleaner.test.ts b/src/test/abilities/screen_cleaner.test.ts index 3c0d12a06ea..403efcce1c0 100644 --- a/src/test/abilities/screen_cleaner.test.ts +++ b/src/test/abilities/screen_cleaner.test.ts @@ -1,12 +1,13 @@ -import { ArenaTagType } from "#app/enums/arena-tag-type"; -import { PostSummonPhase } from "#app/phases/post-summon-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { ArenaTagType } from "#app/enums/arena-tag-type.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { PostSummonPhase } from "#app/phases/post-summon-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Abilities - Screen Cleaner", () => { let phaserGame: Phaser.Game; @@ -35,7 +36,7 @@ describe("Abilities - Screen Cleaner", () => { await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); - game.move.select(Moves.HAIL); + game.doAttack(getMovePosition(game.scene, 0, Moves.HAIL)); await game.phaseInterceptor.to(TurnEndPhase); expect(game.scene.arena.getTag(ArenaTagType.AURORA_VEIL)).toBeDefined(); @@ -52,7 +53,7 @@ describe("Abilities - Screen Cleaner", () => { await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(game.scene.arena.getTag(ArenaTagType.LIGHT_SCREEN)).toBeDefined(); @@ -69,7 +70,7 @@ describe("Abilities - Screen Cleaner", () => { await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(game.scene.arena.getTag(ArenaTagType.REFLECT)).toBeDefined(); diff --git a/src/test/abilities/serene_grace.test.ts b/src/test/abilities/serene_grace.test.ts index 7316b2ea920..5e4841f005a 100644 --- a/src/test/abilities/serene_grace.test.ts +++ b/src/test/abilities/serene_grace.test.ts @@ -1,14 +1,18 @@ -import { BattlerIndex } from "#app/battle"; import { applyAbAttrs, MoveEffectChanceMultiplierAbAttr } from "#app/data/ability"; import { Stat } from "#app/data/pokemon-stat"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Command } from "#app/ui/command-ui-handler"; +import { Mode } from "#app/ui/ui"; import * as Utils from "#app/utils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { BattlerIndex } from "#app/battle.js"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; describe("Abilities - Serene Grace", () => { @@ -32,10 +36,10 @@ describe("Abilities - Serene Grace", () => { game.override.enemySpecies(Species.ONIX); game.override.startingLevel(100); game.override.moveset(movesToUse); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); - it("Move chance without Serene Grace", async () => { + it("Move chance without Serene Grace", async() => { const moveToUse = Moves.AIR_SLASH; await game.startBattle([ Species.PIDGEOT @@ -45,7 +49,13 @@ describe("Abilities - Serene Grace", () => { game.scene.getEnemyParty()[0].stats[Stat.SPDEF] = 10000; expect(game.scene.getParty()[0].formIndex).toBe(0); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.phaseInterceptor.to(MoveEffectPhase, false); @@ -57,12 +67,12 @@ describe("Abilities - Serene Grace", () => { const chance = new Utils.IntegerHolder(move.chance); console.log(move.chance + " Their ability is " + phase.getUserPokemon()!.getAbility().name); - applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getTarget(), false); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, chance, move, phase.getTarget(), false); expect(chance.value).toBe(30); }, 20000); - it("Move chance with Serene Grace", async () => { + it("Move chance with Serene Grace", async() => { const moveToUse = Moves.AIR_SLASH; game.override.ability(Abilities.SERENE_GRACE); await game.startBattle([ @@ -72,7 +82,13 @@ describe("Abilities - Serene Grace", () => { game.scene.getEnemyParty()[0].stats[Stat.SPDEF] = 10000; expect(game.scene.getParty()[0].formIndex).toBe(0); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.phaseInterceptor.to(MoveEffectPhase, false); @@ -83,7 +99,7 @@ describe("Abilities - Serene Grace", () => { expect(move.id).toBe(Moves.AIR_SLASH); const chance = new Utils.IntegerHolder(move.chance); - applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getTarget(), false); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, chance, move, phase.getTarget(), false); expect(chance.value).toBe(60); }, 20000); diff --git a/src/test/abilities/sheer_force.test.ts b/src/test/abilities/sheer_force.test.ts index f73b749dac2..33b34124cc4 100644 --- a/src/test/abilities/sheer_force.test.ts +++ b/src/test/abilities/sheer_force.test.ts @@ -1,14 +1,18 @@ -import { BattlerIndex } from "#app/battle"; import { applyAbAttrs, applyPostDefendAbAttrs, applyPreAttackAbAttrs, MoveEffectChanceMultiplierAbAttr, MovePowerBoostAbAttr, PostDefendTypeChangeAbAttr } from "#app/data/ability"; import { Stat } from "#app/data/pokemon-stat"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Command } from "#app/ui/command-ui-handler"; +import { Mode } from "#app/ui/ui"; import * as Utils from "#app/utils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { BattlerIndex } from "#app/battle.js"; describe("Abilities - Sheer Force", () => { @@ -32,10 +36,10 @@ describe("Abilities - Sheer Force", () => { game.override.enemySpecies(Species.ONIX); game.override.startingLevel(100); game.override.moveset(movesToUse); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); - it("Sheer Force", async () => { + it("Sheer Force", async() => { const moveToUse = Moves.AIR_SLASH; game.override.ability(Abilities.SHEER_FORCE); await game.startBattle([ @@ -46,7 +50,13 @@ describe("Abilities - Sheer Force", () => { game.scene.getEnemyParty()[0].stats[Stat.SPDEF] = 10000; expect(game.scene.getParty()[0].formIndex).toBe(0); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.phaseInterceptor.to(MoveEffectPhase, false); @@ -59,16 +69,16 @@ describe("Abilities - Sheer Force", () => { const power = new Utils.IntegerHolder(move.power); const chance = new Utils.IntegerHolder(move.chance); - applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getTarget(), false); - applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon()!, phase.getTarget()!, move, false, power); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, chance, move, phase.getTarget(), false); + applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon()!, phase.getTarget()!, move, power); expect(chance.value).toBe(0); - expect(power.value).toBe(move.power * 5461 / 4096); + expect(power.value).toBe(move.power * 5461/4096); }, 20000); - it("Sheer Force with exceptions including binding moves", async () => { + it("Sheer Force with exceptions including binding moves", async() => { const moveToUse = Moves.BIND; game.override.ability(Abilities.SHEER_FORCE); await game.startBattle([ @@ -79,7 +89,13 @@ describe("Abilities - Sheer Force", () => { game.scene.getEnemyParty()[0].stats[Stat.DEF] = 10000; expect(game.scene.getParty()[0].formIndex).toBe(0); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.phaseInterceptor.to(MoveEffectPhase, false); @@ -92,8 +108,8 @@ describe("Abilities - Sheer Force", () => { const power = new Utils.IntegerHolder(move.power); const chance = new Utils.IntegerHolder(move.chance); - applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getTarget(), false); - applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon()!, phase.getTarget()!, move, false, power); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, chance, move, phase.getTarget(), false); + applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon()!, phase.getTarget()!, move, power); expect(chance.value).toBe(-1); expect(power.value).toBe(move.power); @@ -101,7 +117,7 @@ describe("Abilities - Sheer Force", () => { }, 20000); - it("Sheer Force with moves with no secondary effect", async () => { + it("Sheer Force with moves with no secondary effect", async() => { const moveToUse = Moves.TACKLE; game.override.ability(Abilities.SHEER_FORCE); await game.startBattle([ @@ -112,7 +128,13 @@ describe("Abilities - Sheer Force", () => { game.scene.getEnemyParty()[0].stats[Stat.DEF] = 10000; expect(game.scene.getParty()[0].formIndex).toBe(0); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.phaseInterceptor.to(MoveEffectPhase, false); @@ -125,8 +147,8 @@ describe("Abilities - Sheer Force", () => { const power = new Utils.IntegerHolder(move.power); const chance = new Utils.IntegerHolder(move.chance); - applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getTarget(), false); - applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon()!, phase.getTarget()!, move, false, power); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, chance, move, phase.getTarget(), false); + applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon()!, phase.getTarget()!, move, power); expect(chance.value).toBe(-1); expect(power.value).toBe(move.power); @@ -134,10 +156,10 @@ describe("Abilities - Sheer Force", () => { }, 20000); - it("Sheer Force Disabling Specific Abilities", async () => { + it("Sheer Force Disabling Specific Abilities", async() => { const moveToUse = Moves.CRUSH_CLAW; game.override.enemyAbility(Abilities.COLOR_CHANGE); - game.override.startingHeldItems([{ name: "KINGS_ROCK", count: 1 }]); + game.override.startingHeldItems([{name: "KINGS_ROCK", count: 1}]); game.override.ability(Abilities.SHEER_FORCE); await game.startBattle([ Species.PIDGEOT @@ -147,7 +169,13 @@ describe("Abilities - Sheer Force", () => { game.scene.getEnemyParty()[0].stats[Stat.DEF] = 10000; expect(game.scene.getParty()[0].formIndex).toBe(0); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.phaseInterceptor.to(MoveEffectPhase, false); @@ -163,12 +191,12 @@ describe("Abilities - Sheer Force", () => { const target = phase.getTarget()!; const opponentType = target.getTypes()[0]; - applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, false, chance, move, target, false); - applyPreAttackAbAttrs(MovePowerBoostAbAttr, user, target, move, false, power); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, chance, move, target, false); + applyPreAttackAbAttrs(MovePowerBoostAbAttr, user, target, move, power); applyPostDefendAbAttrs(PostDefendTypeChangeAbAttr, target, user, move, target.apply(user, move)); expect(chance.value).toBe(0); - expect(power.value).toBe(move.power * 5461 / 4096); + expect(power.value).toBe(move.power * 5461/4096); expect(target.getTypes().length).toBe(2); expect(target.getTypes()[0]).toBe(opponentType); diff --git a/src/test/abilities/shield_dust.test.ts b/src/test/abilities/shield_dust.test.ts index 14770c49427..b40689a180a 100644 --- a/src/test/abilities/shield_dust.test.ts +++ b/src/test/abilities/shield_dust.test.ts @@ -1,14 +1,18 @@ -import { BattlerIndex } from "#app/battle"; import { applyAbAttrs, applyPreDefendAbAttrs, IgnoreMoveEffectsAbAttr, MoveEffectChanceMultiplierAbAttr } from "#app/data/ability"; import { Stat } from "#app/data/pokemon-stat"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Command } from "#app/ui/command-ui-handler"; +import { Mode } from "#app/ui/ui"; import * as Utils from "#app/utils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { BattlerIndex } from "#app/battle.js"; describe("Abilities - Shield Dust", () => { @@ -33,10 +37,10 @@ describe("Abilities - Shield Dust", () => { game.override.enemyAbility(Abilities.SHIELD_DUST); game.override.startingLevel(100); game.override.moveset(movesToUse); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); - it("Shield Dust", async () => { + it("Shield Dust", async() => { const moveToUse = Moves.AIR_SLASH; await game.startBattle([ Species.PIDGEOT @@ -46,7 +50,13 @@ describe("Abilities - Shield Dust", () => { game.scene.getEnemyParty()[0].stats[Stat.SPDEF] = 10000; expect(game.scene.getParty()[0].formIndex).toBe(0); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.phaseInterceptor.to(MoveEffectPhase, false); @@ -57,8 +67,8 @@ describe("Abilities - Shield Dust", () => { expect(move.id).toBe(Moves.AIR_SLASH); const chance = new Utils.IntegerHolder(move.chance); - applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getTarget(), false); - applyPreDefendAbAttrs(IgnoreMoveEffectsAbAttr, phase.getTarget()!, phase.getUserPokemon()!, null, null, false, chance); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, chance, move, phase.getTarget(), false); + applyPreDefendAbAttrs(IgnoreMoveEffectsAbAttr, phase.getTarget()!, phase.getUserPokemon()!, null!, null!, chance); expect(chance.value).toBe(0); }, 20000); diff --git a/src/test/abilities/shields_down.test.ts b/src/test/abilities/shields_down.test.ts index 9bfec23ddf1..e07c12ebb63 100644 --- a/src/test/abilities/shields_down.test.ts +++ b/src/test/abilities/shields_down.test.ts @@ -1,10 +1,11 @@ -import { Status, StatusEffect } from "#app/data/status-effect"; -import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { Status, StatusEffect } from "#app/data/status-effect.js"; +import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; const TIMEOUT = 20 * 1000; @@ -52,7 +53,7 @@ describe("Abilities - SHIELDS DOWN", () => { minior.status = new Status(StatusEffect.FAINT); expect(minior.isFainted()).toBe(true); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.doKillOpponents(); await game.phaseInterceptor.to(TurnEndPhase); game.doSelectModifier(); diff --git a/src/test/abilities/stall.test.ts b/src/test/abilities/stall.test.ts index d8dbe9d0e06..5410d2e953e 100644 --- a/src/test/abilities/stall.test.ts +++ b/src/test/abilities/stall.test.ts @@ -1,10 +1,11 @@ -import { MovePhase } from "#app/phases/move-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { MovePhase } from "#app/phases/move-phase.js"; describe("Abilities - Stall", () => { @@ -37,13 +38,13 @@ describe("Abilities - Stall", () => { * https://bulbapedia.bulbagarden.net/wiki/Priority **/ - it("Pokemon with Stall should move last in its priority bracket regardless of speed", async () => { - await game.startBattle([Species.SHUCKLE]); + it("Pokemon with Stall should move last in its priority bracket regardless of speed", async() => { + await game.startBattle([ Species.SHUCKLE ]); const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); - game.move.select(Moves.QUICK_ATTACK); + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK)); await game.phaseInterceptor.to(MovePhase, false); // The player Pokemon (without Stall) goes first despite having lower speed than the opponent. @@ -55,13 +56,13 @@ describe("Abilities - Stall", () => { expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(enemyIndex); }, 20000); - it("Pokemon with Stall will go first if a move that is in a higher priority bracket than the opponent's move is used", async () => { - await game.startBattle([Species.SHUCKLE]); + it("Pokemon with Stall will go first if a move that is in a higher priority bracket than the opponent's move is used", async() => { + await game.startBattle([ Species.SHUCKLE ]); const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(MovePhase, false); // The opponent Pokemon (with Stall) goes first because its move is still within a higher priority bracket than its opponent. @@ -73,14 +74,14 @@ describe("Abilities - Stall", () => { expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(leadIndex); }, 20000); - it("If both Pokemon have stall and use the same move, speed is used to determine who goes first.", async () => { + it("If both Pokemon have stall and use the same move, speed is used to determine who goes first.", async() => { game.override.ability(Abilities.STALL); - await game.startBattle([Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE ]); const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(MovePhase, false); // The opponent Pokemon (with Stall) goes first because it has a higher speed. diff --git a/src/test/abilities/steely_spirit.test.ts b/src/test/abilities/steely_spirit.test.ts index c632d0be777..3ca1a55ebee 100644 --- a/src/test/abilities/steely_spirit.test.ts +++ b/src/test/abilities/steely_spirit.test.ts @@ -1,13 +1,15 @@ -import { allAbilities } from "#app/data/ability"; -import { allMoves } from "#app/data/move"; -import { Abilities } from "#app/enums/abilities"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import { allAbilities } from "#app/data/ability.js"; +import { allMoves } from "#app/data/move.js"; +import { Abilities } from "#app/enums/abilities.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import { SelectTargetPhase } from "#app/phases/select-target-phase.js"; describe("Abilities - Steely Spirit", () => { let phaserGame: Phaser.Game; @@ -45,8 +47,10 @@ describe("Abilities - Steely Spirit", () => { expect(boostSource.hasAbility(Abilities.STEELY_SPIRIT)).toBe(true); - game.move.select(moveToCheck, 0, enemyToCheck.getBattlerIndex()); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, moveToCheck)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(enemyToCheck.getBattlerIndex()); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(MoveEffectPhase); expect(allMoves[moveToCheck].calculateBattlePower).toHaveReturnedWith(ironHeadPower * steelySpiritMultiplier); @@ -62,8 +66,12 @@ describe("Abilities - Steely Spirit", () => { expect(game.scene.getPlayerField().every(p => p.hasAbility(Abilities.STEELY_SPIRIT))).toBe(true); - game.move.select(moveToCheck, 0, enemyToCheck.getBattlerIndex()); - game.move.select(moveToCheck, 1, enemyToCheck.getBattlerIndex()); + game.doAttack(getMovePosition(game.scene, 0, moveToCheck)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(enemyToCheck.getBattlerIndex()); + game.doAttack(getMovePosition(game.scene, 1, moveToCheck)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(enemyToCheck.getBattlerIndex()); await game.phaseInterceptor.to(MoveEffectPhase); expect(allMoves[moveToCheck].calculateBattlePower).toHaveReturnedWith(ironHeadPower * Math.pow(steelySpiritMultiplier, 2)); @@ -82,8 +90,10 @@ describe("Abilities - Steely Spirit", () => { expect(boostSource.hasAbility(Abilities.STEELY_SPIRIT)).toBe(false); expect(boostSource.summonData.abilitySuppressed).toBe(true); - game.move.select(moveToCheck, 0, enemyToCheck.getBattlerIndex()); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, moveToCheck)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(enemyToCheck.getBattlerIndex()); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(MoveEffectPhase); expect(allMoves[moveToCheck].calculateBattlePower).toHaveReturnedWith(ironHeadPower); diff --git a/src/test/abilities/sturdy.test.ts b/src/test/abilities/sturdy.test.ts index dc9f774cc5b..602b2c04eb1 100644 --- a/src/test/abilities/sturdy.test.ts +++ b/src/test/abilities/sturdy.test.ts @@ -1,12 +1,13 @@ -import { EnemyPokemon } from "#app/field/pokemon"; -import { DamagePhase } from "#app/phases/damage-phase"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; +import { EnemyPokemon } from "#app/field/pokemon.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import { DamagePhase } from "#app/phases/damage-phase.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -41,7 +42,7 @@ describe("Abilities - Sturdy", () => { "Sturdy activates when user is at full HP", async () => { await game.startBattle(); - game.move.select(Moves.CLOSE_COMBAT); + game.doAttack(getMovePosition(game.scene, 0, Moves.CLOSE_COMBAT)); await game.phaseInterceptor.to(MoveEndPhase); expect(game.scene.getEnemyParty()[0].hp).toBe(1); }, @@ -56,7 +57,7 @@ describe("Abilities - Sturdy", () => { const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; enemyPokemon.hp = enemyPokemon.getMaxHp() - 1; - game.move.select(Moves.CLOSE_COMBAT); + game.doAttack(getMovePosition(game.scene, 0, Moves.CLOSE_COMBAT)); await game.phaseInterceptor.to(DamagePhase); expect(enemyPokemon.hp).toBe(0); @@ -69,7 +70,7 @@ describe("Abilities - Sturdy", () => { "Sturdy pokemon should be immune to OHKO moves", async () => { await game.startBattle(); - game.move.select(Moves.FISSURE); + game.doAttack(getMovePosition(game.scene, 0, Moves.FISSURE)); await game.phaseInterceptor.to(MoveEndPhase); const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; @@ -84,7 +85,7 @@ describe("Abilities - Sturdy", () => { game.override.ability(Abilities.MOLD_BREAKER); await game.startBattle(); - game.move.select(Moves.CLOSE_COMBAT); + game.doAttack(getMovePosition(game.scene, 0, Moves.CLOSE_COMBAT)); await game.phaseInterceptor.to(DamagePhase); const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; diff --git a/src/test/abilities/sweet_veil.test.ts b/src/test/abilities/sweet_veil.test.ts index 5de3c7285a9..8ab384ae59e 100644 --- a/src/test/abilities/sweet_veil.test.ts +++ b/src/test/abilities/sweet_veil.test.ts @@ -1,14 +1,16 @@ -import { BattlerIndex } from "#app/battle"; -import { Abilities } from "#app/enums/abilities"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { CommandPhase } from "#app/phases/command-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { Moves } from "#enums/moves"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { Species } from "#enums/species"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { BattlerIndex } from "#app/battle.js"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { MovePhase } from "#app/phases/move-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Abilities - Sweet Veil", () => { let phaserGame: Phaser.Game; @@ -27,7 +29,7 @@ describe("Abilities - Sweet Veil", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleType("double"); - game.override.moveset([Moves.SPLASH, Moves.REST, Moves.YAWN]); + game.override.moveset([Moves.SPLASH, Moves.REST]); game.override.enemySpecies(Species.MAGIKARP); game.override.enemyAbility(Abilities.BALL_FETCH); game.override.enemyMoveset([Moves.POWDER, Moves.POWDER, Moves.POWDER, Moves.POWDER]); @@ -36,8 +38,8 @@ describe("Abilities - Sweet Veil", () => { it("prevents the user and its allies from falling asleep", async () => { await game.startBattle([Species.SWIRLIX, Species.MAGIKARP]); - game.move.select(Moves.SPLASH); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); @@ -48,8 +50,8 @@ describe("Abilities - Sweet Veil", () => { game.override.enemyMoveset(SPLASH_ONLY); await game.startBattle([Species.SWIRLIX, Species.MAGIKARP]); - game.move.select(Moves.SPLASH); - game.move.select(Moves.REST, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + game.doAttack(getMovePosition(game.scene, 1, Moves.REST)); await game.phaseInterceptor.to(TurnEndPhase); @@ -60,8 +62,8 @@ describe("Abilities - Sweet Veil", () => { game.override.enemyMoveset([Moves.YAWN, Moves.YAWN, Moves.YAWN, Moves.YAWN]); await game.startBattle([Species.SWIRLIX, Species.MAGIKARP]); - game.move.select(Moves.SPLASH); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); @@ -72,19 +74,28 @@ describe("Abilities - Sweet Veil", () => { game.override.enemySpecies(Species.PIKACHU); game.override.enemyLevel(5); game.override.startingLevel(5); - game.override.enemyMoveset(SPLASH_ONLY); + game.override.enemyMoveset([Moves.YAWN, Moves.YAWN, Moves.YAWN, Moves.YAWN]); await game.startBattle([Species.SHUCKLE, Species.SHUCKLE, Species.SWIRLIX]); - game.move.select(Moves.SPLASH); - game.move.select(Moves.YAWN, 1, BattlerIndex.PLAYER); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); - await game.phaseInterceptor.to("BerryPhase"); + // First pokemon move + await game.move.forceHit(); + + // Second pokemon move + await game.phaseInterceptor.to(MovePhase, false); + await game.move.forceHit(); expect(game.scene.getPlayerField().some(p => !!p.getTag(BattlerTagType.DROWSY))).toBe(true); + await game.phaseInterceptor.to(TurnEndPhase); + + const drowsyMon = game.scene.getPlayerField().find(p => !!p.getTag(BattlerTagType.DROWSY))!; + await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, (drowsyMon.getBattlerIndex() as BattlerIndex.PLAYER | BattlerIndex.PLAYER_2), Moves.SPLASH)); game.doSwitchPokemon(2); expect(game.scene.getPlayerField().every(p => p.status?.effect)).toBe(false); diff --git a/src/test/abilities/unseen_fist.test.ts b/src/test/abilities/unseen_fist.test.ts index ea1996ec66b..7d47d73bb16 100644 --- a/src/test/abilities/unseen_fist.test.ts +++ b/src/test/abilities/unseen_fist.test.ts @@ -1,10 +1,11 @@ -import { TurnEndPhase } from "#app/phases/turn-end-phase"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -79,7 +80,7 @@ async function testUnseenFistHitResult(game: GameManager, attackMove: Moves, pro const enemyStartingHp = enemyPokemon.hp; - game.move.select(attackMove); + game.doAttack(getMovePosition(game.scene, 0, attackMove)); await game.phaseInterceptor.to(TurnEndPhase, false); if (shouldSucceed) { diff --git a/src/test/abilities/volt_absorb.test.ts b/src/test/abilities/volt_absorb.test.ts index d9c3fe34c24..0e3d5c9792f 100644 --- a/src/test/abilities/volt_absorb.test.ts +++ b/src/test/abilities/volt_absorb.test.ts @@ -1,10 +1,11 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { BattlerTagType } from "#enums/battler-tag-type"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -41,7 +42,7 @@ describe("Abilities - Volt Absorb", () => { await game.startBattle(); - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); diff --git a/src/test/abilities/wind_power.test.ts b/src/test/abilities/wind_power.test.ts index c944e01b43a..24f01cceebc 100644 --- a/src/test/abilities/wind_power.test.ts +++ b/src/test/abilities/wind_power.test.ts @@ -1,12 +1,13 @@ -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; describe("Abilities - Wind Power", () => { let phaserGame: Phaser.Game; @@ -37,7 +38,7 @@ describe("Abilities - Wind Power", () => { expect(shiftry.getTag(BattlerTagType.CHARGED)).toBeUndefined(); - game.move.select(Moves.PETAL_BLIZZARD); + game.doAttack(getMovePosition(game.scene, 0, Moves.PETAL_BLIZZARD)); await game.phaseInterceptor.to(TurnEndPhase); expect(shiftry.getTag(BattlerTagType.CHARGED)).toBeDefined(); @@ -52,7 +53,7 @@ describe("Abilities - Wind Power", () => { expect(shiftry.getTag(BattlerTagType.CHARGED)).toBeUndefined(); - game.move.select(Moves.TAILWIND); + game.doAttack(getMovePosition(game.scene, 0, Moves.TAILWIND)); await game.phaseInterceptor.to(TurnEndPhase); expect(shiftry.getTag(BattlerTagType.CHARGED)).toBeDefined(); @@ -69,7 +70,7 @@ describe("Abilities - Wind Power", () => { expect(shiftry.getTag(BattlerTagType.CHARGED)).toBeUndefined(); expect(magikarp.getTag(BattlerTagType.CHARGED)).toBeUndefined(); - game.move.select(Moves.TAILWIND); + game.doAttack(getMovePosition(game.scene, 0, Moves.TAILWIND)); await game.phaseInterceptor.to(TurnEndPhase); @@ -85,7 +86,7 @@ describe("Abilities - Wind Power", () => { expect(shiftry.getTag(BattlerTagType.CHARGED)).toBeUndefined(); - game.move.select(Moves.SANDSTORM); + game.doAttack(getMovePosition(game.scene, 0, Moves.SANDSTORM)); await game.phaseInterceptor.to(TurnEndPhase); diff --git a/src/test/abilities/wind_rider.test.ts b/src/test/abilities/wind_rider.test.ts index 97e2e6456dc..92c38507e4f 100644 --- a/src/test/abilities/wind_rider.test.ts +++ b/src/test/abilities/wind_rider.test.ts @@ -1,12 +1,13 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; describe("Abilities - Wind Rider", () => { let phaserGame: Phaser.Game; @@ -37,7 +38,7 @@ describe("Abilities - Wind Rider", () => { expect(shiftry.summonData.battleStats[BattleStat.ATK]).toBe(0); - game.move.select(Moves.PETAL_BLIZZARD); + game.doAttack(getMovePosition(game.scene, 0, Moves.PETAL_BLIZZARD)); await game.phaseInterceptor.to(TurnEndPhase); @@ -54,7 +55,7 @@ describe("Abilities - Wind Rider", () => { expect(shiftry.summonData.battleStats[BattleStat.ATK]).toBe(0); - game.move.select(Moves.TAILWIND); + game.doAttack(getMovePosition(game.scene, 0, Moves.TAILWIND)); await game.phaseInterceptor.to(TurnEndPhase); @@ -72,7 +73,7 @@ describe("Abilities - Wind Rider", () => { expect(shiftry.summonData.battleStats[BattleStat.ATK]).toBe(0); expect(magikarp.summonData.battleStats[BattleStat.ATK]).toBe(0); - game.move.select(Moves.TAILWIND); + game.doAttack(getMovePosition(game.scene, 0, Moves.TAILWIND)); await game.phaseInterceptor.to(TurnEndPhase); @@ -90,7 +91,7 @@ describe("Abilities - Wind Rider", () => { expect(shiftry.summonData.battleStats[BattleStat.ATK]).toBe(0); expect(magikarp.summonData.battleStats[BattleStat.ATK]).toBe(0); - game.move.select(Moves.TAILWIND); + game.doAttack(getMovePosition(game.scene, 0, Moves.TAILWIND)); await game.phaseInterceptor.to(TurnEndPhase); @@ -107,7 +108,7 @@ describe("Abilities - Wind Rider", () => { expect(shiftry.summonData.battleStats[BattleStat.ATK]).toBe(0); expect(shiftry.isFullHp()).toBe(true); - game.move.select(Moves.SANDSTORM); + game.doAttack(getMovePosition(game.scene, 0, Moves.SANDSTORM)); await game.phaseInterceptor.to(TurnEndPhase); diff --git a/src/test/abilities/wonder_skin.test.ts b/src/test/abilities/wonder_skin.test.ts index 0c2aedc8ce8..d6e2b2443c4 100644 --- a/src/test/abilities/wonder_skin.test.ts +++ b/src/test/abilities/wonder_skin.test.ts @@ -1,13 +1,14 @@ -import { allAbilities } from "#app/data/ability"; -import { allMoves } from "#app/data/move"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import { allAbilities } from "#app/data/ability.js"; +import { allMoves } from "#app/data/move.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; describe("Abilities - Wonder Skin", () => { let phaserGame: Phaser.Game; @@ -39,7 +40,7 @@ describe("Abilities - Wonder Skin", () => { vi.spyOn(moveToCheck, "calculateBattleAccuracy"); await game.startBattle([Species.PIKACHU]); - game.move.select(Moves.CHARM); + game.doAttack(getMovePosition(game.scene, 0, Moves.CHARM)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattleAccuracy).toHaveReturnedWith(50); @@ -51,7 +52,7 @@ describe("Abilities - Wonder Skin", () => { vi.spyOn(moveToCheck, "calculateBattleAccuracy"); await game.startBattle([Species.PIKACHU]); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattleAccuracy).toHaveReturnedWith(100); @@ -67,7 +68,7 @@ describe("Abilities - Wonder Skin", () => { vi.spyOn(moveToCheck, "calculateBattleAccuracy"); await game.startBattle([Species.PIKACHU]); - game.move.select(Moves.CHARM); + game.doAttack(getMovePosition(game.scene, 0, Moves.CHARM)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattleAccuracy).toHaveReturnedWith(100); diff --git a/src/test/abilities/zen_mode.test.ts b/src/test/abilities/zen_mode.test.ts index 677d998e876..72fdc5442c5 100644 --- a/src/test/abilities/zen_mode.test.ts +++ b/src/test/abilities/zen_mode.test.ts @@ -1,23 +1,26 @@ -import { BattlerIndex } from "#app/battle"; import { Stat } from "#app/data/pokemon-stat"; -import { Status, StatusEffect } from "#app/data/status-effect"; -import { DamagePhase } from "#app/phases/damage-phase"; -import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; -import { MessagePhase } from "#app/phases/message-phase"; -import { PostSummonPhase } from "#app/phases/post-summon-phase"; -import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; -import { SwitchPhase } from "#app/phases/switch-phase"; -import { SwitchSummonPhase } from "#app/phases/switch-summon-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; -import { TurnStartPhase } from "#app/phases/turn-start-phase"; +import { Status, StatusEffect } from "#app/data/status-effect.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Command } from "#app/ui/command-ui-handler"; import { Mode } from "#app/ui/ui"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import { BattlerIndex } from "#app/battle.js"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { DamagePhase } from "#app/phases/damage-phase.js"; +import { EnemyCommandPhase } from "#app/phases/enemy-command-phase.js"; +import { MessagePhase } from "#app/phases/message-phase.js"; +import { PostSummonPhase } from "#app/phases/post-summon-phase.js"; +import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase.js"; +import { SwitchPhase } from "#app/phases/switch-phase.js"; +import { SwitchSummonPhase } from "#app/phases/switch-summon-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; +import { TurnStartPhase } from "#app/phases/turn-start-phase.js"; const TIMEOUT = 20 * 1000; @@ -56,7 +59,13 @@ describe("Abilities - ZEN MODE", () => { game.scene.getParty()[0].hp = 100; expect(game.scene.getParty()[0].formIndex).toBe(0); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.phaseInterceptor.to(DamagePhase, false); @@ -79,7 +88,13 @@ describe("Abilities - ZEN MODE", () => { game.scene.getParty()[0].hp = 100; expect(game.scene.getParty()[0].formIndex).toBe(0); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.phaseInterceptor.to(QuietFormChangePhase); @@ -99,7 +114,13 @@ describe("Abilities - ZEN MODE", () => { game.scene.getParty()[0].hp = 100; expect(game.scene.getParty()[0].formIndex).toBe(0); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.phaseInterceptor.to(DamagePhase, false); @@ -148,7 +169,7 @@ describe("Abilities - ZEN MODE", () => { darmanitan.status = new Status(StatusEffect.FAINT); expect(darmanitan.isFainted()).toBe(true); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.doKillOpponents(); await game.phaseInterceptor.to(TurnEndPhase); game.doSelectModifier(); diff --git a/src/test/abilities/zero_to_hero.test.ts b/src/test/abilities/zero_to_hero.test.ts index 1a9697f974e..ee6c07096a8 100644 --- a/src/test/abilities/zero_to_hero.test.ts +++ b/src/test/abilities/zero_to_hero.test.ts @@ -1,10 +1,11 @@ -import { Status, StatusEffect } from "#app/data/status-effect"; -import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { Status, StatusEffect } from "#app/data/status-effect.js"; +import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { SPLASH_ONLY } from "../utils/testUtils"; @@ -51,7 +52,7 @@ describe("Abilities - ZERO TO HERO", () => { palafin2.status = new Status(StatusEffect.FAINT); expect(palafin2.isFainted()).toBe(true); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.doKillOpponents(); await game.phaseInterceptor.to(TurnEndPhase); game.doSelectModifier(); @@ -79,7 +80,7 @@ describe("Abilities - ZERO TO HERO", () => { const palafin = game.scene.getPlayerPokemon()!; expect(palafin.formIndex).toBe(baseForm); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.killPokemon(palafin); game.doSelectPartyPokemon(1); await game.toNextTurn(); @@ -96,7 +97,7 @@ describe("Abilities - ZERO TO HERO", () => { const palafin = game.scene.getPlayerPokemon()!; expect(palafin.formIndex).toBe(heroForm); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.killPokemon(palafin); game.doSelectPartyPokemon(1); await game.toNextTurn(); diff --git a/src/test/account.spec.ts b/src/test/account.spec.ts index eb6002f3cf2..d5d0458c7e8 100644 --- a/src/test/account.spec.ts +++ b/src/test/account.spec.ts @@ -1,4 +1,4 @@ -import * as battleScene from "#app/battle-scene"; +import * as battleScene from "#app/battle-scene.js"; import { describe, expect, it, vi } from "vitest"; import { initLoggedInUser, loggedInUser, updateUserInfo } from "../account"; import * as utils from "../utils"; diff --git a/src/test/achievements/achievement.test.ts b/src/test/achievements/achievement.test.ts index 36c20ae2248..5cd9c4d4094 100644 --- a/src/test/achievements/achievement.test.ts +++ b/src/test/achievements/achievement.test.ts @@ -1,7 +1,7 @@ -import { TurnHeldItemTransferModifier } from "#app/modifier/modifier"; +import { TurnHeldItemTransferModifier } from "#app/modifier/modifier.js"; import { Achv, AchvTier, DamageAchv, HealAchv, LevelAchv, ModifierAchv, MoneyAchv, RibbonAchv, achvs } from "#app/system/achv"; -import { IntegerHolder, NumberHolder } from "#app/utils"; import GameManager from "#test/utils/gameManager"; +import { IntegerHolder, NumberHolder } from "#app/utils.js"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import BattleScene from "../../battle-scene"; diff --git a/src/test/arena/arena_gravity.test.ts b/src/test/arena/arena_gravity.test.ts index eda8c687ba1..68c31258454 100644 --- a/src/test/arena/arena_gravity.test.ts +++ b/src/test/arena/arena_gravity.test.ts @@ -1,14 +1,14 @@ -import { allMoves } from "#app/data/move"; -import { Abilities } from "#app/enums/abilities"; -import { ArenaTagType } from "#app/enums/arena-tag-type"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { allMoves } from "#app/data/move.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { ArenaTagType } from "#app/enums/arena-tag-type.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { SPLASH_ONLY } from "../utils/testUtils"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Arena - Gravity", () => { let phaserGame: Phaser.Game; @@ -26,17 +26,14 @@ describe("Arena - Gravity", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override - .battleType("single") - .moveset([Moves.TACKLE, Moves.GRAVITY, Moves.FISSURE]) - .ability(Abilities.UNNERVE) - .enemyAbility(Abilities.BALL_FETCH) - .enemySpecies(Species.SHUCKLE) - .enemyMoveset(SPLASH_ONLY); + game.override.battleType("single"); + game.override.moveset([Moves.TACKLE, Moves.GRAVITY, Moves.FISSURE]); + game.override.ability(Abilities.UNNERVE); + game.override.enemyAbility(Abilities.BALL_FETCH); + game.override.enemySpecies(Species.SHUCKLE); + game.override.enemyMoveset(new Array(4).fill(Moves.SPLASH)); }); - // Reference: https://bulbapedia.bulbagarden.net/wiki/Gravity_(move) - it("non-OHKO move accuracy is multiplied by 1.67", async () => { const moveToCheck = allMoves[Moves.TACKLE]; @@ -44,14 +41,14 @@ describe("Arena - Gravity", () => { // Setup Gravity on first turn await game.startBattle([Species.PIKACHU]); - game.move.select(Moves.GRAVITY); + game.doAttack(getMovePosition(game.scene, 0, Moves.GRAVITY)); await game.phaseInterceptor.to(TurnEndPhase); expect(game.scene.arena.getTag(ArenaTagType.GRAVITY)).toBeDefined(); // Use non-OHKO move on second turn await game.toNextTurn(); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattleAccuracy).toHaveReturnedWith(100 * 1.67); @@ -68,77 +65,16 @@ describe("Arena - Gravity", () => { // Setup Gravity on first turn await game.startBattle([Species.PIKACHU]); - game.move.select(Moves.GRAVITY); + game.doAttack(getMovePosition(game.scene, 0, Moves.GRAVITY)); await game.phaseInterceptor.to(TurnEndPhase); expect(game.scene.arena.getTag(ArenaTagType.GRAVITY)).toBeDefined(); // Use OHKO move on second turn await game.toNextTurn(); - game.move.select(Moves.FISSURE); + game.doAttack(getMovePosition(game.scene, 0, Moves.FISSURE)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattleAccuracy).toHaveReturnedWith(30); }); - - describe("Against flying types", () => { - it("can be hit by ground-type moves now", async () => { - game.override - .startingLevel(5) - .enemyLevel(5) - .enemySpecies(Species.PIDGEOT) - .moveset([Moves.GRAVITY, Moves.EARTHQUAKE]); - - await game.startBattle([Species.PIKACHU]); - - const pidgeot = game.scene.getEnemyPokemon()!; - vi.spyOn(pidgeot, "getAttackTypeEffectiveness"); - - // Try earthquake on 1st turn (fails!); - game.move.select(Moves.EARTHQUAKE); - await game.phaseInterceptor.to(TurnEndPhase); - - expect(pidgeot.getAttackTypeEffectiveness).toHaveReturnedWith(0); - - // Setup Gravity on 2nd turn - await game.toNextTurn(); - game.move.select(Moves.GRAVITY); - await game.phaseInterceptor.to(TurnEndPhase); - - expect(game.scene.arena.getTag(ArenaTagType.GRAVITY)).toBeDefined(); - - // Use ground move on 3rd turn - await game.toNextTurn(); - game.move.select(Moves.EARTHQUAKE); - await game.phaseInterceptor.to(TurnEndPhase); - - expect(pidgeot.getAttackTypeEffectiveness).toHaveReturnedWith(1); - }); - - it("keeps super-effective moves super-effective after using gravity", async () => { - game.override - .startingLevel(5) - .enemyLevel(5) - .enemySpecies(Species.PIDGEOT) - .moveset([Moves.GRAVITY, Moves.THUNDERBOLT]); - - await game.startBattle([Species.PIKACHU]); - - const pidgeot = game.scene.getEnemyPokemon()!; - vi.spyOn(pidgeot, "getAttackTypeEffectiveness"); - - // Setup Gravity on 1st turn - game.move.select(Moves.GRAVITY); - await game.phaseInterceptor.to(TurnEndPhase); - - expect(game.scene.arena.getTag(ArenaTagType.GRAVITY)).toBeDefined(); - - // Use electric move on 2nd turn - await game.toNextTurn(); - game.move.select(Moves.THUNDERBOLT); - await game.phaseInterceptor.to(TurnEndPhase); - - expect(pidgeot.getAttackTypeEffectiveness).toHaveReturnedWith(2); - }); - }); }); diff --git a/src/test/arena/weather_fog.test.ts b/src/test/arena/weather_fog.test.ts index b36b0de2e06..350007ae943 100644 --- a/src/test/arena/weather_fog.test.ts +++ b/src/test/arena/weather_fog.test.ts @@ -1,10 +1,11 @@ -import { allMoves } from "#app/data/move"; -import { WeatherType } from "#app/data/weather"; -import { Abilities } from "#app/enums/abilities"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import { allMoves } from "#app/data/move.js"; +import { WeatherType } from "#app/data/weather.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; @@ -40,7 +41,7 @@ describe("Weather - Fog", () => { vi.spyOn(moveToCheck, "calculateBattleAccuracy"); await game.startBattle([Species.MAGIKARP]); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattleAccuracy).toHaveReturnedWith(100 * 0.9); diff --git a/src/test/arena/weather_strong_winds.test.ts b/src/test/arena/weather_strong_winds.test.ts index 8b2d3e2547e..79fba30c019 100644 --- a/src/test/arena/weather_strong_winds.test.ts +++ b/src/test/arena/weather_strong_winds.test.ts @@ -1,11 +1,12 @@ -import { allMoves } from "#app/data/move"; -import { TurnStartPhase } from "#app/phases/turn-start-phase"; +import { allMoves } from "#app/data/move.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { TurnStartPhase } from "#app/phases/turn-start-phase.js"; describe("Weather - Strong Winds", () => { let phaserGame: Phaser.Game; @@ -37,7 +38,7 @@ describe("Weather - Strong Winds", () => { const pikachu = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; - game.move.select(Moves.THUNDERBOLT); + game.doAttack(getMovePosition(game.scene, 0, Moves.THUNDERBOLT)); await game.phaseInterceptor.to(TurnStartPhase); expect(enemy.getAttackTypeEffectiveness(allMoves[Moves.THUNDERBOLT].type, pikachu)).toBe(0.5); @@ -48,7 +49,7 @@ describe("Weather - Strong Winds", () => { const pikachu = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; - game.move.select(Moves.THUNDERBOLT); + game.doAttack(getMovePosition(game.scene, 0, Moves.THUNDERBOLT)); await game.phaseInterceptor.to(TurnStartPhase); expect(enemy.getAttackTypeEffectiveness(allMoves[Moves.THUNDERBOLT].type, pikachu)).toBe(1); @@ -59,7 +60,7 @@ describe("Weather - Strong Winds", () => { const pikachu = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; - game.move.select(Moves.ICE_BEAM); + game.doAttack(getMovePosition(game.scene, 0, Moves.ICE_BEAM)); await game.phaseInterceptor.to(TurnStartPhase); expect(enemy.getAttackTypeEffectiveness(allMoves[Moves.ICE_BEAM].type, pikachu)).toBe(1); @@ -70,7 +71,7 @@ describe("Weather - Strong Winds", () => { const pikachu = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; - game.move.select(Moves.ROCK_SLIDE); + game.doAttack(getMovePosition(game.scene, 0, Moves.ROCK_SLIDE)); await game.phaseInterceptor.to(TurnStartPhase); expect(enemy.getAttackTypeEffectiveness(allMoves[Moves.ROCK_SLIDE].type, pikachu)).toBe(1); diff --git a/src/test/battle-scene.test.ts b/src/test/battle-scene.test.ts index 9e28ec99791..21d3f689d1c 100644 --- a/src/test/battle-scene.test.ts +++ b/src/test/battle-scene.test.ts @@ -1,4 +1,4 @@ -import { LoadingScene } from "#app/loading-scene"; +import { LoadingScene } from "#app/loading-scene.js"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import GameManager from "./utils/gameManager"; diff --git a/src/test/battle-stat.spec.ts b/src/test/battle-stat.spec.ts index 16fce962838..775dd40ff34 100644 --- a/src/test/battle-stat.spec.ts +++ b/src/test/battle-stat.spec.ts @@ -1,4 +1,4 @@ -import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "#app/data/battle-stat"; +import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "#app/data/battle-stat.js"; import { describe, expect, it } from "vitest"; import { arrayOfRange, mockI18next } from "./utils/testUtils"; diff --git a/src/test/battle/battle-order.test.ts b/src/test/battle/battle-order.test.ts index 0129ecad254..208b921b843 100644 --- a/src/test/battle/battle-order.test.ts +++ b/src/test/battle/battle-order.test.ts @@ -1,13 +1,19 @@ import { Stat } from "#app/data/pokemon-stat"; -import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; -import { SelectTargetPhase } from "#app/phases/select-target-phase"; -import { TurnStartPhase } from "#app/phases/turn-start-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Command } from "#app/ui/command-ui-handler"; +import TargetSelectUiHandler from "#app/ui/target-select-ui-handler"; +import { Mode } from "#app/ui/ui"; import { Abilities } from "#enums/abilities"; +import { Button } from "#enums/buttons"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { EnemyCommandPhase } from "#app/phases/enemy-command-phase.js"; +import { SelectTargetPhase } from "#app/phases/select-target-phase.js"; +import { TurnStartPhase } from "#app/phases/turn-start-phase.js"; describe("Battle order", () => { @@ -33,14 +39,20 @@ describe("Battle order", () => { game.override.moveset([Moves.TACKLE]); }); - it("opponent faster than player 50 vs 150", async () => { + it("opponent faster than player 50 vs 150", async() => { await game.startBattle([ Species.BULBASAUR, ]); game.scene.getParty()[0].stats[Stat.SPD] = 50; game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 150; - game.move.select(Moves.TACKLE); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.phaseInterceptor.run(EnemyCommandPhase); const phase = game.scene.getCurrentPhase() as TurnStartPhase; const order = phase.getOrder(); @@ -48,14 +60,20 @@ describe("Battle order", () => { expect(order[1]).toBe(0); }, 20000); - it("Player faster than opponent 150 vs 50", async () => { + it("Player faster than opponent 150 vs 50", async() => { await game.startBattle([ Species.BULBASAUR, ]); game.scene.getParty()[0].stats[Stat.SPD] = 150; game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 50; - game.move.select(Moves.TACKLE); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.phaseInterceptor.run(EnemyCommandPhase); const phase = game.scene.getCurrentPhase() as TurnStartPhase; const order = phase.getOrder(); @@ -63,7 +81,7 @@ describe("Battle order", () => { expect(order[1]).toBe(2); }, 20000); - it("double - both opponents faster than player 50/50 vs 150/150", async () => { + it("double - both opponents faster than player 50/50 vs 150/150", async() => { game.override.battleType("double"); await game.startBattle([ Species.BULBASAUR, @@ -74,8 +92,28 @@ describe("Battle order", () => { game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 150; game.scene.currentBattle.enemyParty[1].stats[Stat.SPD] = 150; - game.move.select(Moves.TACKLE); - game.move.select(Moves.TACKLE, 1); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + game.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = game.scene.ui.getHandler() as TargetSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + game.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = game.scene.ui.getHandler() as TargetSelectUiHandler; + handler.processInput(Button.ACTION); + }); await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false); const phase = game.scene.getCurrentPhase() as TurnStartPhase; const order = phase.getOrder(); @@ -85,7 +123,7 @@ describe("Battle order", () => { expect(order.indexOf(1)).toBeGreaterThan(order.indexOf(3)); }, 20000); - it("double - speed tie except 1 - 100/100 vs 100/150", async () => { + it("double - speed tie except 1 - 100/100 vs 100/150", async() => { game.override.battleType("double"); await game.startBattle([ Species.BULBASAUR, @@ -96,8 +134,28 @@ describe("Battle order", () => { game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 100; game.scene.currentBattle.enemyParty[1].stats[Stat.SPD] = 150; - game.move.select(Moves.TACKLE); - game.move.select(Moves.TACKLE, 1); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + game.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = game.scene.ui.getHandler() as TargetSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + game.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = game.scene.ui.getHandler() as TargetSelectUiHandler; + handler.processInput(Button.ACTION); + }); await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false); const phase = game.scene.getCurrentPhase() as TurnStartPhase; const order = phase.getOrder(); @@ -106,7 +164,7 @@ describe("Battle order", () => { expect(order.indexOf(3)).toBeLessThan(order.indexOf(2)); }, 20000); - it("double - speed tie 100/150 vs 100/150", async () => { + it("double - speed tie 100/150 vs 100/150", async() => { game.override.battleType("double"); await game.startBattle([ Species.BULBASAUR, @@ -117,8 +175,28 @@ describe("Battle order", () => { game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 100; game.scene.currentBattle.enemyParty[1].stats[Stat.SPD] = 150; - game.move.select(Moves.TACKLE); - game.move.select(Moves.TACKLE, 1); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + game.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = game.scene.ui.getHandler() as TargetSelectUiHandler; + handler.processInput(Button.ACTION); + }); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + game.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = game.scene.ui.getHandler() as TargetSelectUiHandler; + handler.processInput(Button.ACTION); + }); await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false); const phase = game.scene.getCurrentPhase() as TurnStartPhase; const order = phase.getOrder(); diff --git a/src/test/battle/battle.test.ts b/src/test/battle/battle.test.ts index c79eee63a7c..43d8ddce4b0 100644 --- a/src/test/battle/battle.test.ts +++ b/src/test/battle/battle.test.ts @@ -1,23 +1,10 @@ import { allSpecies } from "#app/data/pokemon-species"; -import { TempBattleStat } from "#app/data/temp-battle-stat"; -import { GameModes, getGameMode } from "#app/game-mode"; -import { BattleEndPhase } from "#app/phases/battle-end-phase"; -import { CommandPhase } from "#app/phases/command-phase"; -import { DamagePhase } from "#app/phases/damage-phase"; -import { EncounterPhase } from "#app/phases/encounter-phase"; -import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; -import { LoginPhase } from "#app/phases/login-phase"; -import { NextEncounterPhase } from "#app/phases/next-encounter-phase"; -import { SelectGenderPhase } from "#app/phases/select-gender-phase"; -import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; -import { SelectStarterPhase } from "#app/phases/select-starter-phase"; -import { SummonPhase } from "#app/phases/summon-phase"; -import { SwitchPhase } from "#app/phases/switch-phase"; -import { TitlePhase } from "#app/phases/title-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; -import { VictoryPhase } from "#app/phases/victory-phase"; +import { TempBattleStat } from "#app/data/temp-battle-stat.js"; +import { GameModes } from "#app/game-mode"; +import { getGameMode } from "#app/game-mode.js"; import GameManager from "#app/test/utils/gameManager"; -import { generateStarter } from "#app/test/utils/gameManagerUtils"; +import { generateStarter, getMovePosition, } from "#app/test/utils/gameManagerUtils"; +import { Command } from "#app/ui/command-ui-handler"; import { Mode } from "#app/ui/ui"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; @@ -26,6 +13,21 @@ import { Species } from "#enums/species"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { SPLASH_ONLY } from "../utils/testUtils"; +import { BattleEndPhase } from "#app/phases/battle-end-phase.js"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { DamagePhase } from "#app/phases/damage-phase.js"; +import { EncounterPhase } from "#app/phases/encounter-phase.js"; +import { EnemyCommandPhase } from "#app/phases/enemy-command-phase.js"; +import { LoginPhase } from "#app/phases/login-phase.js"; +import { NextEncounterPhase } from "#app/phases/next-encounter-phase.js"; +import { SelectGenderPhase } from "#app/phases/select-gender-phase.js"; +import { SelectModifierPhase } from "#app/phases/select-modifier-phase.js"; +import { SelectStarterPhase } from "#app/phases/select-starter-phase.js"; +import { SummonPhase } from "#app/phases/summon-phase.js"; +import { SwitchPhase } from "#app/phases/switch-phase.js"; +import { TitlePhase } from "#app/phases/title-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; +import { VictoryPhase } from "#app/phases/victory-phase.js"; describe("Test Battle Phase", () => { let phaserGame: Phaser.Game; @@ -45,7 +47,7 @@ describe("Test Battle Phase", () => { game = new GameManager(phaserGame); }); - it("test phase interceptor with prompt", async () => { + it("test phase interceptor with prompt", async() => { await game.phaseInterceptor.run(LoginPhase); game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { @@ -63,7 +65,7 @@ describe("Test Battle Phase", () => { expect(game.scene.gameData.gender).toBe(PlayerGender.MALE); }, 20000); - it("test phase interceptor with prompt with preparation for a future prompt", async () => { + it("test phase interceptor with prompt with preparation for a future prompt", async() => { await game.phaseInterceptor.run(LoginPhase); game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { @@ -85,13 +87,13 @@ describe("Test Battle Phase", () => { expect(game.scene.gameData.gender).toBe(PlayerGender.MALE); }, 20000); - it("newGame one-liner", async () => { + it("newGame one-liner", async() => { await game.startBattle(); expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND); expect(game.scene.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name); }, 20000); - it("do attack wave 3 - single battle - regular - OHKO", async () => { + it("do attack wave 3 - single battle - regular - OHKO", async() => { game.override.starterSpecies(Species.MEWTWO); game.override.enemySpecies(Species.RATTATA); game.override.startingLevel(2000); @@ -102,11 +104,17 @@ describe("Test Battle Phase", () => { game.override.enemyAbility(Abilities.HYDRATION); game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); await game.startBattle(); - game.move.select(Moves.TACKLE); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(SelectModifierPhase, false); }, 20000); - it("do attack wave 3 - single battle - regular - NO OHKO with opponent using non damage attack", async () => { + it("do attack wave 3 - single battle - regular - NO OHKO with opponent using non damage attack", async() => { game.override.starterSpecies(Species.MEWTWO); game.override.enemySpecies(Species.RATTATA); game.override.startingLevel(5); @@ -116,11 +124,17 @@ describe("Test Battle Phase", () => { game.override.enemyMoveset([Moves.TAIL_WHIP, Moves.TAIL_WHIP, Moves.TAIL_WHIP, Moves.TAIL_WHIP]); game.override.battleType("single"); await game.startBattle(); - game.move.select(Moves.TACKLE); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase, false); }, 20000); - it("load 100% data file", async () => { + it("load 100% data file", async() => { await game.importData("src/test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; @@ -129,7 +143,7 @@ describe("Test Battle Phase", () => { expect(caughtCount).toBe(Object.keys(allSpecies).length); }, 20000); - it("start battle with selected team", async () => { + it("start battle with selected team", async() => { await game.startBattle([ Species.CHARIZARD, Species.CHANSEY, @@ -140,26 +154,26 @@ describe("Test Battle Phase", () => { expect(game.scene.getParty()[2].species.speciesId).toBe(Species.MEW); }, 20000); - it("test remove random battle seed int", async () => { - for (let i = 0; i < 10; i++) { + it("test remove random battle seed int", async() => { + for (let i=0; i<10; i++) { const rand = game.scene.randBattleSeedInt(16); expect(rand).toBe(15); } }); - it("wrong phase", async () => { + it("wrong phase", async() => { await game.phaseInterceptor.run(LoginPhase); await game.phaseInterceptor.run(LoginPhase).catch((e) => { expect(e).toBe("Wrong phase: this is SelectGenderPhase and not LoginPhase"); }); }, 20000); - it("wrong phase but skip", async () => { + it("wrong phase but skip", async() => { await game.phaseInterceptor.run(LoginPhase); await game.phaseInterceptor.run(LoginPhase, () => game.isCurrentPhase(SelectGenderPhase)); }, 20000); - it("good run", async () => { + it("good run", async() => { await game.phaseInterceptor.run(LoginPhase); game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { game.scene.gameData.gender = PlayerGender.MALE; @@ -169,7 +183,7 @@ describe("Test Battle Phase", () => { await game.phaseInterceptor.run(TitlePhase); }, 20000); - it("good run from select gender to title", async () => { + it("good run from select gender to title", async() => { await game.phaseInterceptor.run(LoginPhase); game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { game.scene.gameData.gender = PlayerGender.MALE; @@ -178,7 +192,7 @@ describe("Test Battle Phase", () => { await game.phaseInterceptor.runFrom(SelectGenderPhase).to(TitlePhase); }, 20000); - it("good run to SummonPhase phase", async () => { + it("good run to SummonPhase phase", async() => { await game.phaseInterceptor.run(LoginPhase); game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { game.scene.gameData.gender = PlayerGender.MALE; @@ -194,7 +208,7 @@ describe("Test Battle Phase", () => { await game.phaseInterceptor.runFrom(SelectGenderPhase).to(SummonPhase); }, 20000); - it("2vs1", async () => { + it("2vs1", async() => { game.override.battleType("single"); game.override.enemySpecies(Species.MIGHTYENA); game.override.enemyAbility(Abilities.HYDRATION); @@ -207,7 +221,7 @@ describe("Test Battle Phase", () => { expect(game.scene.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name); }, 20000); - it("1vs1", async () => { + it("1vs1", async() => { game.override.battleType("single"); game.override.enemySpecies(Species.MIGHTYENA); game.override.enemyAbility(Abilities.HYDRATION); @@ -219,7 +233,7 @@ describe("Test Battle Phase", () => { expect(game.scene.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name); }, 20000); - it("2vs2", async () => { + it("2vs2", async() => { game.override.battleType("double"); game.override.enemySpecies(Species.MIGHTYENA); game.override.enemyAbility(Abilities.HYDRATION); @@ -233,7 +247,7 @@ describe("Test Battle Phase", () => { expect(game.scene.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name); }, 20000); - it("4vs2", async () => { + it("4vs2", async() => { game.override.battleType("double"); game.override.enemySpecies(Species.MIGHTYENA); game.override.enemyAbility(Abilities.HYDRATION); @@ -249,7 +263,7 @@ describe("Test Battle Phase", () => { expect(game.scene.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name); }, 20000); - it("kill opponent pokemon", async () => { + it("kill opponent pokemon", async() => { const moveToUse = Moves.SPLASH; game.override.battleType("single"); game.override.starterSpecies(Species.MEWTWO); @@ -259,20 +273,26 @@ describe("Test Battle Phase", () => { game.override.startingLevel(2000); game.override.startingWave(3); game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); await game.startBattle([ Species.DARMANITAN, Species.CHARIZARD, ]); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.phaseInterceptor.to(DamagePhase, false); await game.killPokemon(game.scene.currentBattle.enemyParty[0]); expect(game.scene.currentBattle.enemyParty[0].isFainted()).toBe(true); await game.phaseInterceptor.to(VictoryPhase, false); }, 200000); - it("to next turn", async () => { + it("to next turn", async() => { const moveToUse = Moves.SPLASH; game.override.battleType("single"); game.override.starterSpecies(Species.MEWTWO); @@ -282,15 +302,15 @@ describe("Test Battle Phase", () => { game.override.startingLevel(2000); game.override.startingWave(3); game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); await game.startBattle(); const turn = game.scene.currentBattle.turn; - game.move.select(moveToUse); + game.doAttack(0); await game.toNextTurn(); expect(game.scene.currentBattle.turn).toBeGreaterThan(turn); }, 20000); - it("to next wave with pokemon killed, single", async () => { + it("to next wave with pokemon killed, single", async() => { const moveToUse = Moves.SPLASH; game.override.battleType("single"); game.override.starterSpecies(Species.MEWTWO); @@ -300,10 +320,10 @@ describe("Test Battle Phase", () => { game.override.startingLevel(2000); game.override.startingWave(3); game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); await game.startBattle(); const waveIndex = game.scene.currentBattle.waveIndex; - game.move.select(moveToUse); + game.doAttack(0); await game.doKillOpponents(); await game.toNextWave(); expect(game.scene.currentBattle.waveIndex).toBeGreaterThan(waveIndex); @@ -323,7 +343,7 @@ describe("Test Battle Phase", () => { await game.startBattle(); game.scene.getPlayerPokemon()!.hp = 1; - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(BattleEndPhase); game.doRevivePokemon(0); // pretend max revive was picked diff --git a/src/test/battle/damage_calculation.test.ts b/src/test/battle/damage_calculation.test.ts deleted file mode 100644 index 665000450be..00000000000 --- a/src/test/battle/damage_calculation.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { DamagePhase } from "#app/phases/damage-phase.js"; -import { toDmgValue } from "#app/utils"; -import { Abilities } from "#enums/abilities"; -import { ArenaTagType } from "#enums/arena-tag-type"; -import { Moves } from "#enums/moves"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - -describe("Round Down and Minimun 1 test in Damage Calculation", () => { - 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"); - game.override.startingLevel(10); - }); - - it("When the user fails to use Jump Kick with Wonder Guard ability, the damage should be 1.", async () => { - game.override.enemySpecies(Species.GASTLY); - game.override.enemyMoveset(SPLASH_ONLY); - game.override.starterSpecies(Species.SHEDINJA); - game.override.moveset([Moves.JUMP_KICK]); - game.override.ability(Abilities.WONDER_GUARD); - - await game.startBattle(); - - const shedinja = game.scene.getPlayerPokemon()!; - - game.move.select(Moves.JUMP_KICK); - - await game.phaseInterceptor.to(DamagePhase); - - expect(shedinja.hp).toBe(shedinja.getMaxHp() - 1); - }); - - - it("Charizard with odd HP survives Stealth Rock damage twice", async () => { - game.scene.arena.addTag(ArenaTagType.STEALTH_ROCK, 1, Moves.STEALTH_ROCK, 0); - game.override.seed("Charizard Stealth Rock test"); - game.override.enemySpecies(Species.CHARIZARD); - game.override.enemyAbility(Abilities.BLAZE); - game.override.starterSpecies(Species.PIKACHU); - game.override.enemyLevel(100); - - await game.startBattle(); - - const charizard = game.scene.getEnemyPokemon()!; - - const maxHp = charizard.getMaxHp(); - const damage_prediction = toDmgValue(charizard.getMaxHp() / 2); - const currentHp = charizard.hp; - const expectedHP = maxHp - damage_prediction; - - expect(currentHp).toBe(expectedHP); - }); -}); diff --git a/src/test/battle/double_battle.test.ts b/src/test/battle/double_battle.test.ts index d264a29ef9b..d2ee3812b3e 100644 --- a/src/test/battle/double_battle.test.ts +++ b/src/test/battle/double_battle.test.ts @@ -1,12 +1,13 @@ -import { Status, StatusEffect } from "#app/data/status-effect"; -import { BattleEndPhase } from "#app/phases/battle-end-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition, } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { Status, StatusEffect } from "#app/data/status-effect.js"; +import { BattleEndPhase } from "#app/phases/battle-end-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; describe("Double Battles", () => { let phaserGame: Phaser.Game; @@ -28,7 +29,7 @@ describe("Double Battles", () => { // double-battle player's pokemon both fainted in same round, then revive one, and next double battle summons two player's pokemon successfully. // (There were bugs that either only summon one when can summon two, player stuck in switchPhase etc) - it("3v2 edge case: player summons 2 pokemon on the next battle after being fainted and revived", async () => { + it("3v2 edge case: player summons 2 pokemon on the next battle after being fainted and revived", async() => { game.override.battleType("double").enemyMoveset(SPLASH_ONLY).moveset(SPLASH_ONLY); await game.startBattle([ Species.BULBASAUR, @@ -36,8 +37,8 @@ describe("Double Battles", () => { Species.SQUIRTLE, ]); - game.move.select(Moves.SPLASH); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); for (const pokemon of game.scene.getPlayerField()) { pokemon.hp = 0; diff --git a/src/test/battle/error-handling.test.ts b/src/test/battle/error-handling.test.ts index da5cc4d1969..a88d7cd8c18 100644 --- a/src/test/battle/error-handling.test.ts +++ b/src/test/battle/error-handling.test.ts @@ -1,14 +1,13 @@ +import GameManager from "#test/utils/gameManager"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; describe("Error Handling", () => { let phaserGame: Phaser.Game; let game: GameManager; - const moveToUse = Moves.SPLASH; beforeAll(() => { phaserGame = new Phaser.Game({ @@ -22,6 +21,7 @@ describe("Error Handling", () => { beforeEach(() => { game = new GameManager(phaserGame); + const moveToUse = Moves.SPLASH; game.override .battleType("single") .startingWave(3); @@ -31,13 +31,13 @@ describe("Error Handling", () => { game.override.ability(Abilities.ZEN_MODE); game.override.startingLevel(2000); game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); - it.skip("to next turn", async () => { + it.skip("to next turn", async() => { await game.startBattle(); const turn = game.scene.currentBattle.turn; - game.move.select(moveToUse); + game.doAttack(0); await game.toNextTurn(); expect(game.scene.currentBattle.turn).toBeGreaterThan(turn); }, 20000); diff --git a/src/test/battle/special_battle.test.ts b/src/test/battle/special_battle.test.ts index 1d319bea372..9b0fd1b3ab1 100644 --- a/src/test/battle/special_battle.test.ts +++ b/src/test/battle/special_battle.test.ts @@ -1,9 +1,9 @@ -import { CommandPhase } from "#app/phases/command-phase"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import GameManager from "#test/utils/gameManager"; import { Mode } from "#app/ui/ui"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; diff --git a/src/test/battlerTags/octolock.test.ts b/src/test/battlerTags/octolock.test.ts index fa491589f09..a69b45cdfd2 100644 --- a/src/test/battlerTags/octolock.test.ts +++ b/src/test/battlerTags/octolock.test.ts @@ -1,10 +1,10 @@ -import BattleScene from "#app/battle-scene"; -import { BattleStat } from "#app/data/battle-stat"; -import { BattlerTag, BattlerTagLapseType, OctolockTag, TrappedTag } from "#app/data/battler-tags"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import Pokemon from "#app/field/pokemon"; -import { StatChangePhase } from "#app/phases/stat-change-phase"; import { describe, expect, it, vi } from "vitest"; +import Pokemon from "#app/field/pokemon.js"; +import BattleScene from "#app/battle-scene.js"; +import { BattlerTag, BattlerTagLapseType, OctolockTag, TrappedTag } from "#app/data/battler-tags.js"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { StatChangePhase } from "#app/phases/stat-change-phase.js"; vi.mock("#app/battle-scene.js"); diff --git a/src/test/battlerTags/stockpiling.test.ts b/src/test/battlerTags/stockpiling.test.ts index fef1e938c09..1a39d11e1bd 100644 --- a/src/test/battlerTags/stockpiling.test.ts +++ b/src/test/battlerTags/stockpiling.test.ts @@ -1,10 +1,10 @@ -import BattleScene from "#app/battle-scene"; -import { BattleStat } from "#app/data/battle-stat"; -import { StockpilingTag } from "#app/data/battler-tags"; -import Pokemon, { PokemonSummonData } from "#app/field/pokemon"; -import * as messages from "#app/messages"; -import { StatChangePhase } from "#app/phases/stat-change-phase"; import { beforeEach, describe, expect, it, vi } from "vitest"; +import Pokemon, { PokemonSummonData } from "#app/field/pokemon.js"; +import BattleScene from "#app/battle-scene.js"; +import { StockpilingTag } from "#app/data/battler-tags.js"; +import { BattleStat } from "#app/data/battle-stat.js"; +import * as messages from "#app/messages.js"; +import { StatChangePhase } from "#app/phases/stat-change-phase.js"; beforeEach(() => { vi.spyOn(messages, "getPokemonNameWithAffix").mockImplementation(() => ""); diff --git a/src/test/eggs/egg.test.ts b/src/test/eggs/egg.test.ts index a01d2257099..0bc2972e2dc 100644 --- a/src/test/eggs/egg.test.ts +++ b/src/test/eggs/egg.test.ts @@ -1,14 +1,14 @@ -import { Egg, getLegendaryGachaSpeciesForTimestamp } from "#app/data/egg"; -import { EggSourceType } from "#app/enums/egg-source-types"; -import { EggTier } from "#app/enums/egg-type"; -import { VariantTier } from "#app/enums/variant-tiers"; -import EggData from "#app/system/egg-data"; -import * as Utils from "#app/utils"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import BattleScene from "../../battle-scene"; +import { Egg, getLegendaryGachaSpeciesForTimestamp } from "#app/data/egg.js"; +import { Species } from "#enums/species"; +import Phaser from "phaser"; +import { EggSourceType } from "#app/enums/egg-source-types.js"; +import { EggTier } from "#app/enums/egg-type.js"; +import { VariantTier } from "#app/enums/variant-tiers.js"; +import GameManager from "#test/utils/gameManager"; +import EggData from "#app/system/egg-data.js"; +import * as Utils from "#app/utils.js"; describe("Egg Generation Tests", () => { let phaserGame: Phaser.Game; diff --git a/src/test/evolution.test.ts b/src/test/evolution.test.ts index 41088c17bcb..b54deaa4611 100644 --- a/src/test/evolution.test.ts +++ b/src/test/evolution.test.ts @@ -1,6 +1,6 @@ -import { pokemonEvolutions, SpeciesFormEvolution, SpeciesWildEvolutionDelay } from "#app/data/pokemon-evolutions"; -import { Abilities } from "#app/enums/abilities"; -import { Species } from "#app/enums/species"; +import { pokemonEvolutions, SpeciesFormEvolution, SpeciesWildEvolutionDelay } from "#app/data/pokemon-evolutions.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { Species } from "#app/enums/species.js"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; diff --git a/src/test/evolutions/evolutions.test.ts b/src/test/evolutions/evolutions.test.ts index 2028764115c..af43e91b059 100644 --- a/src/test/evolutions/evolutions.test.ts +++ b/src/test/evolutions/evolutions.test.ts @@ -1,8 +1,8 @@ -import * as Utils from "#app/utils"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { Species } from "#enums/species"; +import * as Utils from "#app/utils"; describe("Evolution tests", () => { let phaserGame: Phaser.Game; diff --git a/src/test/field/pokemon.test.ts b/src/test/field/pokemon.test.ts index d597cd5219c..ee8e41e8b42 100644 --- a/src/test/field/pokemon.test.ts +++ b/src/test/field/pokemon.test.ts @@ -1,4 +1,4 @@ -import { Species } from "#app/enums/species"; +import { Species } from "#app/enums/species.js"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import GameManager from "../utils/gameManager"; diff --git a/src/test/final_boss.test.ts b/src/test/final_boss.test.ts index 0f59572619b..a57d71534a3 100644 --- a/src/test/final_boss.test.ts +++ b/src/test/final_boss.test.ts @@ -1,8 +1,8 @@ -import { Biome } from "#app/enums/biome"; -import { Species } from "#app/enums/species"; -import { GameModes } from "#app/game-mode"; +import { Biome } from "#app/enums/biome.js"; +import { Species } from "#app/enums/species.js"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import GameManager from "./utils/gameManager"; +import { GameModes } from "#app/game-mode"; const FinalWave = { Classic: 200, diff --git a/src/test/game-mode.test.ts b/src/test/game-mode.test.ts index ccec3a3aa16..4a1960a05ff 100644 --- a/src/test/game-mode.test.ts +++ b/src/test/game-mode.test.ts @@ -1,7 +1,7 @@ -import { GameMode, GameModes, getGameMode } from "#app/game-mode"; +import { GameMode, GameModes, getGameMode } from "#app/game-mode.js"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import * as Utils from "../utils"; import GameManager from "./utils/gameManager"; +import * as Utils from "../utils"; describe("game-mode", () => { let phaserGame: Phaser.Game; let game: GameManager; diff --git a/src/test/imports.test.ts b/src/test/imports.test.ts index 305eccdc465..69c145236bc 100644 --- a/src/test/imports.test.ts +++ b/src/test/imports.test.ts @@ -1,5 +1,5 @@ -import { initStatsKeys } from "#app/ui/game-stats-ui-handler"; import { describe, expect, it } from "vitest"; +import { initStatsKeys } from "#app/ui/game-stats-ui-handler"; async function importModule() { try { diff --git a/src/test/inputs/inputs.test.ts b/src/test/inputs/inputs.test.ts index 6306c1b9da6..7182ac2c02c 100644 --- a/src/test/inputs/inputs.test.ts +++ b/src/test/inputs/inputs.test.ts @@ -1,9 +1,9 @@ -import cfg_keyboard_qwerty from "#app/configs/inputs/cfg_keyboard_qwerty"; -import pad_xbox360 from "#app/configs/inputs/pad_xbox360"; -import GameManager from "#test/utils/gameManager"; -import InputsHandler from "#test/utils/inputsHandler"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import pad_xbox360 from "#app/configs/inputs/pad_xbox360"; +import cfg_keyboard_qwerty from "#app/configs/inputs/cfg_keyboard_qwerty"; +import InputsHandler from "#test/utils/inputsHandler"; describe("Inputs", () => { diff --git a/src/test/internals.test.ts b/src/test/internals.test.ts index 3c76b40e901..0ecd156431d 100644 --- a/src/test/internals.test.ts +++ b/src/test/internals.test.ts @@ -1,8 +1,8 @@ -import { Abilities } from "#app/enums/abilities"; -import { Species } from "#app/enums/species"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { Species } from "#app/enums/species.js"; +import { Abilities } from "#app/enums/abilities.js"; describe("Internals", () => { let phaserGame: Phaser.Game; diff --git a/src/test/items/eviolite.test.ts b/src/test/items/eviolite.test.ts index e491784acec..0fe90866de8 100644 --- a/src/test/items/eviolite.test.ts +++ b/src/test/items/eviolite.test.ts @@ -2,9 +2,9 @@ import { Stat } from "#app/data/pokemon-stat"; import { EvolutionStatBoosterModifier } from "#app/modifier/modifier"; import { modifierTypes } from "#app/modifier/modifier-type"; import i18next from "#app/plugins/i18n"; +import GameManager from "#test/utils/gameManager"; import * as Utils from "#app/utils"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phase from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; diff --git a/src/test/items/exp_booster.test.ts b/src/test/items/exp_booster.test.ts index 9a7464e4866..2b700c92086 100644 --- a/src/test/items/exp_booster.test.ts +++ b/src/test/items/exp_booster.test.ts @@ -1,7 +1,7 @@ -import { Abilities } from "#app/enums/abilities"; -import { PokemonExpBoosterModifier } from "#app/modifier/modifier"; -import * as Utils from "#app/utils"; +import { Abilities } from "#app/enums/abilities.js"; +import { PokemonExpBoosterModifier } from "#app/modifier/modifier.js"; import GameManager from "#test/utils/gameManager"; +import * as Utils from "#app/utils"; import Phase from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; diff --git a/src/test/items/grip_claw.test.ts b/src/test/items/grip_claw.test.ts index 09afa9aea0b..ecf144c96c5 100644 --- a/src/test/items/grip_claw.test.ts +++ b/src/test/items/grip_claw.test.ts @@ -1,14 +1,16 @@ -import { BattlerIndex } from "#app/battle"; -import { allMoves } from "#app/data/move"; -import { Abilities } from "#app/enums/abilities"; -import { BerryType } from "#app/enums/berry-type"; -import { Moves } from "#app/enums/moves"; -import { Species } from "#app/enums/species"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; +import { BattlerIndex } from "#app/battle.js"; +import { allMoves } from "#app/data/move.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { BerryType } from "#app/enums/berry-type.js"; +import { Moves } from "#app/enums/moves.js"; +import { Species } from "#app/enums/species.js"; import GameManager from "#test/utils/gameManager"; import Phase from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { SPLASH_ONLY } from "../utils/testUtils"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { SelectTargetPhase } from "#app/phases/select-target-phase.js"; const TIMEOUT = 20 * 1000; // 20 seconds @@ -33,12 +35,12 @@ describe("Items - Grip Claw", () => { .battleType("double") .moveset([Moves.POPULATION_BOMB, Moves.SPLASH]) .startingHeldItems([ - { name: "GRIP_CLAW", count: 5 }, // TODO: Find a way to mock the steal chance of grip claw + { name: "GRIP_CLAW", count: 5 }, { name: "MULTI_LENS", count: 3 }, ]) .enemySpecies(Species.SNORLAX) .ability(Abilities.KLUTZ) - .enemyMoveset(SPLASH_ONLY) + .enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]) .enemyHeldItems([ { name: "BERRY", type: BerryType.SITRUS, count: 2 }, { name: "BERRY", type: BerryType.LUM, count: 2 }, @@ -52,14 +54,19 @@ describe("Items - Grip Claw", () => { it( "should only steal items from the attack target", async () => { - await game.startBattle([Species.PANSEAR, Species.ROWLET]); + await game.startBattle([Species.PANSEAR, Species.ROWLET, Species.PANPOUR, Species.PANSAGE, Species.CHARMANDER, Species.SQUIRTLE]); const enemyPokemon = game.scene.getEnemyField(); const enemyHeldItemCt = enemyPokemon.map(p => p.getHeldItems.length); - game.move.select(Moves.POPULATION_BOMB, 0, BattlerIndex.ENEMY); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.POPULATION_BOMB)); + + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY); + + await game.phaseInterceptor.to(CommandPhase, false); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(MoveEndPhase, false); diff --git a/src/test/items/leek.test.ts b/src/test/items/leek.test.ts index 7505b6374a0..1e46bda9f0f 100644 --- a/src/test/items/leek.test.ts +++ b/src/test/items/leek.test.ts @@ -1,11 +1,11 @@ import { BattlerIndex } from "#app/battle"; import { CritBoosterModifier } from "#app/modifier/modifier"; import { modifierTypes } from "#app/modifier/modifier-type"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import GameManager from "#test/utils/gameManager"; import * as Utils from "#app/utils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phase from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; @@ -27,21 +27,21 @@ describe("Items - Leek", () => { game = new GameManager(phaserGame); game.override.enemySpecies(Species.MAGIKARP); - game.override.enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); game.override.disableCrits(); game.override.battleType("single"); }); - it("LEEK activates in battle correctly", async () => { + it("LEEK activates in battle correctly", async() => { game.override.startingHeldItems([{ name: "LEEK" }]); - game.override.moveset([Moves.POUND]); + game.override.moveset([ Moves.POUND ]); const consoleSpy = vi.spyOn(console, "log"); await game.startBattle([ Species.FARFETCHD ]); - game.move.select(Moves.POUND); + game.doAttack(0); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); @@ -50,7 +50,7 @@ describe("Items - Leek", () => { expect(consoleSpy).toHaveBeenCalledWith("Applied", "Leek", ""); }, 20000); - it("LEEK held by FARFETCHD", async () => { + it("LEEK held by FARFETCHD", async() => { await game.startBattle([ Species.FARFETCHD ]); @@ -70,7 +70,7 @@ describe("Items - Leek", () => { expect(critLevel.value).toBe(2); }, 20000); - it("LEEK held by GALAR_FARFETCHD", async () => { + it("LEEK held by GALAR_FARFETCHD", async() => { await game.startBattle([ Species.GALAR_FARFETCHD ]); @@ -90,7 +90,7 @@ describe("Items - Leek", () => { expect(critLevel.value).toBe(2); }, 20000); - it("LEEK held by SIRFETCHD", async () => { + it("LEEK held by SIRFETCHD", async() => { await game.startBattle([ Species.SIRFETCHD ]); @@ -110,9 +110,9 @@ describe("Items - Leek", () => { expect(critLevel.value).toBe(2); }, 20000); - it("LEEK held by fused FARFETCHD line (base)", async () => { + it("LEEK held by fused FARFETCHD line (base)", async() => { // Randomly choose from the Farfetch'd line - const species = [Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD]; + const species = [ Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD ]; await game.startBattle([ species[Utils.randInt(species.length)], @@ -145,9 +145,9 @@ describe("Items - Leek", () => { expect(critLevel.value).toBe(2); }, 20000); - it("LEEK held by fused FARFETCHD line (part)", async () => { + it("LEEK held by fused FARFETCHD line (part)", async() => { // Randomly choose from the Farfetch'd line - const species = [Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD]; + const species = [ Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD ]; await game.startBattle([ Species.PIKACHU, @@ -180,7 +180,7 @@ describe("Items - Leek", () => { expect(critLevel.value).toBe(2); }, 20000); - it("LEEK not held by FARFETCHD line", async () => { + it("LEEK not held by FARFETCHD line", async() => { await game.startBattle([ Species.PIKACHU ]); diff --git a/src/test/items/leftovers.test.ts b/src/test/items/leftovers.test.ts index 8e548542436..1a1c95ad9e6 100644 --- a/src/test/items/leftovers.test.ts +++ b/src/test/items/leftovers.test.ts @@ -1,11 +1,12 @@ -import { DamagePhase } from "#app/phases/damage-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { DamagePhase } from "#app/phases/damage-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Items - Leftovers", () => { @@ -31,10 +32,10 @@ describe("Items - Leftovers", () => { game.override.enemySpecies(Species.SHUCKLE); game.override.enemyAbility(Abilities.UNNERVE); game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); - game.override.startingHeldItems([{ name: "LEFTOVERS", count: 1 }]); + game.override.startingHeldItems([{name: "LEFTOVERS", count: 1}]); }); - it("leftovers works", async () => { + it("leftovers works", async() => { await game.startBattle([Species.ARCANINE]); // Make sure leftovers are there @@ -45,7 +46,7 @@ describe("Items - Leftovers", () => { // We should have full hp expect(leadPokemon.isFullHp()).toBe(true); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); // We should have less hp after the attack await game.phaseInterceptor.to(DamagePhase, false); diff --git a/src/test/items/light_ball.test.ts b/src/test/items/light_ball.test.ts index cf4f5c9e22f..ff7dfa4eba5 100644 --- a/src/test/items/light_ball.test.ts +++ b/src/test/items/light_ball.test.ts @@ -2,9 +2,9 @@ import { Stat } from "#app/data/pokemon-stat"; import { SpeciesStatBoosterModifier } from "#app/modifier/modifier"; import { modifierTypes } from "#app/modifier/modifier-type"; import i18next from "#app/plugins/i18n"; +import GameManager from "#test/utils/gameManager"; import * as Utils from "#app/utils"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phase from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; diff --git a/src/test/items/lock_capsule.test.ts b/src/test/items/lock_capsule.test.ts index bc4ca1cb014..0909e51ea2c 100644 --- a/src/test/items/lock_capsule.test.ts +++ b/src/test/items/lock_capsule.test.ts @@ -1,10 +1,11 @@ -import { Abilities } from "#app/enums/abilities"; -import { Moves } from "#app/enums/moves"; -import { ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type"; -import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import GameManager from "#test/utils/gameManager"; import Phase from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { Abilities } from "#app/enums/abilities.js"; +import { Moves } from "#app/enums/moves.js"; +import { getMovePosition } from "../utils/gameManagerUtils"; +import { ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type.js"; +import { SelectModifierPhase } from "#app/phases/select-modifier-phase.js"; describe("Items - Lock Capsule", () => { let phaserGame: Phaser.Game; @@ -28,13 +29,13 @@ describe("Items - Lock Capsule", () => { .startingLevel(200) .moveset([Moves.SURF]) .enemyAbility(Abilities.BALL_FETCH) - .startingModifier([{ name: "LOCK_CAPSULE" }]); + .startingModifier([{name: "LOCK_CAPSULE"}]); }); - it("doesn't set the cost of common tier items to 0", async () => { + it("doesn't set the cost of common tier items to 0", async() => { await game.startBattle(); - game.move.select(Moves.SURF); + game.doAttack(getMovePosition(game.scene, 0, Moves.SURF)); await game.phaseInterceptor.to(SelectModifierPhase, false); const rewards = game.scene.getCurrentPhase() as SelectModifierPhase; diff --git a/src/test/items/metal_powder.test.ts b/src/test/items/metal_powder.test.ts index a3a4936532f..966762e4175 100644 --- a/src/test/items/metal_powder.test.ts +++ b/src/test/items/metal_powder.test.ts @@ -2,9 +2,9 @@ import { Stat } from "#app/data/pokemon-stat"; import { SpeciesStatBoosterModifier } from "#app/modifier/modifier"; import { modifierTypes } from "#app/modifier/modifier-type"; import i18next from "#app/plugins/i18n"; +import GameManager from "#test/utils/gameManager"; import * as Utils from "#app/utils"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phase from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; diff --git a/src/test/items/quick_powder.test.ts b/src/test/items/quick_powder.test.ts index 53521ba78f1..d2435dab431 100644 --- a/src/test/items/quick_powder.test.ts +++ b/src/test/items/quick_powder.test.ts @@ -2,9 +2,9 @@ import { Stat } from "#app/data/pokemon-stat"; import { SpeciesStatBoosterModifier } from "#app/modifier/modifier"; import { modifierTypes } from "#app/modifier/modifier-type"; import i18next from "#app/plugins/i18n"; +import GameManager from "#test/utils/gameManager"; import * as Utils from "#app/utils"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phase from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; diff --git a/src/test/items/scope_lens.test.ts b/src/test/items/scope_lens.test.ts index 85673218762..fa605ca7129 100644 --- a/src/test/items/scope_lens.test.ts +++ b/src/test/items/scope_lens.test.ts @@ -1,11 +1,11 @@ import { BattlerIndex } from "#app/battle"; import { CritBoosterModifier } from "#app/modifier/modifier"; import { modifierTypes } from "#app/modifier/modifier-type"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import GameManager from "#test/utils/gameManager"; import * as Utils from "#app/utils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phase from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; @@ -27,30 +27,30 @@ describe("Items - Scope Lens", () => { game = new GameManager(phaserGame); game.override.enemySpecies(Species.MAGIKARP); - game.override.enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); game.override.disableCrits(); game.override.battleType("single"); }, 20000); - it("SCOPE_LENS activates in battle correctly", async () => { + it("SCOPE_LENS activates in battle correctly", async() => { game.override.startingHeldItems([{ name: "SCOPE_LENS" }]); - game.override.moveset([Moves.POUND]); + game.override.moveset([ Moves.POUND ]); const consoleSpy = vi.spyOn(console, "log"); await game.startBattle([ Species.GASTLY ]); - game.move.select(Moves.POUND); + game.doAttack(0); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase); expect(consoleSpy).toHaveBeenCalledWith("Applied", "Scope Lens", ""); }, 20000); - it("SCOPE_LENS held by random pokemon", async () => { + it("SCOPE_LENS held by random pokemon", async() => { await game.startBattle([ Species.GASTLY ]); diff --git a/src/test/items/thick_club.test.ts b/src/test/items/thick_club.test.ts index 347921446e6..841cd7c90ac 100644 --- a/src/test/items/thick_club.test.ts +++ b/src/test/items/thick_club.test.ts @@ -2,9 +2,9 @@ import { Stat } from "#app/data/pokemon-stat"; import { SpeciesStatBoosterModifier } from "#app/modifier/modifier"; import { modifierTypes } from "#app/modifier/modifier-type"; import i18next from "#app/plugins/i18n"; +import GameManager from "#test/utils/gameManager"; import * as Utils from "#app/utils"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phase from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; diff --git a/src/test/items/toxic_orb.test.ts b/src/test/items/toxic_orb.test.ts index 95336c0793e..dc54a5a1c36 100644 --- a/src/test/items/toxic_orb.test.ts +++ b/src/test/items/toxic_orb.test.ts @@ -1,14 +1,18 @@ import { StatusEffect } from "#app/data/status-effect"; -import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; -import { MessagePhase } from "#app/phases/message-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; import i18next, { initI18n } from "#app/plugins/i18n"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Command } from "#app/ui/command-ui-handler"; +import { Mode } from "#app/ui/ui"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { EnemyCommandPhase } from "#app/phases/enemy-command-phase.js"; +import { MessagePhase } from "#app/phases/message-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Items - Toxic orb", () => { @@ -41,7 +45,7 @@ describe("Items - Toxic orb", () => { }]); }); - it("TOXIC ORB", async () => { + it("TOXIC ORB", async() => { initI18n(); i18next.changeLanguage("en"); const moveToUse = Moves.GROWTH; @@ -51,7 +55,15 @@ describe("Items - Toxic orb", () => { ]); expect(game.scene.modifiers[0].type.id).toBe("TOXIC_ORB"); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + // Select Attack + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + // Select Move Growth + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); // will run the 13 phase from enemyCommandPhase to TurnEndPhase await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnEndPhase); diff --git a/src/test/localization/battle-stat.test.ts b/src/test/localization/battle-stat.test.ts index e8fc20ab5a4..b99ed2b7064 100644 --- a/src/test/localization/battle-stat.test.ts +++ b/src/test/localization/battle-stat.test.ts @@ -1,25 +1,26 @@ -import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "#app/data/battle-stat"; -import { battle as deBattleStat } from "#app/locales/de/battle"; -import { pokemonInfo as dePokemonInfo } from "#app/locales/de/pokemon-info"; -import { battle as enBattleStat } from "#app/locales/en/battle"; -import { pokemonInfo as enPokemonInfo } from "#app/locales/en/pokemon-info"; -import { battle as esBattleStat } from "#app/locales/es/battle"; -import { pokemonInfo as esPokemonInfo } from "#app/locales/es/pokemon-info"; -import { battle as frBattleStat } from "#app/locales/fr/battle"; -import { pokemonInfo as frPokemonInfo } from "#app/locales/fr/pokemon-info"; -import { battle as itBattleStat } from "#app/locales/it/battle"; -import { pokemonInfo as itPokemonInfo } from "#app/locales/it/pokemon-info"; -import { battle as koBattleStat } from "#app/locales/ko/battle"; -import { pokemonInfo as koPokemonInfo } from "#app/locales/ko/pokemon-info"; -import { battle as ptBrBattleStat } from "#app/locales/pt_BR/battle"; -import { pokemonInfo as ptBrPokemonInfo } from "#app/locales/pt_BR/pokemon-info"; -import { battle as zhCnBattleStat } from "#app/locales/zh_CN/battle"; -import { pokemonInfo as zhCnPokemonInfo } from "#app/locales/zh_CN/pokemon-info"; -import { battle as zhTwBattleStat } from "#app/locales/zh_TW/battle"; -import { pokemonInfo as zhTwPokemonInfo } from "#app/locales/zh_TW/pokemon-info"; +import { beforeAll, describe, expect, it } from "vitest"; +import { getBattleStatName, getBattleStatLevelChangeDescription } from "#app/data/battle-stat.js"; +import { BattleStat} from "#app/data/battle-stat.js"; +import { pokemonInfo as enPokemonInfo } from "#app/locales/en/pokemon-info.js"; +import { battle as enBattleStat } from "#app/locales/en/battle.js"; +import { pokemonInfo as dePokemonInfo } from "#app/locales/de/pokemon-info.js"; +import { battle as deBattleStat } from "#app/locales/de/battle.js"; +import { pokemonInfo as esPokemonInfo } from "#app/locales/es/pokemon-info.js"; +import { battle as esBattleStat } from "#app/locales/es/battle.js"; +import { pokemonInfo as frPokemonInfo } from "#app/locales/fr/pokemon-info.js"; +import { battle as frBattleStat } from "#app/locales/fr/battle.js"; +import { pokemonInfo as itPokemonInfo } from "#app/locales/it/pokemon-info.js"; +import { battle as itBattleStat } from "#app/locales/it/battle.js"; +import { pokemonInfo as koPokemonInfo } from "#app/locales/ko/pokemon-info.js"; +import { battle as koBattleStat } from "#app/locales/ko/battle.js"; +import { pokemonInfo as ptBrPokemonInfo } from "#app/locales/pt_BR/pokemon-info.js"; +import { battle as ptBrBattleStat } from "#app/locales/pt_BR/battle.js"; +import { pokemonInfo as zhCnPokemonInfo } from "#app/locales/zh_CN/pokemon-info.js"; +import { battle as zhCnBattleStat } from "#app/locales/zh_CN/battle.js"; +import { pokemonInfo as zhTwPokemonInfo } from "#app/locales/zh_TW/pokemon-info.js"; +import { battle as zhTwBattleStat } from "#app/locales/zh_TW/battle.js"; import i18next, { initI18n } from "#app/plugins/i18n"; import { KoreanPostpositionProcessor } from "i18next-korean-postposition-processor"; -import { beforeAll, describe, expect, it } from "vitest"; interface BattleStatTestUnit { stat: BattleStat, diff --git a/src/test/localization/french.test.ts b/src/test/localization/french.test.ts index 92b4c82d7cb..b03a8ee64e8 100644 --- a/src/test/localization/french.test.ts +++ b/src/test/localization/french.test.ts @@ -1,9 +1,9 @@ -import { initI18n } from "#app/plugins/i18n"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import i18next from "i18next"; -import Phaser from "phaser"; import { afterEach, beforeAll, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { Species } from "#enums/species"; +import i18next from "i18next"; +import { initI18n } from "#app/plugins/i18n"; describe("Lokalization - french", () => { let phaserGame: Phaser.Game; diff --git a/src/test/localization/status-effect.test.ts b/src/test/localization/status-effect.test.ts index 9dcab5aeb5f..8a9effe1672 100644 --- a/src/test/localization/status-effect.test.ts +++ b/src/test/localization/status-effect.test.ts @@ -1,7 +1,7 @@ +import { beforeAll, describe, afterEach, expect, it, vi } from "vitest"; import { StatusEffect, getStatusEffectActivationText, getStatusEffectDescriptor, getStatusEffectHealText, getStatusEffectObtainText, getStatusEffectOverlapText } from "#app/data/status-effect"; -import { mockI18next } from "#test/utils/testUtils"; import i18next from "i18next"; -import { afterEach, beforeAll, describe, expect, it, vi } from "vitest"; +import { mockI18next } from "#test/utils/testUtils"; const pokemonName = "PKM"; const sourceText = "SOURCE"; diff --git a/src/test/localization/terrain.test.ts b/src/test/localization/terrain.test.ts index ed280177a06..c072f9cc9ab 100644 --- a/src/test/localization/terrain.test.ts +++ b/src/test/localization/terrain.test.ts @@ -1,11 +1,11 @@ import { TerrainType, getTerrainName } from "#app/data/terrain"; import { getTerrainBlockMessage, getTerrainClearMessage, getTerrainStartMessage } from "#app/data/weather"; -import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; -import { mockI18next } from "#test/utils/testUtils"; +import { Species } from "#enums/species"; import i18next from "i18next"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { mockI18next } from "#test/utils/testUtils"; describe("terrain", () => { let phaserGame: Phaser.Game; diff --git a/src/test/moves/astonish.test.ts b/src/test/moves/astonish.test.ts index b21e2a06051..21a82f09d33 100644 --- a/src/test/moves/astonish.test.ts +++ b/src/test/moves/astonish.test.ts @@ -1,15 +1,16 @@ -import { allMoves } from "#app/data/move"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { CommandPhase } from "#app/phases/command-phase"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { allMoves } from "#app/data/move.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -49,7 +50,7 @@ describe("Moves - Astonish", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.ASTONISH); + game.doAttack(getMovePosition(game.scene, 0, Moves.ASTONISH)); await game.phaseInterceptor.to(MoveEndPhase, false); @@ -62,7 +63,7 @@ describe("Moves - Astonish", () => { await game.phaseInterceptor.to(CommandPhase, false); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(BerryPhase, false); diff --git a/src/test/moves/aurora_veil.test.ts b/src/test/moves/aurora_veil.test.ts index fec280debf4..5429efec2bf 100644 --- a/src/test/moves/aurora_veil.test.ts +++ b/src/test/moves/aurora_veil.test.ts @@ -1,14 +1,15 @@ -import { ArenaTagSide } from "#app/data/arena-tag"; -import Move, { allMoves } from "#app/data/move"; -import { WeatherType } from "#app/data/weather"; -import { Abilities } from "#app/enums/abilities"; -import { ArenaTagType } from "#app/enums/arena-tag-type"; -import Pokemon from "#app/field/pokemon"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { NumberHolder } from "#app/utils"; +import { ArenaTagSide } from "#app/data/arena-tag.js"; +import Move, { allMoves } from "#app/data/move.js"; +import { WeatherType } from "#app/data/weather.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { ArenaTagType } from "#app/enums/arena-tag-type.js"; +import Pokemon from "#app/field/pokemon.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { NumberHolder } from "#app/utils.js"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -17,7 +18,7 @@ describe("Moves - Aurora Veil", () => { let phaserGame: Phaser.Game; let game: GameManager; const singleBattleMultiplier = 0.5; - const doubleBattleMultiplier = 2732 / 4096; + const doubleBattleMultiplier = 2732/4096; beforeAll(() => { phaserGame = new Phaser.Game({ @@ -41,11 +42,11 @@ describe("Moves - Aurora Veil", () => { game.override.weather(WeatherType.HAIL); }); - it("reduces damage of physical attacks by half in a single battle", async () => { + it("reduces damage of physical attacks by half in a single battle", async() => { const moveToUse = Moves.TACKLE; await game.startBattle([Species.SHUCKLE]); - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); const mockedDmg = getMockedMoveDamage(game.scene.getEnemyPokemon()!, game.scene.getPlayerPokemon()!, allMoves[moveToUse]); @@ -53,14 +54,14 @@ describe("Moves - Aurora Veil", () => { expect(mockedDmg).toBe(allMoves[moveToUse].power * singleBattleMultiplier); }); - it("reduces damage of physical attacks by a third in a double battle", async () => { + it("reduces damage of physical attacks by a third in a double battle", async() => { game.override.battleType("double"); const moveToUse = Moves.ROCK_SLIDE; await game.startBattle([Species.SHUCKLE, Species.SHUCKLE]); - game.move.select(moveToUse); - game.move.select(moveToUse, 1); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); + game.doAttack(getMovePosition(game.scene, 1, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); const mockedDmg = getMockedMoveDamage(game.scene.getEnemyPokemon()!, game.scene.getPlayerPokemon()!, allMoves[moveToUse]); @@ -68,11 +69,11 @@ describe("Moves - Aurora Veil", () => { expect(mockedDmg).toBe(allMoves[moveToUse].power * doubleBattleMultiplier); }); - it("reduces damage of special attacks by half in a single battle", async () => { + it("reduces damage of special attacks by half in a single battle", async() => { const moveToUse = Moves.ABSORB; await game.startBattle([Species.SHUCKLE]); - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); @@ -81,14 +82,14 @@ describe("Moves - Aurora Veil", () => { expect(mockedDmg).toBe(allMoves[moveToUse].power * singleBattleMultiplier); }); - it("reduces damage of special attacks by a third in a double battle", async () => { + it("reduces damage of special attacks by a third in a double battle", async() => { game.override.battleType("double"); const moveToUse = Moves.DAZZLING_GLEAM; await game.startBattle([Species.SHUCKLE, Species.SHUCKLE]); - game.move.select(moveToUse); - game.move.select(moveToUse, 1); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); + game.doAttack(getMovePosition(game.scene, 1, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); const mockedDmg = getMockedMoveDamage(game.scene.getEnemyPokemon()!, game.scene.getPlayerPokemon()!, allMoves[moveToUse]); diff --git a/src/test/moves/baton_pass.test.ts b/src/test/moves/baton_pass.test.ts index 602da9e37f8..790eddbf45c 100644 --- a/src/test/moves/baton_pass.test.ts +++ b/src/test/moves/baton_pass.test.ts @@ -1,12 +1,13 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { PostSummonPhase } from "#app/phases/post-summon-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { BattleStat } from "#app/data/battle-stat.js"; import GameManager from "#app/test/utils/gameManager"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { SPLASH_ONLY } from "../utils/testUtils"; +import { PostSummonPhase } from "#app/phases/post-summon-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Moves - Baton Pass", () => { @@ -35,7 +36,7 @@ describe("Moves - Baton Pass", () => { .disableCrits(); }); - it("passes stat stage buffs when player uses it", async () => { + it("passes stat stage buffs when player uses it", async() => { // arrange await game.startBattle([ Species.RAICHU, @@ -43,12 +44,12 @@ describe("Moves - Baton Pass", () => { ]); // round 1 - buff - game.move.select(Moves.NASTY_PLOT); + game.doAttack(getMovePosition(game.scene, 0, Moves.NASTY_PLOT)); await game.toNextTurn(); expect(game.scene.getPlayerPokemon()!.summonData.battleStats[BattleStat.SPATK]).toEqual(2); // round 2 - baton pass - game.move.select(Moves.BATON_PASS); + game.doAttack(getMovePosition(game.scene, 0, Moves.BATON_PASS)); game.doSelectPartyPokemon(1); await game.phaseInterceptor.to(TurnEndPhase); @@ -58,7 +59,7 @@ describe("Moves - Baton Pass", () => { expect(playerPkm.summonData.battleStats[BattleStat.SPATK]).toEqual(2); }, 20000); - it("passes stat stage buffs when AI uses it", async () => { + it("passes stat stage buffs when AI uses it", async() => { // arrange game.override .startingWave(5) @@ -69,13 +70,13 @@ describe("Moves - Baton Pass", () => { ]); // round 1 - ai buffs - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.toNextTurn(); // round 2 - baton pass game.scene.getEnemyPokemon()!.hp = 100; game.override.enemyMoveset(new Array(4).fill(Moves.BATON_PASS)); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(PostSummonPhase, false); // assert diff --git a/src/test/moves/beak_blast.test.ts b/src/test/moves/beak_blast.test.ts index 2a93dc00a54..8938b4c7af8 100644 --- a/src/test/moves/beak_blast.test.ts +++ b/src/test/moves/beak_blast.test.ts @@ -1,14 +1,15 @@ -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { StatusEffect } from "#app/enums/status-effect"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { MovePhase } from "#app/phases/move-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { Abilities } from "#enums/abilities"; -import { Moves } from "#enums/moves"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import GameManager from "#test/utils/gameManager"; +import { Species } from "#enums/species"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { StatusEffect } from "#app/enums/status-effect.js"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { MovePhase } from "#app/phases/move-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -47,7 +48,7 @@ describe("Moves - Beak Blast", () => { const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.BEAK_BLAST); + game.doAttack(getMovePosition(game.scene, 0, Moves.BEAK_BLAST)); await game.phaseInterceptor.to(MovePhase, false); expect(leadPokemon.getTag(BattlerTagType.BEAK_BLAST_CHARGING)).toBeDefined(); @@ -67,7 +68,7 @@ describe("Moves - Beak Blast", () => { const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.BEAK_BLAST); + game.doAttack(getMovePosition(game.scene, 0, Moves.BEAK_BLAST)); await game.phaseInterceptor.to(MovePhase, false); expect(leadPokemon.getTag(BattlerTagType.BEAK_BLAST_CHARGING)).toBeDefined(); @@ -87,7 +88,7 @@ describe("Moves - Beak Blast", () => { const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.BEAK_BLAST); + game.doAttack(getMovePosition(game.scene, 0, Moves.BEAK_BLAST)); await game.phaseInterceptor.to(MovePhase, false); expect(leadPokemon.getTag(BattlerTagType.BEAK_BLAST_CHARGING)).toBeDefined(); @@ -100,13 +101,13 @@ describe("Moves - Beak Blast", () => { it( "should only hit twice with Multi-Lens", async () => { - game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]); + game.override.startingHeldItems([{name: "MULTI_LENS", count: 1}]); await game.startBattle([Species.BLASTOISE]); const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.BEAK_BLAST); + game.doAttack(getMovePosition(game.scene, 0, Moves.BEAK_BLAST)); await game.phaseInterceptor.to(BerryPhase, false); expect(leadPokemon.turnData.hitCount).toBe(2); @@ -123,7 +124,7 @@ describe("Moves - Beak Blast", () => { const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.BEAK_BLAST); + game.doAttack(getMovePosition(game.scene, 0, Moves.BEAK_BLAST)); await game.phaseInterceptor.to(MovePhase, false); expect(leadPokemon.getTag(BattlerTagType.BEAK_BLAST_CHARGING)).toBeDefined(); diff --git a/src/test/moves/beat_up.test.ts b/src/test/moves/beat_up.test.ts index ce1598a49b4..a0f168ea30f 100644 --- a/src/test/moves/beat_up.test.ts +++ b/src/test/moves/beat_up.test.ts @@ -1,11 +1,12 @@ -import { Abilities } from "#app/enums/abilities"; -import { Moves } from "#app/enums/moves"; -import { Species } from "#app/enums/species"; -import { StatusEffect } from "#app/enums/status-effect"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { Species } from "#app/enums/species.js"; +import { Moves } from "#app/enums/moves.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { StatusEffect } from "#app/enums/status-effect.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; const TIMEOUT = 20 * 1000; // 20 sec timeout @@ -45,7 +46,7 @@ describe("Moves - Beat Up", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; let enemyStartingHp = enemyPokemon.hp; - game.move.select(Moves.BEAT_UP); + game.doAttack(getMovePosition(game.scene, 0, Moves.BEAT_UP)); await game.phaseInterceptor.to(MoveEffectPhase); @@ -69,7 +70,7 @@ describe("Moves - Beat Up", () => { game.scene.getParty()[1].trySetStatus(StatusEffect.BURN); - game.move.select(Moves.BEAT_UP); + game.doAttack(getMovePosition(game.scene, 0, Moves.BEAT_UP)); await game.phaseInterceptor.to(MoveEffectPhase); @@ -80,14 +81,14 @@ describe("Moves - Beat Up", () => { it( "should hit twice for each player Pokemon if the user has Multi-Lens", async () => { - game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]); + game.override.startingHeldItems([{name: "MULTI_LENS", count: 1}]); await game.startBattle([Species.MAGIKARP, Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.PIKACHU, Species.EEVEE]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; let enemyStartingHp = enemyPokemon.hp; - game.move.select(Moves.BEAT_UP); + game.doAttack(getMovePosition(game.scene, 0, Moves.BEAT_UP)); await game.phaseInterceptor.to(MoveEffectPhase); diff --git a/src/test/moves/belly_drum.test.ts b/src/test/moves/belly_drum.test.ts index 631de952a58..e579a4587ad 100644 --- a/src/test/moves/belly_drum.test.ts +++ b/src/test/moves/belly_drum.test.ts @@ -1,11 +1,11 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { toDmgValue } from "#app/utils"; +import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import { BattleStat } from "#app/data/battle-stat"; const TIMEOUT = 20 * 1000; // RATIO : HP Cost of Move @@ -40,13 +40,13 @@ describe("Moves - BELLY DRUM", () => { // Bulbapedia Reference: https://bulbapedia.bulbagarden.net/wiki/Belly_Drum_(move) test("Belly Drum raises the user's Attack to its max, at the cost of 1/2 of its maximum HP", - async () => { + async() => { await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; - const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); + const hpLost = Math.floor(leadPokemon.getMaxHp() / RATIO); - game.move.select(Moves.BELLY_DRUM); + game.doAttack(getMovePosition(game.scene, 0, Moves.BELLY_DRUM)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp() - hpLost); @@ -55,17 +55,17 @@ describe("Moves - BELLY DRUM", () => { ); test("Belly Drum will still take effect if an uninvolved stat is at max", - async () => { + async() => { await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; - const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); + const hpLost = Math.floor(leadPokemon.getMaxHp() / RATIO); // Here - BattleStat.ATK -> -3 and BattleStat.SPATK -> 6 leadPokemon.summonData.battleStats[BattleStat.ATK] = -3; leadPokemon.summonData.battleStats[BattleStat.SPATK] = 6; - game.move.select(Moves.BELLY_DRUM); + game.doAttack(getMovePosition(game.scene, 0, Moves.BELLY_DRUM)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp() - hpLost); @@ -75,14 +75,14 @@ describe("Moves - BELLY DRUM", () => { ); test("Belly Drum fails if the pokemon's attack stat is at its maximum", - async () => { + async() => { await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; leadPokemon.summonData.battleStats[BattleStat.ATK] = 6; - game.move.select(Moves.BELLY_DRUM); + game.doAttack(getMovePosition(game.scene, 0, Moves.BELLY_DRUM)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); @@ -91,14 +91,14 @@ describe("Moves - BELLY DRUM", () => { ); test("Belly Drum fails if the user's health is less than 1/2", - async () => { + async() => { await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; - const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); + const hpLost = Math.floor(leadPokemon.getMaxHp() / RATIO); leadPokemon.hp = hpLost - PREDAMAGE; - game.move.select(Moves.BELLY_DRUM); + game.doAttack(getMovePosition(game.scene, 0, Moves.BELLY_DRUM)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.hp).toBe(hpLost - PREDAMAGE); diff --git a/src/test/moves/ceaseless_edge.test.ts b/src/test/moves/ceaseless_edge.test.ts index 34ecf8f39f6..c8291a99b59 100644 --- a/src/test/moves/ceaseless_edge.test.ts +++ b/src/test/moves/ceaseless_edge.test.ts @@ -2,13 +2,14 @@ import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; import { allMoves } from "#app/data/move"; import { Abilities } from "#app/enums/abilities"; import { ArenaTagType } from "#app/enums/arena-tag-type"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -34,8 +35,8 @@ describe("Moves - Ceaseless Edge", () => { game.override.enemyPassiveAbility(Abilities.RUN_AWAY); game.override.startingLevel(100); game.override.enemyLevel(100); - game.override.moveset([Moves.CEASELESS_EDGE, Moves.SPLASH, Moves.ROAR]); - game.override.enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + game.override.moveset([ Moves.CEASELESS_EDGE, Moves.SPLASH, Moves.ROAR ]); + game.override.enemyMoveset([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]); vi.spyOn(allMoves[Moves.CEASELESS_EDGE], "accuracy", "get").mockReturnValue(100); }); @@ -43,13 +44,13 @@ describe("Moves - Ceaseless Edge", () => { test( "move should hit and apply spikes", async () => { - await game.startBattle([Species.ILLUMISE]); + await game.startBattle([ Species.ILLUMISE ]); const enemyPokemon = game.scene.getEnemyPokemon()!; const enemyStartingHp = enemyPokemon.hp; - game.move.select(Moves.CEASELESS_EDGE); + game.doAttack(getMovePosition(game.scene, 0, Moves.CEASELESS_EDGE)); await game.phaseInterceptor.to(MoveEffectPhase, false); // Spikes should not have any layers before move effect is applied @@ -67,14 +68,14 @@ describe("Moves - Ceaseless Edge", () => { test( "move should hit twice with multi lens and apply two layers of spikes", async () => { - game.override.startingHeldItems([{ name: "MULTI_LENS" }]); - await game.startBattle([Species.ILLUMISE]); + game.override.startingHeldItems([{name: "MULTI_LENS"}]); + await game.startBattle([ Species.ILLUMISE ]); const enemyPokemon = game.scene.getEnemyPokemon()!; const enemyStartingHp = enemyPokemon.hp; - game.move.select(Moves.CEASELESS_EDGE); + game.doAttack(getMovePosition(game.scene, 0, Moves.CEASELESS_EDGE)); await game.phaseInterceptor.to(MoveEffectPhase, false); // Spikes should not have any layers before move effect is applied @@ -92,12 +93,12 @@ describe("Moves - Ceaseless Edge", () => { test( "trainer - move should hit twice, apply two layers of spikes, force switch opponent - opponent takes damage", async () => { - game.override.startingHeldItems([{ name: "MULTI_LENS" }]); + game.override.startingHeldItems([{name: "MULTI_LENS"}]); game.override.startingWave(5); - await game.startBattle([Species.ILLUMISE]); + await game.startBattle([ Species.ILLUMISE ]); - game.move.select(Moves.CEASELESS_EDGE); + game.doAttack(getMovePosition(game.scene, 0, Moves.CEASELESS_EDGE)); await game.phaseInterceptor.to(MoveEffectPhase, false); // Spikes should not have any layers before move effect is applied const tagBefore = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as ArenaTrapTag; @@ -111,7 +112,7 @@ describe("Moves - Ceaseless Edge", () => { const hpBeforeSpikes = game.scene.currentBattle.enemyParty[1].hp; // Check HP of pokemon that WILL BE switched in (index 1) game.forceOpponentToSwitch(); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase, false); expect(game.scene.currentBattle.enemyParty[0].hp).toBeLessThan(hpBeforeSpikes); }, TIMEOUT diff --git a/src/test/moves/clangorous_soul.test.ts b/src/test/moves/clangorous_soul.test.ts index 9ea6da91595..5b2e8b6e06d 100644 --- a/src/test/moves/clangorous_soul.test.ts +++ b/src/test/moves/clangorous_soul.test.ts @@ -1,12 +1,12 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { toDmgValue } from "#app/utils"; +import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; +import { BattleStat } from "#app/data/battle-stat"; import { SPLASH_ONLY } from "#test/utils/testUtils"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; const TIMEOUT = 20 * 1000; /** HP Cost of Move */ @@ -41,13 +41,13 @@ describe("Moves - CLANGOROUS_SOUL", () => { //Bulbapedia Reference: https://bulbapedia.bulbagarden.net/wiki/Clangorous_Soul_(move) test("Clangorous Soul raises the user's Attack, Defense, Special Attack, Special Defense and Speed by one stage each, at the cost of 1/3 of its maximum HP", - async () => { - await game.startBattle([Species.MAGIKARP]); + async() => { + await game.startBattle([Species.MAGIKARP]); - const leadPokemon = game.scene.getPlayerPokemon()!; - const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); + const leadPokemon = game.scene.getPlayerPokemon()!; + const hpLost = Math.floor(leadPokemon.getMaxHp() / RATIO); - game.move.select(Moves.CLANGOROUS_SOUL); + game.doAttack(getMovePosition(game.scene, 0, Moves.CLANGOROUS_SOUL)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp() - hpLost); @@ -56,15 +56,15 @@ describe("Moves - CLANGOROUS_SOUL", () => { expect(leadPokemon.summonData.battleStats[BattleStat.SPATK]).toBe(1); expect(leadPokemon.summonData.battleStats[BattleStat.SPDEF]).toBe(1); expect(leadPokemon.summonData.battleStats[BattleStat.SPD]).toBe(1); - }, TIMEOUT + }, TIMEOUT ); test("Clangorous Soul will still take effect if one or more of the involved stats are not at max", - async () => { + async() => { await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; - const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); + const hpLost = Math.floor(leadPokemon.getMaxHp() / RATIO); //Here - BattleStat.SPD -> 0 and BattleStat.SPDEF -> 4 leadPokemon.summonData.battleStats[BattleStat.ATK] = 6; @@ -72,7 +72,7 @@ describe("Moves - CLANGOROUS_SOUL", () => { leadPokemon.summonData.battleStats[BattleStat.SPATK] = 6; leadPokemon.summonData.battleStats[BattleStat.SPDEF] = 4; - game.move.select(Moves.CLANGOROUS_SOUL); + game.doAttack(getMovePosition(game.scene, 0, Moves.CLANGOROUS_SOUL)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp() - hpLost); @@ -85,7 +85,7 @@ describe("Moves - CLANGOROUS_SOUL", () => { ); test("Clangorous Soul fails if all stats involved are at max", - async () => { + async() => { await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -96,7 +96,7 @@ describe("Moves - CLANGOROUS_SOUL", () => { leadPokemon.summonData.battleStats[BattleStat.SPDEF] = 6; leadPokemon.summonData.battleStats[BattleStat.SPD] = 6; - game.move.select(Moves.CLANGOROUS_SOUL); + game.doAttack(getMovePosition(game.scene, 0, Moves.CLANGOROUS_SOUL)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); @@ -109,14 +109,14 @@ describe("Moves - CLANGOROUS_SOUL", () => { ); test("Clangorous Soul fails if the user's health is less than 1/3", - async () => { + async() => { await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; - const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); + const hpLost = Math.floor(leadPokemon.getMaxHp() / RATIO); leadPokemon.hp = hpLost - PREDAMAGE; - game.move.select(Moves.CLANGOROUS_SOUL); + game.doAttack(getMovePosition(game.scene, 0, Moves.CLANGOROUS_SOUL)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.hp).toBe(hpLost - PREDAMAGE); diff --git a/src/test/moves/crafty_shield.test.ts b/src/test/moves/crafty_shield.test.ts index a341a50b0b9..c3e50bc52c2 100644 --- a/src/test/moves/crafty_shield.test.ts +++ b/src/test/moves/crafty_shield.test.ts @@ -1,13 +1,14 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { CommandPhase } from "#app/phases/command-phase"; -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, test } from "vitest"; import GameManager from "../utils/gameManager"; +import { Species } from "#enums/species"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "../utils/gameManagerUtils"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { CommandPhase } from "#app/phases/command-phase.js"; const TIMEOUT = 20 * 1000; @@ -47,11 +48,11 @@ describe("Moves - Crafty Shield", () => { const leadPokemon = game.scene.getPlayerField(); - game.move.select(Moves.CRAFTY_SHIELD); + game.doAttack(getMovePosition(game.scene, 0, Moves.CRAFTY_SHIELD)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(BerryPhase, false); @@ -68,11 +69,11 @@ describe("Moves - Crafty Shield", () => { const leadPokemon = game.scene.getPlayerField(); - game.move.select(Moves.CRAFTY_SHIELD); + game.doAttack(getMovePosition(game.scene, 0, Moves.CRAFTY_SHIELD)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(BerryPhase, false); @@ -90,11 +91,11 @@ describe("Moves - Crafty Shield", () => { const leadPokemon = game.scene.getPlayerField(); - game.move.select(Moves.CRAFTY_SHIELD); + game.doAttack(getMovePosition(game.scene, 0, Moves.CRAFTY_SHIELD)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(BerryPhase, false); @@ -109,11 +110,11 @@ describe("Moves - Crafty Shield", () => { const leadPokemon = game.scene.getPlayerField(); - game.move.select(Moves.CRAFTY_SHIELD); + game.doAttack(getMovePosition(game.scene, 0, Moves.CRAFTY_SHIELD)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SWORDS_DANCE, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SWORDS_DANCE)); await game.phaseInterceptor.to(BerryPhase, false); diff --git a/src/test/moves/double_team.test.ts b/src/test/moves/double_team.test.ts index c45c8bd8516..1c89d5b6350 100644 --- a/src/test/moves/double_team.test.ts +++ b/src/test/moves/double_team.test.ts @@ -1,9 +1,10 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { Abilities } from "#app/enums/abilities"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; @@ -41,7 +42,7 @@ describe("Moves - Double Team", () => { vi.spyOn(enemy, "getAccuracyMultiplier"); expect(ally.summonData.battleStats[BattleStat.EVA]).toBe(0); - game.move.select(Moves.DOUBLE_TEAM); + game.doAttack(getMovePosition(game.scene, 0, Moves.DOUBLE_TEAM)); await game.phaseInterceptor.to(TurnEndPhase); await game.toNextTurn(); diff --git a/src/test/moves/dragon_rage.test.ts b/src/test/moves/dragon_rage.test.ts index 223635575ab..8a27f4006f4 100644 --- a/src/test/moves/dragon_rage.test.ts +++ b/src/test/moves/dragon_rage.test.ts @@ -1,16 +1,17 @@ import { BattleStat } from "#app/data/battle-stat"; import { Type } from "#app/data/type"; -import { Species } from "#app/enums/species"; +import { Species } from "#app/enums/species.js"; import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; import { modifierTypes } from "#app/modifier/modifier-type"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { BattlerTagType } from "#enums/battler-tag-type"; import { Moves } from "#enums/moves"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; describe("Moves - Dragon Rage", () => { let phaserGame: Phaser.Game; @@ -61,7 +62,7 @@ describe("Moves - Dragon Rage", () => { game.override.disableCrits(); vi.spyOn(enemyPokemon, "getTypes").mockReturnValue([Type.DRAGON]); - game.move.select(Moves.DRAGON_RAGE); + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_RAGE)); await game.phaseInterceptor.to(TurnEndPhase); const damageDealt = enemyPokemon.getMaxHp() - enemyPokemon.hp; @@ -72,7 +73,7 @@ describe("Moves - Dragon Rage", () => { game.override.disableCrits(); vi.spyOn(enemyPokemon, "getTypes").mockReturnValue([Type.STEEL]); - game.move.select(Moves.DRAGON_RAGE); + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_RAGE)); await game.phaseInterceptor.to(TurnEndPhase); const damageDealt = enemyPokemon.getMaxHp() - enemyPokemon.hp; @@ -83,7 +84,7 @@ describe("Moves - Dragon Rage", () => { game.override.disableCrits(); partyPokemon.summonData.battleStats[BattleStat.SPATK] = 2; - game.move.select(Moves.DRAGON_RAGE); + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_RAGE)); await game.phaseInterceptor.to(TurnEndPhase); const damageDealt = enemyPokemon.getMaxHp() - enemyPokemon.hp; @@ -94,7 +95,7 @@ describe("Moves - Dragon Rage", () => { game.override.disableCrits(); vi.spyOn(partyPokemon, "getTypes").mockReturnValue([Type.DRAGON]); - game.move.select(Moves.DRAGON_RAGE); + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_RAGE)); await game.phaseInterceptor.to(TurnEndPhase); const damageDealt = enemyPokemon.getMaxHp() - enemyPokemon.hp; @@ -104,7 +105,7 @@ describe("Moves - Dragon Rage", () => { it("ignores criticals", async () => { partyPokemon.addTag(BattlerTagType.ALWAYS_CRIT, 99); - game.move.select(Moves.DRAGON_RAGE); + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_RAGE)); await game.phaseInterceptor.to(TurnEndPhase); const damageDealt = enemyPokemon.getMaxHp() - enemyPokemon.hp; @@ -115,7 +116,7 @@ describe("Moves - Dragon Rage", () => { game.override.disableCrits(); game.override.enemyAbility(Abilities.ICE_SCALES); - game.move.select(Moves.DRAGON_RAGE); + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_RAGE)); await game.phaseInterceptor.to(TurnEndPhase); const damageDealt = enemyPokemon.getMaxHp() - enemyPokemon.hp; @@ -126,7 +127,7 @@ describe("Moves - Dragon Rage", () => { game.override.disableCrits(); game.scene.addModifier(modifierTypes.MULTI_LENS().newModifier(partyPokemon), false); - game.move.select(Moves.DRAGON_RAGE); + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_RAGE)); await game.phaseInterceptor.to(TurnEndPhase); const damageDealt = enemyPokemon.getMaxHp() - enemyPokemon.hp; diff --git a/src/test/moves/dragon_tail.test.ts b/src/test/moves/dragon_tail.test.ts index 362383e2fe3..28c47a83454 100644 --- a/src/test/moves/dragon_tail.test.ts +++ b/src/test/moves/dragon_tail.test.ts @@ -1,15 +1,16 @@ -import { BattlerIndex } from "#app/battle"; -import { allMoves } from "#app/data/move"; -import { BattleEndPhase } from "#app/phases/battle-end-phase"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { allMoves } from "#app/data/move.js"; +import { SPLASH_ONLY } from "../utils/testUtils"; 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, test, vi } from "vitest"; import GameManager from "../utils/gameManager"; -import { SPLASH_ONLY } from "../utils/testUtils"; +import { getMovePosition } from "../utils/gameManagerUtils"; +import { BattlerIndex } from "#app/battle.js"; +import { BattleEndPhase } from "#app/phases/battle-end-phase.js"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -45,8 +46,9 @@ describe("Moves - Dragon Tail", () => { await game.startBattle([Species.DRATINI]); const enemyPokemon = game.scene.getEnemyPokemon()!; + expect(enemyPokemon).toBeDefined(); - game.move.select(Moves.DRAGON_TAIL); + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_TAIL)); await game.phaseInterceptor.to(BerryPhase); @@ -66,9 +68,12 @@ describe("Moves - Dragon Tail", () => { await game.startBattle([Species.DRATINI]); const leadPokemon = game.scene.getPlayerPokemon()!; - const enemyPokemon = game.scene.getEnemyPokemon()!; + expect(leadPokemon).toBeDefined(); - game.move.select(Moves.DRAGON_TAIL); + const enemyPokemon = game.scene.getEnemyPokemon()!; + expect(enemyPokemon).toBeDefined(); + + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_TAIL)); await game.phaseInterceptor.to(BerryPhase); @@ -80,7 +85,7 @@ describe("Moves - Dragon Tail", () => { ); test( - "Double battles should proceed without crashing", + "Double battles should proceed without crashing" , async () => { game.override.battleType("double").enemyMoveset(SPLASH_ONLY); game.override.moveset([Moves.DRAGON_TAIL, Moves.SPLASH, Moves.FLAMETHROWER]) @@ -88,12 +93,19 @@ describe("Moves - Dragon Tail", () => { await game.startBattle([Species.DRATINI, Species.DRATINI, Species.WAILORD, Species.WAILORD]); const leadPokemon = game.scene.getParty()[0]!; + const secPokemon = game.scene.getParty()[1]!; + expect(leadPokemon).toBeDefined(); + expect(secPokemon).toBeDefined(); - const enemyLeadPokemon = game.scene.getEnemyParty()[0]!; - const enemySecPokemon = game.scene.getEnemyParty()[1]!; + const enemyLeadPokemon = game.scene.currentBattle.enemyParty[0]!; + const enemySecPokemon = game.scene.currentBattle.enemyParty[1]!; + expect(enemyLeadPokemon).toBeDefined(); + expect(enemySecPokemon).toBeDefined(); - game.move.select(Moves.DRAGON_TAIL, 0, BattlerIndex.ENEMY); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_TAIL)); + game.doSelectTarget(BattlerIndex.ENEMY); + + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); @@ -105,8 +117,10 @@ describe("Moves - Dragon Tail", () => { expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp()); // second turn - game.move.select(Moves.FLAMETHROWER, 0, BattlerIndex.ENEMY_2); - game.move.select(Moves.SPLASH, 1); + + game.doAttack(getMovePosition(game.scene, 0, Moves.FLAMETHROWER)); + game.doSelectTarget(BattlerIndex.ENEMY_2); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(BerryPhase); expect(enemySecPokemon.hp).toBeLessThan(enemySecPokemon.getMaxHp()); @@ -114,7 +128,7 @@ describe("Moves - Dragon Tail", () => { ); test( - "Flee move redirection works", + "Flee move redirection works" , async () => { game.override.battleType("double").enemyMoveset(SPLASH_ONLY); game.override.moveset([Moves.DRAGON_TAIL, Moves.SPLASH, Moves.FLAMETHROWER]); @@ -123,13 +137,20 @@ describe("Moves - Dragon Tail", () => { const leadPokemon = game.scene.getParty()[0]!; const secPokemon = game.scene.getParty()[1]!; + expect(leadPokemon).toBeDefined(); + expect(secPokemon).toBeDefined(); - const enemyLeadPokemon = game.scene.getEnemyParty()[0]!; - const enemySecPokemon = game.scene.getEnemyParty()[1]!; + const enemyLeadPokemon = game.scene.currentBattle.enemyParty[0]!; + const enemySecPokemon = game.scene.currentBattle.enemyParty[1]!; + expect(enemyLeadPokemon).toBeDefined(); + expect(enemySecPokemon).toBeDefined(); + + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_TAIL)); + game.doSelectTarget(BattlerIndex.ENEMY); - game.move.select(Moves.DRAGON_TAIL, 0, BattlerIndex.ENEMY); // target the same pokemon, second move should be redirected after first flees - game.move.select(Moves.DRAGON_TAIL, 1, BattlerIndex.ENEMY); + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_TAIL)); + game.doSelectTarget(BattlerIndex.ENEMY); await game.phaseInterceptor.to(BerryPhase); diff --git a/src/test/moves/dynamax_cannon.test.ts b/src/test/moves/dynamax_cannon.test.ts index 6ac0befdb36..5e81241ef46 100644 --- a/src/test/moves/dynamax_cannon.test.ts +++ b/src/test/moves/dynamax_cannon.test.ts @@ -1,12 +1,14 @@ import { BattlerIndex } from "#app/battle"; import { allMoves } from "#app/data/move"; -import { DamagePhase } from "#app/phases/damage-phase"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { DamagePhase } from "#app/phases/damage-phase.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import { TurnStartPhase } from "#app/phases/turn-start-phase.js"; describe("Moves - Dynamax Cannon", () => { let phaserGame: Phaser.Game; @@ -27,7 +29,7 @@ describe("Moves - Dynamax Cannon", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.moveset([dynamaxCannon.id]); + game.override.moveset([ dynamaxCannon.id ]); game.override.startingLevel(200); // Note that, for Waves 1-10, the level cap is 10 @@ -36,18 +38,18 @@ describe("Moves - Dynamax Cannon", () => { game.override.disableCrits(); game.override.enemySpecies(Species.MAGIKARP); - game.override.enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); vi.spyOn(dynamaxCannon, "calculateBattlePower"); }); - it("should return 100 power against an enemy below level cap", async () => { + it("should return 100 power against an enemy below level cap", async() => { game.override.enemyLevel(1); await game.startBattle([ Species.ETERNATUS, ]); - game.move.select(dynamaxCannon.id); + game.doAttack(getMovePosition(game.scene, 0, dynamaxCannon.id)); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(dynamaxCannon.id); @@ -55,13 +57,13 @@ describe("Moves - Dynamax Cannon", () => { expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(100); }, 20000); - it("should return 100 power against an enemy at level cap", async () => { + it("should return 100 power against an enemy at level cap", async() => { game.override.enemyLevel(10); await game.startBattle([ Species.ETERNATUS, ]); - game.move.select(dynamaxCannon.id); + game.doAttack(getMovePosition(game.scene, 0, dynamaxCannon.id)); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(dynamaxCannon.id); @@ -69,13 +71,13 @@ describe("Moves - Dynamax Cannon", () => { expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(100); }, 20000); - it("should return 120 power against an enemy 1% above level cap", async () => { + it("should return 120 power against an enemy 1% above level cap", async() => { game.override.enemyLevel(101); await game.startBattle([ Species.ETERNATUS, ]); - game.move.select(dynamaxCannon.id); + game.doAttack(getMovePosition(game.scene, 0, dynamaxCannon.id)); await game.phaseInterceptor.to(MoveEffectPhase, false); const phase = game.scene.getCurrentPhase() as MoveEffectPhase; @@ -86,13 +88,13 @@ describe("Moves - Dynamax Cannon", () => { expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(120); }, 20000); - it("should return 140 power against an enemy 2% above level capp", async () => { + it("should return 140 power against an enemy 2% above level capp", async() => { game.override.enemyLevel(102); await game.startBattle([ Species.ETERNATUS, ]); - game.move.select(dynamaxCannon.id); + game.doAttack(getMovePosition(game.scene, 0, dynamaxCannon.id)); await game.phaseInterceptor.to(MoveEffectPhase, false); const phase = game.scene.getCurrentPhase() as MoveEffectPhase; @@ -103,13 +105,13 @@ describe("Moves - Dynamax Cannon", () => { expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(140); }, 20000); - it("should return 160 power against an enemy 3% above level cap", async () => { + it("should return 160 power against an enemy 3% above level cap", async() => { game.override.enemyLevel(103); await game.startBattle([ Species.ETERNATUS, ]); - game.move.select(dynamaxCannon.id); + game.doAttack(getMovePosition(game.scene, 0, dynamaxCannon.id)); await game.phaseInterceptor.to(MoveEffectPhase, false); const phase = game.scene.getCurrentPhase() as MoveEffectPhase; @@ -120,13 +122,13 @@ describe("Moves - Dynamax Cannon", () => { expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(160); }, 20000); - it("should return 180 power against an enemy 4% above level cap", async () => { + it("should return 180 power against an enemy 4% above level cap", async() => { game.override.enemyLevel(104); await game.startBattle([ Species.ETERNATUS, ]); - game.move.select(dynamaxCannon.id); + game.doAttack(getMovePosition(game.scene, 0, dynamaxCannon.id)); await game.phaseInterceptor.to(MoveEffectPhase, false); const phase = game.scene.getCurrentPhase() as MoveEffectPhase; @@ -137,13 +139,13 @@ describe("Moves - Dynamax Cannon", () => { expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(180); }, 20000); - it("should return 200 power against an enemy 5% above level cap", async () => { + it("should return 200 power against an enemy 5% above level cap", async() => { game.override.enemyLevel(105); await game.startBattle([ Species.ETERNATUS, ]); - game.move.select(dynamaxCannon.id); + game.doAttack(getMovePosition(game.scene, 0, dynamaxCannon.id)); await game.phaseInterceptor.to(MoveEffectPhase, false); const phase = game.scene.getCurrentPhase() as MoveEffectPhase; @@ -154,14 +156,17 @@ describe("Moves - Dynamax Cannon", () => { expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(200); }, 20000); - it("should return 200 power against an enemy way above level cap", async () => { + it("should return 200 power against an enemy way above level cap", async() => { game.override.enemyLevel(999); await game.startBattle([ Species.ETERNATUS, ]); - game.move.select(dynamaxCannon.id); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + game.doAttack(getMovePosition(game.scene, 0, dynamaxCannon.id)); + + await game.phaseInterceptor.to(TurnStartPhase, false); + // Force user to act before enemy + vi.spyOn((game.scene.getCurrentPhase() as TurnStartPhase), "getOrder").mockReturnValue([ BattlerIndex.PLAYER, BattlerIndex. ENEMY]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(dynamaxCannon.id); diff --git a/src/test/moves/fillet_away.test.ts b/src/test/moves/fillet_away.test.ts index b2ff9e25dba..fcad704ef29 100644 --- a/src/test/moves/fillet_away.test.ts +++ b/src/test/moves/fillet_away.test.ts @@ -1,12 +1,12 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { toDmgValue } from "#app/utils"; +import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; +import { BattleStat } from "#app/data/battle-stat"; import { SPLASH_ONLY } from "#test/utils/testUtils"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; const TIMEOUT = 20 * 1000; /** HP Cost of Move */ @@ -41,13 +41,13 @@ describe("Moves - FILLET AWAY", () => { //Bulbapedia Reference: https://bulbapedia.bulbagarden.net/wiki/fillet_away_(move) test("Fillet Away raises the user's Attack, Special Attack, and Speed by two stages each, at the cost of 1/2 of its maximum HP", - async () => { + async() => { await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; - const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); + const hpLost = Math.floor(leadPokemon.getMaxHp() / RATIO); - game.move.select(Moves.FILLET_AWAY); + game.doAttack(getMovePosition(game.scene, 0, Moves.FILLET_AWAY)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp() - hpLost); @@ -58,17 +58,17 @@ describe("Moves - FILLET AWAY", () => { ); test("Fillet Away will still take effect if one or more of the involved stats are not at max", - async () => { + async() => { await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; - const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); + const hpLost = Math.floor(leadPokemon.getMaxHp() / RATIO); //Here - BattleStat.SPD -> 0 and BattleStat.SPATK -> 3 leadPokemon.summonData.battleStats[BattleStat.ATK] = 6; leadPokemon.summonData.battleStats[BattleStat.SPATK] = 3; - game.move.select(Moves.FILLET_AWAY); + game.doAttack(getMovePosition(game.scene, 0, Moves.FILLET_AWAY)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp() - hpLost); @@ -79,7 +79,7 @@ describe("Moves - FILLET AWAY", () => { ); test("Fillet Away fails if all stats involved are at max", - async () => { + async() => { await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -88,7 +88,7 @@ describe("Moves - FILLET AWAY", () => { leadPokemon.summonData.battleStats[BattleStat.SPATK] = 6; leadPokemon.summonData.battleStats[BattleStat.SPD] = 6; - game.move.select(Moves.FILLET_AWAY); + game.doAttack(getMovePosition(game.scene, 0, Moves.FILLET_AWAY)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); @@ -99,14 +99,14 @@ describe("Moves - FILLET AWAY", () => { ); test("Fillet Away fails if the user's health is less than 1/2", - async () => { + async() => { await game.startBattle([Species.MAGIKARP]); const leadPokemon = game.scene.getPlayerPokemon()!; - const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); + const hpLost = Math.floor(leadPokemon.getMaxHp() / RATIO); leadPokemon.hp = hpLost - PREDAMAGE; - game.move.select(Moves.FILLET_AWAY); + game.doAttack(getMovePosition(game.scene, 0, Moves.FILLET_AWAY)); await game.phaseInterceptor.to(TurnEndPhase); expect(leadPokemon.hp).toBe(hpLost - PREDAMAGE); diff --git a/src/test/moves/fissure.test.ts b/src/test/moves/fissure.test.ts index 51122b269b8..65d692a5cc1 100644 --- a/src/test/moves/fissure.test.ts +++ b/src/test/moves/fissure.test.ts @@ -1,14 +1,15 @@ import { BattleStat } from "#app/data/battle-stat"; -import { Species } from "#app/enums/species"; +import { Species } from "#app/enums/species.js"; import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; -import { DamagePhase } from "#app/phases/damage-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { DamagePhase } from "#app/phases/damage-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Moves - Fissure", () => { let phaserGame: Phaser.Game; @@ -56,7 +57,7 @@ describe("Moves - Fissure", () => { game.override.ability(Abilities.NO_GUARD); game.override.enemyAbility(Abilities.FUR_COAT); - game.move.select(Moves.FISSURE); + game.doAttack(getMovePosition(game.scene, 0, Moves.FISSURE)); await game.phaseInterceptor.to(DamagePhase, true); expect(enemyPokemon.isFainted()).toBe(true); @@ -67,7 +68,7 @@ describe("Moves - Fissure", () => { enemyPokemon.summonData.battleStats[BattleStat.ACC] = -6; - game.move.select(Moves.FISSURE); + game.doAttack(getMovePosition(game.scene, 0, Moves.FISSURE)); // wait for TurnEndPhase instead of DamagePhase as fissure might not actually inflict damage await game.phaseInterceptor.to(TurnEndPhase); @@ -80,7 +81,7 @@ describe("Moves - Fissure", () => { enemyPokemon.summonData.battleStats[BattleStat.EVA] = 6; - game.move.select(Moves.FISSURE); + game.doAttack(getMovePosition(game.scene, 0, Moves.FISSURE)); // wait for TurnEndPhase instead of DamagePhase as fissure might not actually inflict damage await game.phaseInterceptor.to(TurnEndPhase); diff --git a/src/test/moves/flame_burst.test.ts b/src/test/moves/flame_burst.test.ts index 2777b8178b8..d6679f921df 100644 --- a/src/test/moves/flame_burst.test.ts +++ b/src/test/moves/flame_burst.test.ts @@ -1,12 +1,14 @@ -import { allAbilities } from "#app/data/ability"; -import { Abilities } from "#app/enums/abilities"; -import Pokemon from "#app/field/pokemon"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { Moves } from "#enums/moves"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { Species } from "#enums/species"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Abilities } from "#app/enums/abilities.js"; +import { allAbilities } from "#app/data/ability.js"; +import Pokemon from "#app/field/pokemon.js"; +import { SelectTargetPhase } from "#app/phases/select-target-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Moves - Flame Burst", () => { let phaserGame: Phaser.Game; @@ -20,7 +22,7 @@ describe("Moves - Flame Burst", () => { * @returns Effect damage of Flame Burst */ const getEffectDamage = (pokemon: Pokemon): number => { - return Math.max(1, Math.floor(pokemon.getMaxHp() * 1 / 16)); + return Math.max(1, Math.floor(pokemon.getMaxHp() * 1/16)); }; beforeAll(() => { @@ -47,10 +49,12 @@ describe("Moves - Flame Burst", () => { it("inflicts damage to the target's ally equal to 1/16 of its max HP", async () => { await game.startBattle([Species.PIKACHU, Species.PIKACHU]); - const [leftEnemy, rightEnemy] = game.scene.getEnemyField(); + const [ leftEnemy, rightEnemy ] = game.scene.getEnemyField(); - game.move.select(Moves.FLAME_BURST, 0, leftEnemy.getBattlerIndex()); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.FLAME_BURST)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(leftEnemy.getBattlerIndex()); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(leftEnemy.hp).toBeLessThan(leftEnemy.getMaxHp()); @@ -61,10 +65,12 @@ describe("Moves - Flame Burst", () => { game.override.enemyAbility(Abilities.FLASH_FIRE); await game.startBattle([Species.PIKACHU, Species.PIKACHU]); - const [leftEnemy, rightEnemy] = game.scene.getEnemyField(); + const [ leftEnemy, rightEnemy ] = game.scene.getEnemyField(); - game.move.select(Moves.FLAME_BURST, 0, leftEnemy.getBattlerIndex()); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.FLAME_BURST)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(leftEnemy.getBattlerIndex()); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(leftEnemy.hp).toBe(leftEnemy.getMaxHp()); @@ -73,12 +79,14 @@ describe("Moves - Flame Burst", () => { it("does not interact with the target ally's abilities", async () => { await game.startBattle([Species.PIKACHU, Species.PIKACHU]); - const [leftEnemy, rightEnemy] = game.scene.getEnemyField(); + const [ leftEnemy, rightEnemy ] = game.scene.getEnemyField(); vi.spyOn(rightEnemy, "getAbility").mockReturnValue(allAbilities[Abilities.FLASH_FIRE]); - game.move.select(Moves.FLAME_BURST, 0, leftEnemy.getBattlerIndex()); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.FLAME_BURST)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(leftEnemy.getBattlerIndex()); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(leftEnemy.hp).toBeLessThan(leftEnemy.getMaxHp()); @@ -87,12 +95,14 @@ describe("Moves - Flame Burst", () => { it("effect damage is prevented by Magic Guard", async () => { await game.startBattle([Species.PIKACHU, Species.PIKACHU]); - const [leftEnemy, rightEnemy] = game.scene.getEnemyField(); + const [ leftEnemy, rightEnemy ] = game.scene.getEnemyField(); vi.spyOn(rightEnemy, "getAbility").mockReturnValue(allAbilities[Abilities.MAGIC_GUARD]); - game.move.select(Moves.FLAME_BURST, 0, leftEnemy.getBattlerIndex()); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.FLAME_BURST)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(leftEnemy.getBattlerIndex()); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(leftEnemy.hp).toBeLessThan(leftEnemy.getMaxHp()); diff --git a/src/test/moves/flower_shield.test.ts b/src/test/moves/flower_shield.test.ts index b3e50219aec..9001e8ceacb 100644 --- a/src/test/moves/flower_shield.test.ts +++ b/src/test/moves/flower_shield.test.ts @@ -1,15 +1,16 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { SemiInvulnerableTag } from "#app/data/battler-tags"; -import { Type } from "#app/data/type"; -import { Biome } from "#app/enums/biome"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { SemiInvulnerableTag } from "#app/data/battler-tags.js"; +import { Type } from "#app/data/type.js"; +import { Biome } from "#app/enums/biome.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; describe("Moves - Flower Shield", () => { let phaserGame: Phaser.Game; @@ -44,7 +45,7 @@ describe("Moves - Flower Shield", () => { expect(magikarp.summonData.battleStats[BattleStat.DEF]).toBe(0); expect(cherrim.summonData.battleStats[BattleStat.DEF]).toBe(0); - game.move.select(Moves.FLOWER_SHIELD); + game.doAttack(getMovePosition(game.scene, 0, Moves.FLOWER_SHIELD)); await game.phaseInterceptor.to(TurnEndPhase); expect(magikarp.summonData.battleStats[BattleStat.DEF]).toBe(0); @@ -63,8 +64,8 @@ describe("Moves - Flower Shield", () => { grassPokemons.forEach(p => expect(p.summonData.battleStats[BattleStat.DEF]).toBe(0)); nonGrassPokemons.forEach(p => expect(p.summonData.battleStats[BattleStat.DEF]).toBe(0)); - game.move.select(Moves.FLOWER_SHIELD); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.FLOWER_SHIELD)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); grassPokemons.forEach(p => expect(p.summonData.battleStats[BattleStat.DEF]).toBe(1)); @@ -87,7 +88,7 @@ describe("Moves - Flower Shield", () => { expect(cherrim.summonData.battleStats[BattleStat.DEF]).toBe(0); expect(paras.getTag(SemiInvulnerableTag)).toBeUndefined; - game.move.select(Moves.FLOWER_SHIELD); + game.doAttack(getMovePosition(game.scene, 0, Moves.FLOWER_SHIELD)); await game.phaseInterceptor.to(TurnEndPhase); expect(paras.getTag(SemiInvulnerableTag)).toBeDefined(); @@ -105,7 +106,7 @@ describe("Moves - Flower Shield", () => { expect(enemy.summonData.battleStats[BattleStat.DEF]).toBe(0); expect(ally.summonData.battleStats[BattleStat.DEF]).toBe(0); - game.move.select(Moves.FLOWER_SHIELD); + game.doAttack(getMovePosition(game.scene, 0, Moves.FLOWER_SHIELD)); await game.phaseInterceptor.to(TurnEndPhase); expect(enemy.summonData.battleStats[BattleStat.DEF]).toBe(0); diff --git a/src/test/moves/focus_punch.test.ts b/src/test/moves/focus_punch.test.ts index 99399623a1c..385234f0b71 100644 --- a/src/test/moves/focus_punch.test.ts +++ b/src/test/moves/focus_punch.test.ts @@ -1,15 +1,16 @@ -import { BerryPhase } from "#app/phases/berry-phase"; -import { MessagePhase } from "#app/phases/message-phase"; -import { MoveHeaderPhase } from "#app/phases/move-header-phase"; -import { SwitchSummonPhase } from "#app/phases/switch-summon-phase"; -import { TurnStartPhase } from "#app/phases/turn-start-phase"; -import { Abilities } from "#enums/abilities"; -import { Moves } from "#enums/moves"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import GameManager from "#test/utils/gameManager"; +import { Species } from "#enums/species"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { MessagePhase } from "#app/phases/message-phase.js"; +import { MoveHeaderPhase } from "#app/phases/move-header-phase.js"; +import { SwitchSummonPhase } from "#app/phases/switch-summon-phase.js"; +import { TurnStartPhase } from "#app/phases/turn-start-phase.js"; const TIMEOUT = 20 * 1000; @@ -50,7 +51,7 @@ describe("Moves - Focus Punch", () => { const enemyStartingHp = enemyPokemon.hp; - game.move.select(Moves.FOCUS_PUNCH); + game.doAttack(getMovePosition(game.scene, 0, Moves.FOCUS_PUNCH)); await game.phaseInterceptor.to(MessagePhase); @@ -77,7 +78,7 @@ describe("Moves - Focus Punch", () => { const enemyStartingHp = enemyPokemon.hp; - game.move.select(Moves.FOCUS_PUNCH); + game.doAttack(getMovePosition(game.scene, 0, Moves.FOCUS_PUNCH)); await game.phaseInterceptor.to(MessagePhase); @@ -102,7 +103,7 @@ describe("Moves - Focus Punch", () => { const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.FOCUS_PUNCH); + game.doAttack(getMovePosition(game.scene, 0, Moves.FOCUS_PUNCH)); await game.phaseInterceptor.to(MessagePhase); // Header message @@ -124,7 +125,7 @@ describe("Moves - Focus Punch", () => { await game.startBattle([Species.CHARIZARD]); game.forceOpponentToSwitch(); - game.move.select(Moves.FOCUS_PUNCH); + game.doAttack(getMovePosition(game.scene, 0, Moves.FOCUS_PUNCH)); await game.phaseInterceptor.to(TurnStartPhase); diff --git a/src/test/moves/follow_me.test.ts b/src/test/moves/follow_me.test.ts index d7ef199df3e..a0fff9afbf8 100644 --- a/src/test/moves/follow_me.test.ts +++ b/src/test/moves/follow_me.test.ts @@ -1,12 +1,15 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#app/battle.js"; import { Stat } from "#app/data/pokemon-stat"; -import { Abilities } from "#app/enums/abilities"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { Abilities } from "#app/enums/abilities.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { SelectTargetPhase } from "#app/phases/select-target-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -31,21 +34,32 @@ describe("Moves - Follow Me", () => { game.override.enemySpecies(Species.SNORLAX); game.override.startingLevel(100); game.override.enemyLevel(100); - game.override.moveset([Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.moveset([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); test( "move should redirect enemy attacks to the user", async () => { - await game.startBattle([Species.AMOONGUSS, Species.CHARIZARD]); + await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); + + const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); const playerStartingHp = playerPokemon.map(p => p.hp); - game.move.select(Moves.FOLLOW_ME); - game.move.select(Moves.QUICK_ATTACK, 1, BattlerIndex.ENEMY); + game.doAttack(getMovePosition(game.scene, 0, Moves.FOLLOW_ME)); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + + game.doSelectTarget(BattlerIndex.ENEMY); await game.phaseInterceptor.to(TurnEndPhase, false); expect(playerPokemon[0].hp).toBeLessThan(playerStartingHp[0]); @@ -56,14 +70,22 @@ describe("Moves - Follow Me", () => { test( "move should redirect enemy attacks to the first ally that uses it", async () => { - await game.startBattle([Species.AMOONGUSS, Species.CHARIZARD]); + await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); + + const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); const playerStartingHp = playerPokemon.map(p => p.hp); - game.move.select(Moves.FOLLOW_ME); - game.move.select(Moves.FOLLOW_ME, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.FOLLOW_ME)); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.FOLLOW_ME)); await game.phaseInterceptor.to(TurnEndPhase, false); playerPokemon.sort((a, b) => a.getBattleStat(Stat.SPD) - b.getBattleStat(Stat.SPD)); @@ -77,17 +99,29 @@ describe("Moves - Follow Me", () => { "move effect should be bypassed by Stalwart", async () => { game.override.ability(Abilities.STALWART); - game.override.moveset([Moves.QUICK_ATTACK]); - game.override.enemyMoveset([Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME]); + game.override.moveset([ Moves.QUICK_ATTACK ]); + game.override.enemyMoveset([ Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME ]); - await game.startBattle([Species.AMOONGUSS, Species.CHARIZARD]); + await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); const enemyStartingHp = enemyPokemon.map(p => p.hp); - game.move.select(Moves.QUICK_ATTACK, 0, BattlerIndex.ENEMY); - game.move.select(Moves.QUICK_ATTACK, 1, BattlerIndex.ENEMY_2); + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY_2); await game.phaseInterceptor.to(TurnEndPhase, false); // If redirection was bypassed, both enemies should be damaged @@ -99,17 +133,29 @@ describe("Moves - Follow Me", () => { test( "move effect should be bypassed by Snipe Shot", async () => { - game.override.moveset([Moves.SNIPE_SHOT]); - game.override.enemyMoveset([Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME]); + game.override.moveset([ Moves.SNIPE_SHOT ]); + game.override.enemyMoveset([ Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME ]); - await game.startBattle([Species.AMOONGUSS, Species.CHARIZARD]); + await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); const enemyStartingHp = enemyPokemon.map(p => p.hp); - game.move.select(Moves.SNIPE_SHOT, 0, BattlerIndex.ENEMY); - game.move.select(Moves.SNIPE_SHOT, 1, BattlerIndex.ENEMY_2); + game.doAttack(getMovePosition(game.scene, 0, Moves.SNIPE_SHOT)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.SNIPE_SHOT)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY_2); await game.phaseInterceptor.to(TurnEndPhase, false); // If redirection was bypassed, both enemies should be damaged diff --git a/src/test/moves/foresight.test.ts b/src/test/moves/foresight.test.ts index b856ec0f852..91d3e3c37e0 100644 --- a/src/test/moves/foresight.test.ts +++ b/src/test/moves/foresight.test.ts @@ -1,10 +1,11 @@ -import { Moves } from "#app/enums/moves"; -import { Species } from "#app/enums/species"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { Species } from "#app/enums/species.js"; import { SPLASH_ONLY } from "../utils/testUtils"; +import { Moves } from "#app/enums/moves.js"; +import { getMovePosition } from "../utils/gameManagerUtils"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; describe("Moves - Foresight", () => { let phaserGame: Phaser.Game; @@ -36,19 +37,19 @@ describe("Moves - Foresight", () => { const enemy = game.scene.getEnemyPokemon()!; - game.move.select(Moves.QUICK_ATTACK); + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK)); await game.toNextTurn(); expect(enemy.hp).toBe(enemy.getMaxHp()); - game.move.select(Moves.FORESIGHT); + game.doAttack(getMovePosition(game.scene, 0, Moves.FORESIGHT)); await game.toNextTurn(); - game.move.select(Moves.QUICK_ATTACK); + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK)); await game.toNextTurn(); expect(enemy.hp).toBeLessThan(enemy.getMaxHp()); enemy.hp = enemy.getMaxHp(); - game.move.select(Moves.MACH_PUNCH); + game.doAttack(getMovePosition(game.scene, 0, Moves.MACH_PUNCH)); await game.phaseInterceptor.to(MoveEffectPhase); expect(enemy.hp).toBeLessThan(enemy.getMaxHp()); @@ -61,9 +62,9 @@ describe("Moves - Foresight", () => { const pokemon = game.scene.getPlayerPokemon()!; vi.spyOn(pokemon, "getAccuracyMultiplier"); - game.move.select(Moves.FORESIGHT); + game.doAttack(getMovePosition(game.scene, 0, Moves.FORESIGHT)); await game.toNextTurn(); - game.move.select(Moves.QUICK_ATTACK); + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK)); await game.phaseInterceptor.to(MoveEffectPhase); expect(pokemon.getAccuracyMultiplier).toHaveReturnedWith(1); diff --git a/src/test/moves/freezy_frost.test.ts b/src/test/moves/freezy_frost.test.ts index 00d7104d373..b4c30279c21 100644 --- a/src/test/moves/freezy_frost.test.ts +++ b/src/test/moves/freezy_frost.test.ts @@ -1,14 +1,15 @@ import { BattleStat } from "#app/data/battle-stat"; -import { allMoves } from "#app/data/move"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { allMoves } from "#app/data/move.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; describe("Moves - Freezy Frost", () => { describe("integration tests", () => { @@ -46,17 +47,17 @@ describe("Moves - Freezy Frost", () => { expect(user.summonData.battleStats[BattleStat.ATK]).toBe(0); expect(enemy.summonData.battleStats[BattleStat.ATK]).toBe(0); - game.move.select(Moves.SWORDS_DANCE); + game.doAttack(getMovePosition(game.scene, 0, Moves.SWORDS_DANCE)); await game.phaseInterceptor.to(TurnInitPhase); - game.move.select(Moves.CHARM); + game.doAttack(getMovePosition(game.scene, 0, Moves.CHARM)); await game.phaseInterceptor.to(TurnInitPhase); const userAtkBefore = user.summonData.battleStats[BattleStat.ATK]; const enemyAtkBefore = enemy.summonData.battleStats[BattleStat.ATK]; expect(userAtkBefore).toBe(2); expect(enemyAtkBefore).toBe(-2); - game.move.select(Moves.FREEZY_FROST); + game.doAttack(getMovePosition(game.scene, 0, Moves.FREEZY_FROST)); await game.phaseInterceptor.to(TurnInitPhase); expect(user.summonData.battleStats[BattleStat.ATK]).toBe(0); expect(enemy.summonData.battleStats[BattleStat.ATK]).toBe(0); @@ -68,13 +69,13 @@ describe("Moves - Freezy Frost", () => { const user = game.scene.getPlayerPokemon()!; expect(user.summonData.battleStats[BattleStat.ATK]).toBe(0); - game.move.select(Moves.SWORDS_DANCE); + game.doAttack(getMovePosition(game.scene, 0, Moves.SWORDS_DANCE)); await game.phaseInterceptor.to(TurnInitPhase); const userAtkBefore = user.summonData.battleStats[BattleStat.ATK]; expect(userAtkBefore).toBe(2); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(MoveEndPhase); expect(user.summonData.battleStats[BattleStat.ATK]).toBe(0); }); diff --git a/src/test/moves/fusion_bolt.test.ts b/src/test/moves/fusion_bolt.test.ts index db31863ad03..c7a21e2c736 100644 --- a/src/test/moves/fusion_bolt.test.ts +++ b/src/test/moves/fusion_bolt.test.ts @@ -1,9 +1,10 @@ -import { Abilities } from "#enums/abilities"; -import { Moves } from "#enums/moves"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Species } from "#enums/species"; +import { Moves } from "#enums/moves"; +import { Abilities } from "#enums/abilities"; describe("Moves - Fusion Bolt", () => { let phaserGame: Phaser.Game; @@ -23,19 +24,19 @@ describe("Moves - Fusion Bolt", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.moveset([fusionBolt]); + game.override.moveset([ fusionBolt ]); game.override.startingLevel(1); game.override.enemySpecies(Species.RESHIRAM); game.override.enemyAbility(Abilities.ROUGH_SKIN); - game.override.enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); game.override.battleType("single"); game.override.startingWave(97); game.override.disableCrits(); }); - it("should not make contact", async () => { + it("should not make contact", async() => { await game.startBattle([ Species.ZEKROM, ]); @@ -43,7 +44,7 @@ describe("Moves - Fusion Bolt", () => { const partyMember = game.scene.getPlayerPokemon()!; const initialHp = partyMember.hp; - game.move.select(fusionBolt); + game.doAttack(getMovePosition(game.scene, 0, fusionBolt)); await game.toNextTurn(); diff --git a/src/test/moves/fusion_flare.test.ts b/src/test/moves/fusion_flare.test.ts index 471f6a2ac7b..aa38357ddd3 100644 --- a/src/test/moves/fusion_flare.test.ts +++ b/src/test/moves/fusion_flare.test.ts @@ -1,10 +1,11 @@ -import { StatusEffect } from "#app/data/status-effect"; -import { TurnStartPhase } from "#app/phases/turn-start-phase"; -import { Moves } from "#enums/moves"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { StatusEffect } from "#app/data/status-effect"; +import { Species } from "#enums/species"; +import { Moves } from "#enums/moves"; +import { TurnStartPhase } from "#app/phases/turn-start-phase.js"; describe("Moves - Fusion Flare", () => { let phaserGame: Phaser.Game; @@ -24,25 +25,25 @@ describe("Moves - Fusion Flare", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.moveset([fusionFlare]); + game.override.moveset([ fusionFlare ]); game.override.startingLevel(1); game.override.enemySpecies(Species.RESHIRAM); - game.override.enemyMoveset([Moves.REST, Moves.REST, Moves.REST, Moves.REST]); + game.override.enemyMoveset([ Moves.REST, Moves.REST, Moves.REST, Moves.REST ]); game.override.battleType("single"); game.override.startingWave(97); game.override.disableCrits(); }); - it("should thaw freeze status condition", async () => { + it("should thaw freeze status condition", async() => { await game.startBattle([ Species.RESHIRAM, ]); const partyMember = game.scene.getPlayerPokemon()!; - game.move.select(fusionFlare); + game.doAttack(getMovePosition(game.scene, 0, fusionFlare)); await game.phaseInterceptor.to(TurnStartPhase, false); diff --git a/src/test/moves/fusion_flare_bolt.test.ts b/src/test/moves/fusion_flare_bolt.test.ts index ebef5148778..1b95062ee81 100644 --- a/src/test/moves/fusion_flare_bolt.test.ts +++ b/src/test/moves/fusion_flare_bolt.test.ts @@ -1,15 +1,16 @@ -import { BattlerIndex } from "#app/battle"; -import { allMoves } from "#app/data/move"; -import { Stat } from "#app/data/pokemon-stat"; -import { DamagePhase } from "#app/phases/damage-phase"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { MovePhase } from "#app/phases/move-phase"; -import { Moves } from "#enums/moves"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Stat } from "#app/data/pokemon-stat"; +import { allMoves } from "#app/data/move"; +import { BattlerIndex } from "#app/battle"; +import { Species } from "#enums/species"; +import { Moves } from "#enums/moves"; +import { DamagePhase } from "#app/phases/damage-phase.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { MovePhase } from "#app/phases/move-phase.js"; describe("Moves - Fusion Flare and Fusion Bolt", () => { let phaserGame: Phaser.Game; @@ -30,11 +31,11 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.moveset([fusionFlare.id, fusionBolt.id]); + game.override.moveset([ fusionFlare.id, fusionBolt.id ]); game.override.startingLevel(1); game.override.enemySpecies(Species.RESHIRAM); - game.override.enemyMoveset([Moves.REST, Moves.REST, Moves.REST, Moves.REST]); + game.override.enemyMoveset([ Moves.REST, Moves.REST, Moves.REST, Moves.REST ]); game.override.battleType("double"); game.override.startingWave(97); @@ -44,17 +45,20 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { vi.spyOn(fusionBolt, "calculateBattlePower"); }); - it("FUSION_FLARE should double power of subsequent FUSION_BOLT", async () => { + it("FUSION_FLARE should double power of subsequent FUSION_BOLT", async() => { await game.startBattle([ Species.ZEKROM, Species.ZEKROM ]); - game.move.select(fusionFlare.id, 0, BattlerIndex.ENEMY); - game.move.select(fusionBolt.id, 1, BattlerIndex.ENEMY); + game.doAttack(getMovePosition(game.scene, 0, fusionFlare.id)); + game.doSelectTarget(BattlerIndex.ENEMY); + + game.doAttack(getMovePosition(game.scene, 0, fusionBolt.id)); + game.doSelectTarget(BattlerIndex.ENEMY); // Force user party to act before enemy party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id); @@ -67,17 +71,20 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(200); }, 20000); - it("FUSION_BOLT should double power of subsequent FUSION_FLARE", async () => { + it("FUSION_BOLT should double power of subsequent FUSION_FLARE", async() => { await game.startBattle([ Species.ZEKROM, Species.ZEKROM ]); - game.move.select(fusionBolt.id, 0, BattlerIndex.ENEMY); - game.move.select(fusionFlare.id, 1, BattlerIndex.ENEMY); + game.doAttack(getMovePosition(game.scene, 0, fusionBolt.id)); + game.doSelectTarget(BattlerIndex.ENEMY); + + game.doAttack(getMovePosition(game.scene, 0, fusionFlare.id)); + game.doSelectTarget(BattlerIndex.ENEMY); // Force user party to act before enemy party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id); @@ -90,17 +97,20 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200); }, 20000); - it("FUSION_FLARE should double power of subsequent FUSION_BOLT if a move failed in between", async () => { + it("FUSION_FLARE should double power of subsequent FUSION_BOLT if a move failed in between", async() => { await game.startBattle([ Species.ZEKROM, Species.ZEKROM ]); - game.move.select(fusionFlare.id, 0, BattlerIndex.PLAYER); - game.move.select(fusionBolt.id, 1, BattlerIndex.PLAYER); + game.doAttack(getMovePosition(game.scene, 0, fusionFlare.id)); + game.doSelectTarget(0); + + game.doAttack(getMovePosition(game.scene, 0, fusionBolt.id)); + game.doSelectTarget(0); // Force first enemy to act (and fail) in between party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id); @@ -118,18 +128,21 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(200); }, 20000); - it("FUSION_FLARE should not double power of subsequent FUSION_BOLT if a move succeeded in between", async () => { - game.override.enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + it("FUSION_FLARE should not double power of subsequent FUSION_BOLT if a move succeeded in between", async() => { + game.override.enemyMoveset([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); await game.startBattle([ Species.ZEKROM, Species.ZEKROM ]); - game.move.select(fusionFlare.id, 0, BattlerIndex.ENEMY); - game.move.select(fusionBolt.id, 1, BattlerIndex.ENEMY); + game.doAttack(getMovePosition(game.scene, 0, fusionFlare.id)); + game.doSelectTarget(BattlerIndex.ENEMY); + + game.doAttack(getMovePosition(game.scene, 0, fusionBolt.id)); + game.doSelectTarget(BattlerIndex.ENEMY); // Force first enemy to act in between party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id); @@ -146,17 +159,20 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(100); }, 20000); - it("FUSION_FLARE should double power of subsequent FUSION_BOLT if moves are aimed at allies", async () => { + it("FUSION_FLARE should double power of subsequent FUSION_BOLT if moves are aimed at allies", async() => { await game.startBattle([ Species.ZEKROM, Species.RESHIRAM ]); - game.move.select(fusionBolt.id, 0, BattlerIndex.PLAYER_2); - game.move.select(fusionFlare.id, 1, BattlerIndex.PLAYER); + game.doAttack(getMovePosition(game.scene, 0, fusionBolt.id)); + game.doSelectTarget(BattlerIndex.PLAYER_2); + + game.doAttack(getMovePosition(game.scene, 0, fusionFlare.id)); + game.doSelectTarget(BattlerIndex.PLAYER); // Force user party to act before enemy party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id); @@ -169,8 +185,8 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200); }, 20000); - it("FUSION_FLARE and FUSION_BOLT alternating throughout turn should double power of subsequent moves", async () => { - game.override.enemyMoveset([fusionFlare.id, fusionFlare.id, fusionFlare.id, fusionFlare.id]); + it("FUSION_FLARE and FUSION_BOLT alternating throughout turn should double power of subsequent moves", async() => { + game.override.enemyMoveset([ fusionFlare.id, fusionFlare.id, fusionFlare.id, fusionFlare.id ]); await game.startBattle([ Species.ZEKROM, Species.ZEKROM @@ -201,11 +217,14 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { vi.spyOn(party[1], "stats", "get").mockReturnValue(stats.player[0].map((val, i) => (i === Stat.SPDEF ? 250 : val))); vi.spyOn(party[1], "stats", "get").mockReturnValue(stats.player[1].map((val, i) => (i === Stat.SPDEF ? 250 : val))); - game.move.select(fusionBolt.id, 0, BattlerIndex.ENEMY); - game.move.select(fusionBolt.id, 1, BattlerIndex.ENEMY); + game.doAttack(getMovePosition(game.scene, 0, fusionBolt.id)); + game.doSelectTarget(BattlerIndex.ENEMY); + + game.doAttack(getMovePosition(game.scene, 0, fusionBolt.id)); + game.doSelectTarget(BattlerIndex.ENEMY); // Force first enemy to act in between party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id); @@ -228,8 +247,8 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200); }, 20000); - it("FUSION_FLARE and FUSION_BOLT alternating throughout turn should double power of subsequent moves if moves are aimed at allies", async () => { - game.override.enemyMoveset([fusionFlare.id, fusionFlare.id, fusionFlare.id, fusionFlare.id]); + it("FUSION_FLARE and FUSION_BOLT alternating throughout turn should double power of subsequent moves if moves are aimed at allies", async() => { + game.override.enemyMoveset([ fusionFlare.id, fusionFlare.id, fusionFlare.id, fusionFlare.id ]); await game.startBattle([ Species.ZEKROM, Species.ZEKROM @@ -260,11 +279,14 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { vi.spyOn(party[1], "stats", "get").mockReturnValue(stats.player[0].map((val, i) => (i === Stat.SPDEF ? 250 : val))); vi.spyOn(party[1], "stats", "get").mockReturnValue(stats.player[1].map((val, i) => (i === Stat.SPDEF ? 250 : val))); - game.move.select(fusionBolt.id, 0, BattlerIndex.PLAYER_2); - game.move.select(fusionBolt.id, 1, BattlerIndex.PLAYER); + game.doAttack(getMovePosition(game.scene, 0, fusionBolt.id)); + game.doSelectTarget(BattlerIndex.PLAYER_2); + + game.doAttack(getMovePosition(game.scene, 0, fusionBolt.id)); + game.doSelectTarget(BattlerIndex.PLAYER); // Force first enemy to act in between party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id); diff --git a/src/test/moves/gastro_acid.test.ts b/src/test/moves/gastro_acid.test.ts index 67fd3464cf9..cc247890754 100644 --- a/src/test/moves/gastro_acid.test.ts +++ b/src/test/moves/gastro_acid.test.ts @@ -1,11 +1,12 @@ -import { BattlerIndex } from "#app/battle"; -import { Abilities } from "#app/enums/abilities"; -import { Moves } from "#app/enums/moves"; -import { Species } from "#app/enums/species"; -import { MoveResult } from "#app/field/pokemon"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { BattlerIndex } from "#app/battle.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { Moves } from "#app/enums/moves.js"; +import { Species } from "#app/enums/species.js"; +import { MoveResult } from "#app/field/pokemon.js"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; const TIMEOUT = 20 * 1000; @@ -45,8 +46,10 @@ describe("Moves - Gastro Acid", () => { await game.startBattle(); - game.move.select(Moves.GASTRO_ACID, 0, BattlerIndex.ENEMY); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.GASTRO_ACID)); + game.doSelectTarget(BattlerIndex.ENEMY); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + game.doSelectTarget(BattlerIndex.PLAYER_2); await game.phaseInterceptor.to("TurnInitPhase"); @@ -54,8 +57,10 @@ describe("Moves - Gastro Acid", () => { expect(enemyField[0].summonData.abilitySuppressed).toBe(true); expect(enemyField[1].summonData.abilitySuppressed).toBe(false); - game.move.select(Moves.WATER_GUN, 0, BattlerIndex.ENEMY); - game.move.select(Moves.WATER_GUN, 1, BattlerIndex.ENEMY_2); + game.doAttack(getMovePosition(game.scene, 0, Moves.WATER_GUN)); + game.doSelectTarget(BattlerIndex.ENEMY); + game.doAttack(getMovePosition(game.scene, 0, Moves.WATER_GUN)); + game.doSelectTarget(BattlerIndex.ENEMY_2); await game.phaseInterceptor.to("TurnEndPhase"); @@ -68,13 +73,13 @@ describe("Moves - Gastro Acid", () => { await game.startBattle(); - game.move.select(Moves.CORE_ENFORCER); + game.doAttack(getMovePosition(game.scene, 0, Moves.CORE_ENFORCER)); // Force player to be slower to enable Core Enforcer to proc its suppression effect await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.phaseInterceptor.to("TurnInitPhase"); - game.move.select(Moves.GASTRO_ACID); + game.doAttack(getMovePosition(game.scene, 0, Moves.GASTRO_ACID)); await game.phaseInterceptor.to("TurnInitPhase"); diff --git a/src/test/moves/glaive_rush.test.ts b/src/test/moves/glaive_rush.test.ts index 1eac3c32bb4..f97ba1f0367 100644 --- a/src/test/moves/glaive_rush.test.ts +++ b/src/test/moves/glaive_rush.test.ts @@ -1,12 +1,13 @@ -import { allMoves } from "#app/data/move"; -import { Abilities } from "#app/enums/abilities"; -import { DamagePhase } from "#app/phases/damage-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { allMoves } from "#app/data/move.js"; +import { Abilities } from "#app/enums/abilities.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { DamagePhase } from "#app/phases/damage-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Moves - Glaive Rush", () => { @@ -36,36 +37,36 @@ describe("Moves - Glaive Rush", () => { game.override.moveset([Moves.SHADOW_SNEAK, Moves.AVALANCHE, Moves.SPLASH, Moves.GLAIVE_RUSH]); }); - it("takes double damage from attacks", async () => { + it("takes double damage from attacks", async() => { await game.startBattle(); const enemy = game.scene.getEnemyPokemon()!; enemy.hp = 1000; vi.spyOn(game.scene, "randBattleSeedInt").mockReturnValue(0); - game.move.select(Moves.SHADOW_SNEAK); + game.doAttack(getMovePosition(game.scene, 0, Moves.SHADOW_SNEAK)); await game.phaseInterceptor.to(DamagePhase); const damageDealt = 1000 - enemy.hp; await game.phaseInterceptor.to(TurnEndPhase); - game.move.select(Moves.SHADOW_SNEAK); + game.doAttack(getMovePosition(game.scene, 0, Moves.SHADOW_SNEAK)); await game.phaseInterceptor.to(DamagePhase); expect(enemy.hp).toBeLessThanOrEqual(1001 - (damageDealt * 3)); }, 5000); // TODO: revert back to 20s - it("always gets hit by attacks", async () => { + it("always gets hit by attacks", async() => { await game.startBattle(); const enemy = game.scene.getEnemyPokemon()!; enemy.hp = 1000; allMoves[Moves.AVALANCHE].accuracy = 0; - game.move.select(Moves.AVALANCHE); + game.doAttack(getMovePosition(game.scene, 0, Moves.AVALANCHE)); await game.phaseInterceptor.to(TurnEndPhase); expect(enemy.hp).toBeLessThan(1000); }, 20000); - it("interacts properly with multi-lens", async () => { - game.override.startingHeldItems([{ name: "MULTI_LENS", count: 2 }]); + it("interacts properly with multi-lens", async() => { + game.override.startingHeldItems([{name: "MULTI_LENS", count: 2}]); game.override.enemyMoveset(Array(4).fill(Moves.AVALANCHE)); await game.startBattle(); const player = game.scene.getPlayerPokemon()!; @@ -74,17 +75,17 @@ describe("Moves - Glaive Rush", () => { player.hp = 1000; allMoves[Moves.AVALANCHE].accuracy = 0; - game.move.select(Moves.GLAIVE_RUSH); + game.doAttack(getMovePosition(game.scene, 0, Moves.GLAIVE_RUSH)); await game.phaseInterceptor.to(TurnEndPhase); expect(player.hp).toBeLessThan(1000); player.hp = 1000; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(player.hp).toBe(1000); }, 20000); - it("secondary effects only last until next move", async () => { + it("secondary effects only last until next move", async() => { game.override.enemyMoveset(Array(4).fill(Moves.SHADOW_SNEAK)); await game.startBattle(); const player = game.scene.getPlayerPokemon()!; @@ -93,22 +94,22 @@ describe("Moves - Glaive Rush", () => { player.hp = 1000; allMoves[Moves.SHADOW_SNEAK].accuracy = 0; - game.move.select(Moves.GLAIVE_RUSH); + game.doAttack(getMovePosition(game.scene, 0, Moves.GLAIVE_RUSH)); await game.phaseInterceptor.to(TurnEndPhase); expect(player.hp).toBe(1000); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); const damagedHp = player.hp; expect(player.hp).toBeLessThan(1000); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); expect(player.hp).toBe(damagedHp); }, 20000); - it("secondary effects are removed upon switching", async () => { + it("secondary effects are removed upon switching", async() => { game.override.enemyMoveset(Array(4).fill(Moves.SHADOW_SNEAK)); game.override.starterSpecies(0); await game.startBattle([Species.KLINK, Species.FEEBAS]); @@ -117,7 +118,7 @@ describe("Moves - Glaive Rush", () => { enemy.hp = 1000; allMoves[Moves.SHADOW_SNEAK].accuracy = 0; - game.move.select(Moves.GLAIVE_RUSH); + game.doAttack(getMovePosition(game.scene, 0, Moves.GLAIVE_RUSH)); await game.phaseInterceptor.to(TurnEndPhase); expect(player.hp).toBe(player.getMaxHp()); @@ -129,7 +130,7 @@ describe("Moves - Glaive Rush", () => { }, 20000); - it("secondary effects don't activate if move fails", async () => { + it("secondary effects don't activate if move fails", async() => { game.override.moveset([Moves.SHADOW_SNEAK, Moves.PROTECT, Moves.SPLASH, Moves.GLAIVE_RUSH]); await game.startBattle(); const player = game.scene.getPlayerPokemon()!; @@ -137,16 +138,16 @@ describe("Moves - Glaive Rush", () => { enemy.hp = 1000; player.hp = 1000; - game.move.select(Moves.PROTECT); + game.doAttack(getMovePosition(game.scene, 0, Moves.PROTECT)); await game.phaseInterceptor.to(TurnEndPhase); - game.move.select(Moves.SHADOW_SNEAK); + game.doAttack(getMovePosition(game.scene, 0, Moves.SHADOW_SNEAK)); await game.phaseInterceptor.to(TurnEndPhase); game.override.enemyMoveset(Array(4).fill(Moves.SPLASH)); const damagedHP1 = 1000 - enemy.hp; enemy.hp = 1000; - game.move.select(Moves.SHADOW_SNEAK); + game.doAttack(getMovePosition(game.scene, 0, Moves.SHADOW_SNEAK)); await game.phaseInterceptor.to(TurnEndPhase); const damagedHP2 = 1000 - enemy.hp; diff --git a/src/test/moves/growth.test.ts b/src/test/moves/growth.test.ts index dfbf5406351..0c60bb723f4 100644 --- a/src/test/moves/growth.test.ts +++ b/src/test/moves/growth.test.ts @@ -1,13 +1,17 @@ import { BattleStat } from "#app/data/battle-stat"; import { Stat } from "#app/data/pokemon-stat"; -import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Command } from "#app/ui/command-ui-handler"; +import { Mode } from "#app/ui/ui"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { EnemyCommandPhase } from "#app/phases/enemy-command-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; describe("Moves - Growth", () => { @@ -33,10 +37,10 @@ describe("Moves - Growth", () => { game.override.ability(Abilities.INSOMNIA); game.override.startingLevel(2000); game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); - it("GROWTH", async () => { + it("GROWTH", async() => { const moveToUse = Moves.GROWTH; await game.startBattle([ Species.MIGHTYENA, @@ -48,7 +52,13 @@ describe("Moves - Growth", () => { const battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats; expect(battleStatsOpponent[BattleStat.SPATK]).toBe(0); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase); battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats; expect(battleStatsPokemon[BattleStat.SPATK]).toBe(1); diff --git a/src/test/moves/hard_press.test.ts b/src/test/moves/hard_press.test.ts index 70c78490269..255b9f1f4b1 100644 --- a/src/test/moves/hard_press.test.ts +++ b/src/test/moves/hard_press.test.ts @@ -1,12 +1,13 @@ -import { allMoves } from "#app/data/move"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import { allMoves } from "#app/data/move.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; describe("Moves - Hard Press", () => { let phaserGame: Phaser.Game; @@ -38,7 +39,7 @@ describe("Moves - Hard Press", () => { it("should return 100 power if target HP ratio is at 100%", async () => { await game.startBattle([Species.PIKACHU]); - game.move.select(Moves.HARD_PRESS); + game.doAttack(getMovePosition(game.scene, 0, Moves.HARD_PRESS)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(100); @@ -51,7 +52,7 @@ describe("Moves - Hard Press", () => { vi.spyOn(enemy, "getHpRatio").mockReturnValue(targetHpRatio); - game.move.select(Moves.HARD_PRESS); + game.doAttack(getMovePosition(game.scene, 0, Moves.HARD_PRESS)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(50); @@ -64,7 +65,7 @@ describe("Moves - Hard Press", () => { vi.spyOn(enemy, "getHpRatio").mockReturnValue(targetHpRatio); - game.move.select(Moves.HARD_PRESS); + game.doAttack(getMovePosition(game.scene, 0, Moves.HARD_PRESS)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(1); @@ -77,7 +78,7 @@ describe("Moves - Hard Press", () => { vi.spyOn(enemy, "getHpRatio").mockReturnValue(targetHpRatio); - game.move.select(Moves.HARD_PRESS); + game.doAttack(getMovePosition(game.scene, 0, Moves.HARD_PRESS)); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(1); diff --git a/src/test/moves/haze.test.ts b/src/test/moves/haze.test.ts index 8a32a40cb32..d5e3efcbd9d 100644 --- a/src/test/moves/haze.test.ts +++ b/src/test/moves/haze.test.ts @@ -1,13 +1,14 @@ import { BattleStat } from "#app/data/battle-stat"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; describe("Moves - Haze", () => { describe("integration tests", () => { @@ -44,17 +45,17 @@ describe("Moves - Haze", () => { expect(user.summonData.battleStats[BattleStat.ATK]).toBe(0); expect(enemy.summonData.battleStats[BattleStat.ATK]).toBe(0); - game.move.select(Moves.SWORDS_DANCE); + game.doAttack(getMovePosition(game.scene, 0, Moves.SWORDS_DANCE)); await game.phaseInterceptor.to(TurnInitPhase); - game.move.select(Moves.CHARM); + game.doAttack(getMovePosition(game.scene, 0, Moves.CHARM)); await game.phaseInterceptor.to(TurnInitPhase); const userAtkBefore = user.summonData.battleStats[BattleStat.ATK]; const enemyAtkBefore = enemy.summonData.battleStats[BattleStat.ATK]; expect(userAtkBefore).toBe(2); expect(enemyAtkBefore).toBe(-2); - game.move.select(Moves.HAZE); + game.doAttack(getMovePosition(game.scene, 0, Moves.HAZE)); await game.phaseInterceptor.to(TurnInitPhase); expect(user.summonData.battleStats[BattleStat.ATK]).toBe(0); expect(enemy.summonData.battleStats[BattleStat.ATK]).toBe(0); @@ -66,13 +67,13 @@ describe("Moves - Haze", () => { const user = game.scene.getPlayerPokemon()!; expect(user.summonData.battleStats[BattleStat.ATK]).toBe(0); - game.move.select(Moves.SWORDS_DANCE); + game.doAttack(getMovePosition(game.scene, 0, Moves.SWORDS_DANCE)); await game.phaseInterceptor.to(TurnInitPhase); const userAtkBefore = user.summonData.battleStats[BattleStat.ATK]; expect(userAtkBefore).toBe(2); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(MoveEndPhase); expect(user.summonData.battleStats[BattleStat.ATK]).toBe(0); }); diff --git a/src/test/moves/hyper_beam.test.ts b/src/test/moves/hyper_beam.test.ts index 1280d8b429a..ac8075081fb 100644 --- a/src/test/moves/hyper_beam.test.ts +++ b/src/test/moves/hyper_beam.test.ts @@ -1,13 +1,14 @@ -import { allMoves } from "#app/data/move"; -import { Abilities } from "#app/enums/abilities"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { Moves } from "#app/enums/moves"; -import { Species } from "#app/enums/species"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { allMoves } from "#app/data/move.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { Moves } from "#app/enums/moves.js"; +import { Species } from "#app/enums/species.js"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; // 20 sec timeout for all tests @@ -47,7 +48,7 @@ describe("Moves - Hyper Beam", () => { const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.HYPER_BEAM); + game.doAttack(getMovePosition(game.scene, 0, Moves.HYPER_BEAM)); await game.phaseInterceptor.to(TurnEndPhase); @@ -62,7 +63,7 @@ describe("Moves - Hyper Beam", () => { expect(enemyPokemon.hp).toBe(enemyPostAttackHp); expect(leadPokemon.getTag(BattlerTagType.RECHARGING)).toBeUndefined(); - game.move.select(Moves.TACKLE); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); await game.phaseInterceptor.to(BerryPhase, false); diff --git a/src/test/moves/jaw_lock.test.ts b/src/test/moves/jaw_lock.test.ts deleted file mode 100644 index 42f7a244977..00000000000 --- a/src/test/moves/jaw_lock.test.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { BattlerIndex } from "#app/battle"; -import { Abilities } from "#app/enums/abilities"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { FaintPhase } from "#app/phases/faint-phase"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import GameManager from "#app/test/utils/gameManager"; -import { SPLASH_ONLY } from "#app/test/utils/testUtils"; -import { Moves } from "#enums/moves"; -import { Species } from "#enums/species"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - -const TIMEOUT = 20 * 1000; - -describe("Moves - Jaw Lock", () => { - 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.SNORLAX) - .enemyAbility(Abilities.INSOMNIA) - .enemyMoveset(SPLASH_ONLY) - .moveset([Moves.JAW_LOCK, Moves.SPLASH]) - .startingLevel(100) - .enemyLevel(100) - .disableCrits(); - }); - - it( - "should trap the move's user and target", - async () => { - await game.startBattle([Species.BULBASAUR]); - - const leadPokemon = game.scene.getPlayerPokemon()!; - const enemyPokemon = game.scene.getEnemyPokemon()!; - - game.move.select(Moves.JAW_LOCK); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); - - await game.phaseInterceptor.to(MoveEffectPhase, false); - - expect(leadPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - expect(enemyPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - - await game.phaseInterceptor.to(TurnEndPhase); - - expect(leadPokemon.getTag(BattlerTagType.TRAPPED)).toBeDefined(); - expect(enemyPokemon.getTag(BattlerTagType.TRAPPED)).toBeDefined(); - }, TIMEOUT - ); - - it( - "should not trap either pokemon if the target faints", - async () => { - game.override.enemyLevel(1); - await game.startBattle([Species.BULBASAUR]); - - const leadPokemon = game.scene.getPlayerPokemon()!; - const enemyPokemon = game.scene.getEnemyPokemon()!; - - game.move.select(Moves.JAW_LOCK); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); - - await game.phaseInterceptor.to(MoveEffectPhase, false); - - expect(leadPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - expect(enemyPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - - await game.phaseInterceptor.to(MoveEffectPhase); - - expect(leadPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - expect(enemyPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - - await game.phaseInterceptor.to(FaintPhase); - - expect(leadPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - expect(enemyPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - }, TIMEOUT - ); - - it( - "should only trap the user until the target faints", - async () => { - await game.startBattle([Species.BULBASAUR]); - - const leadPokemon = game.scene.getPlayerPokemon()!; - const enemyPokemon = game.scene.getEnemyPokemon()!; - - game.move.select(Moves.JAW_LOCK); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); - - await game.phaseInterceptor.to(MoveEffectPhase); - - expect(leadPokemon.getTag(BattlerTagType.TRAPPED)).toBeDefined(); - expect(enemyPokemon.getTag(BattlerTagType.TRAPPED)).toBeDefined(); - - await game.phaseInterceptor.to(TurnEndPhase); - - await game.doKillOpponents(); - - expect(leadPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - }, TIMEOUT - ); - - it( - "should not trap other targets after the first target is trapped", - async () => { - game.override.battleType("double"); - - await game.startBattle([Species.CHARMANDER, Species.BULBASAUR]); - - const playerPokemon = game.scene.getPlayerField(); - const enemyPokemon = game.scene.getEnemyField(); - - game.move.select(Moves.JAW_LOCK, 0, BattlerIndex.ENEMY); - game.move.select(Moves.SPLASH, 1); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); - - await game.phaseInterceptor.to(MoveEffectPhase); - - expect(playerPokemon[0].getTag(BattlerTagType.TRAPPED)).toBeDefined(); - expect(enemyPokemon[0].getTag(BattlerTagType.TRAPPED)).toBeDefined(); - - await game.toNextTurn(); - - game.move.select(Moves.JAW_LOCK, 0, BattlerIndex.ENEMY_2); - game.move.select(Moves.SPLASH, 1); - - await game.phaseInterceptor.to(MoveEffectPhase); - - expect(enemyPokemon[1].getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - expect(playerPokemon[0].getTag(BattlerTagType.TRAPPED)).toBeDefined(); - expect(playerPokemon[0].getTag(BattlerTagType.TRAPPED)?.sourceId).toBe(enemyPokemon[0].id); - }, TIMEOUT - ); - - it( - "should not trap either pokemon if the target is protected", - async () => { - game.override.enemyMoveset(Array(4).fill(Moves.PROTECT)); - - await game.startBattle([Species.BULBASAUR]); - - const playerPokemon = game.scene.getPlayerPokemon()!; - const enemyPokemon = game.scene.getEnemyPokemon()!; - - game.move.select(Moves.JAW_LOCK); - - await game.phaseInterceptor.to(BerryPhase, false); - - expect(playerPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - expect(enemyPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - }, TIMEOUT - ); -}); diff --git a/src/test/moves/light_screen.test.ts b/src/test/moves/light_screen.test.ts index e94dc4a299e..4577ffc574a 100644 --- a/src/test/moves/light_screen.test.ts +++ b/src/test/moves/light_screen.test.ts @@ -1,13 +1,14 @@ -import { ArenaTagSide } from "#app/data/arena-tag"; -import Move, { allMoves } from "#app/data/move"; -import { Abilities } from "#app/enums/abilities"; -import { ArenaTagType } from "#app/enums/arena-tag-type"; -import Pokemon from "#app/field/pokemon"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { NumberHolder } from "#app/utils"; +import { ArenaTagSide } from "#app/data/arena-tag.js"; +import Move, { allMoves } from "#app/data/move.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { ArenaTagType } from "#app/enums/arena-tag-type.js"; +import Pokemon from "#app/field/pokemon.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { NumberHolder } from "#app/utils.js"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -16,7 +17,7 @@ describe("Moves - Light Screen", () => { let phaserGame: Phaser.Game; let game: GameManager; const singleBattleMultiplier = 0.5; - const doubleBattleMultiplier = 2732 / 4096; + const doubleBattleMultiplier = 2732/4096; beforeAll(() => { phaserGame = new Phaser.Game({ @@ -39,11 +40,11 @@ describe("Moves - Light Screen", () => { game.override.disableCrits(); }); - it("reduces damage of special attacks by half in a single battle", async () => { + it("reduces damage of special attacks by half in a single battle", async() => { const moveToUse = Moves.ABSORB; await game.startBattle([Species.SHUCKLE]); - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); @@ -52,14 +53,14 @@ describe("Moves - Light Screen", () => { expect(mockedDmg).toBe(allMoves[moveToUse].power * singleBattleMultiplier); }); - it("reduces damage of special attacks by a third in a double battle", async () => { + it("reduces damage of special attacks by a third in a double battle", async() => { game.override.battleType("double"); const moveToUse = Moves.DAZZLING_GLEAM; await game.startBattle([Species.SHUCKLE, Species.SHUCKLE]); - game.move.select(moveToUse); - game.move.select(moveToUse, 1); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); + game.doAttack(getMovePosition(game.scene, 1, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); const mockedDmg = getMockedMoveDamage(game.scene.getEnemyPokemon()!, game.scene.getPlayerPokemon()!, allMoves[moveToUse]); @@ -67,11 +68,11 @@ describe("Moves - Light Screen", () => { expect(mockedDmg).toBe(allMoves[moveToUse].power * doubleBattleMultiplier); }); - it("does not affect physical attacks", async () => { + it("does not affect physical attacks", async() => { const moveToUse = Moves.TACKLE; await game.startBattle([Species.SHUCKLE]); - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); const mockedDmg = getMockedMoveDamage(game.scene.getEnemyPokemon()!, game.scene.getPlayerPokemon()!, allMoves[moveToUse]); diff --git a/src/test/moves/lucky_chant.test.ts b/src/test/moves/lucky_chant.test.ts index 7d5bfe02476..643a5eddb00 100644 --- a/src/test/moves/lucky_chant.test.ts +++ b/src/test/moves/lucky_chant.test.ts @@ -1,11 +1,12 @@ -import { Abilities } from "#app/enums/abilities"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { Moves } from "#app/enums/moves"; -import { Species } from "#app/enums/species"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import GameManager from "../utils/gameManager"; +import { getMovePosition } from "../utils/gameManagerUtils"; +import { Moves } from "#app/enums/moves.js"; +import { Species } from "#app/enums/species.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -43,13 +44,13 @@ describe("Moves - Lucky Chant", () => { const playerPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); const firstTurnDamage = playerPokemon.getMaxHp() - playerPokemon.hp; - game.move.select(Moves.LUCKY_CHANT); + game.doAttack(getMovePosition(game.scene, 0, Moves.LUCKY_CHANT)); await game.phaseInterceptor.to(BerryPhase, false); @@ -67,15 +68,15 @@ describe("Moves - Lucky Chant", () => { const playerPokemon = game.scene.getPlayerField(); - game.move.select(Moves.FOLLOW_ME); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.FOLLOW_ME)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); const firstTurnDamage = playerPokemon[0].getMaxHp() - playerPokemon[0].hp; - game.move.select(Moves.FOLLOW_ME); - game.move.select(Moves.LUCKY_CHANT, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.FOLLOW_ME)); + game.doAttack(getMovePosition(game.scene, 1, Moves.LUCKY_CHANT)); await game.phaseInterceptor.to(BerryPhase, false); @@ -96,13 +97,13 @@ describe("Moves - Lucky Chant", () => { enemyPokemon.addTag(BattlerTagType.ALWAYS_CRIT, 2, Moves.NONE, 0); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); const firstTurnDamage = playerPokemon.getMaxHp() - playerPokemon.hp; - game.move.select(Moves.LUCKY_CHANT); + game.doAttack(getMovePosition(game.scene, 0, Moves.LUCKY_CHANT)); await game.phaseInterceptor.to(BerryPhase, false); diff --git a/src/test/moves/magnet_rise.test.ts b/src/test/moves/magnet_rise.test.ts index 9037e377090..4ab32b5d048 100644 --- a/src/test/moves/magnet_rise.test.ts +++ b/src/test/moves/magnet_rise.test.ts @@ -1,15 +1,14 @@ -import { CommandPhase } from "#app/phases/command-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import GameManager from "#test/utils/gameManager"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Moves - Magnet Rise", () => { let phaserGame: Phaser.Game; let game: GameManager; - const moveToUse = Moves.MAGNET_RISE; beforeAll(() => { phaserGame = new Phaser.Game({ @@ -23,6 +22,7 @@ describe("Moves - Magnet Rise", () => { beforeEach(() => { game = new GameManager(phaserGame); + const moveToUse = Moves.MAGNET_RISE; game.override.battleType("single"); game.override.starterSpecies(Species.MAGNEZONE); game.override.enemySpecies(Species.RATTATA); @@ -36,7 +36,7 @@ describe("Moves - Magnet Rise", () => { await game.startBattle(); const startingHp = game.scene.getParty()[0].hp; - game.move.select(moveToUse); + game.doAttack(0); await game.phaseInterceptor.to(TurnEndPhase); const finalHp = game.scene.getParty()[0].hp; const hpLost = finalHp - startingHp; @@ -47,12 +47,12 @@ describe("Moves - Magnet Rise", () => { await game.startBattle(); const startingHp = game.scene.getParty()[0].hp; - game.move.select(moveToUse); + game.doAttack(0); await game.phaseInterceptor.to(CommandPhase); let finalHp = game.scene.getParty()[0].hp; let hpLost = finalHp - startingHp; expect(hpLost).toBe(0); - game.move.select(Moves.GRAVITY); + game.doAttack(2); await game.phaseInterceptor.to(TurnEndPhase); finalHp = game.scene.getParty()[0].hp; hpLost = finalHp - startingHp; diff --git a/src/test/moves/make_it_rain.test.ts b/src/test/moves/make_it_rain.test.ts index 0af7763f175..5b0a8c6d62a 100644 --- a/src/test/moves/make_it_rain.test.ts +++ b/src/test/moves/make_it_rain.test.ts @@ -1,13 +1,14 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { StatChangePhase } from "#app/phases/stat-change-phase"; +import { BattleStat } from "#app/data/battle-stat.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { StatChangePhase } from "#app/phases/stat-change-phase.js"; const TIMEOUT = 20 * 1000; @@ -41,8 +42,8 @@ describe("Moves - Make It Rain", () => { const playerPokemon = game.scene.getPlayerField(); - game.move.select(Moves.MAKE_IT_RAIN); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.MAKE_IT_RAIN)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(MoveEndPhase); @@ -58,7 +59,7 @@ describe("Moves - Make It Rain", () => { const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.MAKE_IT_RAIN); + game.doAttack(getMovePosition(game.scene, 0, Moves.MAKE_IT_RAIN)); await game.phaseInterceptor.to(StatChangePhase); @@ -74,8 +75,8 @@ describe("Moves - Make It Rain", () => { const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); - game.move.select(Moves.MAKE_IT_RAIN); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.MAKE_IT_RAIN)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(StatChangePhase); @@ -88,8 +89,8 @@ describe("Moves - Make It Rain", () => { const playerPokemon = game.scene.getPlayerField(); - game.move.select(Moves.MAKE_IT_RAIN); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.MAKE_IT_RAIN)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); // Make Make It Rain miss the first target await game.move.forceMiss(true); diff --git a/src/test/moves/mat_block.test.ts b/src/test/moves/mat_block.test.ts index 29a97806242..27a55cab289 100644 --- a/src/test/moves/mat_block.test.ts +++ b/src/test/moves/mat_block.test.ts @@ -1,13 +1,14 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { CommandPhase } from "#app/phases/command-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -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, test } from "vitest"; import GameManager from "../utils/gameManager"; +import { Species } from "#enums/species"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "../utils/gameManagerUtils"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -47,11 +48,11 @@ describe("Moves - Mat Block", () => { const leadPokemon = game.scene.getPlayerField(); - game.move.select(Moves.MAT_BLOCK); + game.doAttack(getMovePosition(game.scene, 0, Moves.MAT_BLOCK)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(BerryPhase, false); @@ -68,11 +69,11 @@ describe("Moves - Mat Block", () => { const leadPokemon = game.scene.getPlayerField(); - game.move.select(Moves.MAT_BLOCK); + game.doAttack(getMovePosition(game.scene, 0, Moves.MAT_BLOCK)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(BerryPhase, false); @@ -87,18 +88,18 @@ describe("Moves - Mat Block", () => { const leadPokemon = game.scene.getPlayerField(); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); const leadStartingHp = leadPokemon.map(p => p.hp); await game.phaseInterceptor.to(CommandPhase, false); - game.move.select(Moves.MAT_BLOCK); + game.doAttack(getMovePosition(game.scene, 0, Moves.MAT_BLOCK)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.MAT_BLOCK, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.MAT_BLOCK)); await game.phaseInterceptor.to(BerryPhase, false); diff --git a/src/test/moves/miracle_eye.test.ts b/src/test/moves/miracle_eye.test.ts index f47e4ce0c16..3e1e151e7d4 100644 --- a/src/test/moves/miracle_eye.test.ts +++ b/src/test/moves/miracle_eye.test.ts @@ -1,11 +1,12 @@ -import { BattlerIndex } from "#app/battle"; -import { Moves } from "#app/enums/moves"; -import { Species } from "#app/enums/species"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { Species } from "#app/enums/species.js"; import { SPLASH_ONLY } from "../utils/testUtils"; +import { Moves } from "#app/enums/moves.js"; +import { getMovePosition } from "../utils/gameManagerUtils"; +import { BattlerIndex } from "#app/battle.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; describe("Moves - Miracle Eye", () => { let phaserGame: Phaser.Game; @@ -37,14 +38,14 @@ describe("Moves - Miracle Eye", () => { const enemy = game.scene.getEnemyPokemon()!; - game.move.select(Moves.CONFUSION); + game.doAttack(getMovePosition(game.scene, 0, Moves.CONFUSION)); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.toNextTurn(); expect(enemy.hp).toBe(enemy.getMaxHp()); - game.move.select(Moves.MIRACLE_EYE); + game.doAttack(getMovePosition(game.scene, 0, Moves.MIRACLE_EYE)); await game.toNextTurn(); - game.move.select(Moves.CONFUSION); + game.doAttack(getMovePosition(game.scene, 0, Moves.CONFUSION)); await game.phaseInterceptor.to(MoveEffectPhase); expect(enemy.hp).toBeLessThan(enemy.getMaxHp()); diff --git a/src/test/moves/multi_target.test.ts b/src/test/moves/multi_target.test.ts index b8c1f67b3df..6e8a7c99e9b 100644 --- a/src/test/moves/multi_target.test.ts +++ b/src/test/moves/multi_target.test.ts @@ -1,12 +1,13 @@ -import { getMoveTargets } from "#app/data/move"; -import { Abilities } from "#app/enums/abilities"; -import { Species } from "#app/enums/species"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { Moves } from "#enums/moves"; +import { getMoveTargets } from "#app/data/move.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { Species } from "#app/enums/species.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { Moves } from "#enums/moves"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; const TIMEOUT = 20 * 1000; @@ -94,8 +95,8 @@ async function checkDamageDecrease(game: GameManager, attackMove: Moves, killAll game.scene.getEnemyField()[1].abilityIndex = ability; } - game.move.select(Moves.SPLASH); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); @@ -104,9 +105,9 @@ async function checkDamageDecrease(game: GameManager, attackMove: Moves, killAll await game.toNextTurn(); const initialHp = game.scene.getEnemyField()[0].hp; - game.move.select(attackMove); + game.doAttack(getMovePosition(game.scene, 0, attackMove)); if (!killAlly) { - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); } await game.phaseInterceptor.to(TurnEndPhase); @@ -118,7 +119,7 @@ async function checkDamageDecrease(game: GameManager, attackMove: Moves, killAll game.scene.getEnemyField()[0].hp = initialHp; const initialHp1v1 = game.scene.getEnemyField()[0].hp; - game.move.select(attackMove); + game.doAttack(getMovePosition(game.scene, 0, attackMove)); await game.phaseInterceptor.to(TurnEndPhase); const afterHp1v1 = game.scene.getEnemyField()[0].hp; diff --git a/src/test/moves/octolock.test.ts b/src/test/moves/octolock.test.ts index 389e4a4c4cf..fcd68446eff 100644 --- a/src/test/moves/octolock.test.ts +++ b/src/test/moves/octolock.test.ts @@ -1,15 +1,16 @@ import { BattleStat } from "#app/data/battle-stat"; -import { TrappedTag } from "#app/data/battler-tags"; -import { CommandPhase } from "#app/phases/command-phase"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import { TrappedTag } from "#app/data/battler-tags.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; describe("Moves - Octolock", () => { describe("integration tests", () => { @@ -46,7 +47,7 @@ describe("Moves - Octolock", () => { const enemyPokemon = game.scene.getEnemyField(); // use Octolock and advance to init phase of next turn to check for stat changes - game.move.select(Moves.OCTOLOCK); + game.doAttack(getMovePosition(game.scene, 0, Moves.OCTOLOCK)); await game.phaseInterceptor.to(TurnInitPhase); expect(enemyPokemon[0].summonData.battleStats[BattleStat.DEF]).toBe(-1); @@ -54,7 +55,7 @@ describe("Moves - Octolock", () => { // take a second turn to make sure stat changes occur again await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.phaseInterceptor.to(TurnInitPhase); expect(enemyPokemon[0].summonData.battleStats[BattleStat.DEF]).toBe(-2); @@ -69,7 +70,7 @@ describe("Moves - Octolock", () => { // before Octolock - enemy should not be trapped expect(enemyPokemon[0].findTag(t => t instanceof TrappedTag)).toBeUndefined(); - game.move.select(Moves.OCTOLOCK); + game.doAttack(getMovePosition(game.scene, 0, Moves.OCTOLOCK)); // after Octolock - enemy should be trapped await game.phaseInterceptor.to(MoveEndPhase); diff --git a/src/test/moves/parting_shot.test.ts b/src/test/moves/parting_shot.test.ts index 7c2ca3f334c..32995d2d563 100644 --- a/src/test/moves/parting_shot.test.ts +++ b/src/test/moves/parting_shot.test.ts @@ -1,15 +1,16 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { FaintPhase } from "#app/phases/faint-phase"; -import { MessagePhase } from "#app/phases/message-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import { SPLASH_ONLY } from "../utils/testUtils"; 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, test } from "vitest"; +import { afterEach, beforeAll, beforeEach, describe, expect, test, it } from "vitest"; import GameManager from "../utils/gameManager"; -import { SPLASH_ONLY } from "../utils/testUtils"; +import { getMovePosition } from "../utils/gameManagerUtils"; +import { BattleStat } from "#app/data/battle-stat"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { FaintPhase } from "#app/phases/faint-phase.js"; +import { MessagePhase } from "#app/phases/message-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; const TIMEOUT = 20 * 1000; @@ -48,7 +49,7 @@ describe("Moves - Parting Shot", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).toBeDefined(); - game.move.select(Moves.PARTING_SHOT); + game.doAttack(getMovePosition(game.scene, 0, Moves.PARTING_SHOT)); await game.phaseInterceptor.to(BerryPhase, false); const battleStatsOpponent = enemyPokemon.summonData.battleStats; @@ -69,7 +70,7 @@ describe("Moves - Parting Shot", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).toBeDefined(); - game.move.select(Moves.PARTING_SHOT); + game.doAttack(getMovePosition(game.scene, 0, Moves.PARTING_SHOT)); await game.phaseInterceptor.to(BerryPhase, false); const battleStatsOpponent = enemyPokemon.summonData.battleStats; @@ -86,19 +87,19 @@ describe("Moves - Parting Shot", () => { await game.startBattle([Species.MEOWTH, Species.MEOWTH, Species.MEOWTH, Species.MURKROW, Species.ABRA]); // use Memento 3 times to debuff enemy - game.move.select(Moves.MEMENTO); + game.doAttack(getMovePosition(game.scene, 0, Moves.MEMENTO)); await game.phaseInterceptor.to(FaintPhase); expect(game.scene.getParty()[0].isFainted()).toBe(true); game.doSelectPartyPokemon(1); await game.phaseInterceptor.to(TurnInitPhase, false); - game.move.select(Moves.MEMENTO); + game.doAttack(getMovePosition(game.scene, 0, Moves.MEMENTO)); await game.phaseInterceptor.to(FaintPhase); expect(game.scene.getParty()[0].isFainted()).toBe(true); game.doSelectPartyPokemon(2); await game.phaseInterceptor.to(TurnInitPhase, false); - game.move.select(Moves.MEMENTO); + game.doAttack(getMovePosition(game.scene, 0, Moves.MEMENTO)); await game.phaseInterceptor.to(FaintPhase); expect(game.scene.getParty()[0].isFainted()).toBe(true); game.doSelectPartyPokemon(3); @@ -113,7 +114,7 @@ describe("Moves - Parting Shot", () => { expect(battleStatsOpponent[BattleStat.SPATK]).toBe(-6); // now parting shot should fail - game.move.select(Moves.PARTING_SHOT); + game.doAttack(getMovePosition(game.scene, 0, Moves.PARTING_SHOT)); await game.phaseInterceptor.to(BerryPhase, false); expect(battleStatsOpponent[BattleStat.ATK]).toBe(-6); @@ -134,7 +135,7 @@ describe("Moves - Parting Shot", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).toBeDefined(); - game.move.select(Moves.PARTING_SHOT); + game.doAttack(getMovePosition(game.scene, 0, Moves.PARTING_SHOT)); await game.phaseInterceptor.to(BerryPhase, false); const battleStatsOpponent = enemyPokemon.summonData.battleStats; @@ -155,7 +156,7 @@ describe("Moves - Parting Shot", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).toBeDefined(); - game.move.select(Moves.PARTING_SHOT); + game.doAttack(getMovePosition(game.scene, 0, Moves.PARTING_SHOT)); await game.phaseInterceptor.to(BerryPhase, false); const battleStatsOpponent = enemyPokemon.summonData.battleStats; @@ -173,7 +174,7 @@ describe("Moves - Parting Shot", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).toBeDefined(); - game.move.select(Moves.PARTING_SHOT); + game.doAttack(getMovePosition(game.scene, 0, Moves.PARTING_SHOT)); await game.phaseInterceptor.to(BerryPhase, false); const battleStatsOpponent = enemyPokemon.summonData.battleStats; @@ -187,7 +188,7 @@ describe("Moves - Parting Shot", () => { "Parting shot regularly not fail if no party available to switch - party fainted", async () => { await game.startBattle([Species.MURKROW, Species.MEOWTH]); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); // intentionally kill party pokemon, switch to second slot (now 1 party mon is fainted) await game.killPokemon(game.scene.getParty()[0]); @@ -196,7 +197,7 @@ describe("Moves - Parting Shot", () => { game.doSelectPartyPokemon(1); await game.phaseInterceptor.to(TurnInitPhase, false); - game.move.select(Moves.PARTING_SHOT); + game.doAttack(getMovePosition(game.scene, 0, Moves.PARTING_SHOT)); await game.phaseInterceptor.to(BerryPhase, false); const battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats; diff --git a/src/test/moves/protect.test.ts b/src/test/moves/protect.test.ts index 3fd51f4bc93..4d97ef5ce82 100644 --- a/src/test/moves/protect.test.ts +++ b/src/test/moves/protect.test.ts @@ -1,13 +1,14 @@ -import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; -import { BattleStat } from "#app/data/battle-stat"; -import { allMoves } from "#app/data/move"; -import { BerryPhase } from "#app/phases/berry-phase"; -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, test, vi } from "vitest"; import GameManager from "../utils/gameManager"; +import { Species } from "#enums/species"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "../utils/gameManagerUtils"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { allMoves } from "#app/data/move.js"; +import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag.js"; +import { BerryPhase } from "#app/phases/berry-phase.js"; const TIMEOUT = 20 * 1000; @@ -47,7 +48,7 @@ describe("Moves - Protect", () => { const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.PROTECT); + game.doAttack(getMovePosition(game.scene, 0, Moves.PROTECT)); await game.phaseInterceptor.to(BerryPhase, false); @@ -65,7 +66,7 @@ describe("Moves - Protect", () => { const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.PROTECT); + game.doAttack(getMovePosition(game.scene, 0, Moves.PROTECT)); await game.phaseInterceptor.to(BerryPhase, false); @@ -83,7 +84,7 @@ describe("Moves - Protect", () => { const leadPokemon = game.scene.getPlayerPokemon()!; - game.move.select(Moves.PROTECT); + game.doAttack(getMovePosition(game.scene, 0, Moves.PROTECT)); await game.phaseInterceptor.to(BerryPhase, false); @@ -102,7 +103,7 @@ describe("Moves - Protect", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.PROTECT); + game.doAttack(getMovePosition(game.scene, 0, Moves.PROTECT)); await game.phaseInterceptor.to(BerryPhase, false); diff --git a/src/test/moves/purify.test.ts b/src/test/moves/purify.test.ts index 15d684b2d60..3020e4b47ac 100644 --- a/src/test/moves/purify.test.ts +++ b/src/test/moves/purify.test.ts @@ -1,12 +1,13 @@ -import { BattlerIndex } from "#app/battle"; -import { Status, StatusEffect } from "#app/data/status-effect"; -import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; +import { Status, StatusEffect } from "#app/data/status-effect.js"; +import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import { BattlerIndex } from "#app/battle.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -48,7 +49,7 @@ describe("Moves - Purify", () => { playerPokemon.hp = playerPokemon.getMaxHp() - 1; enemyPokemon.status = new Status(StatusEffect.BURN); - game.move.select(Moves.PURIFY); + game.doAttack(getMovePosition(game.scene, 0, Moves.PURIFY)); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.phaseInterceptor.to(MoveEndPhase); @@ -68,7 +69,7 @@ describe("Moves - Purify", () => { playerPokemon.hp = playerPokemon.getMaxHp() - 1; const playerInitialHp = playerPokemon.hp; - game.move.select(Moves.PURIFY); + game.doAttack(getMovePosition(game.scene, 0, Moves.PURIFY)); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.phaseInterceptor.to(MoveEndPhase); diff --git a/src/test/moves/quick_guard.test.ts b/src/test/moves/quick_guard.test.ts index 26d9a74e9fd..8bf647f2027 100644 --- a/src/test/moves/quick_guard.test.ts +++ b/src/test/moves/quick_guard.test.ts @@ -1,12 +1,13 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { CommandPhase } from "#app/phases/command-phase"; -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, test } from "vitest"; import GameManager from "../utils/gameManager"; +import { Species } from "#enums/species"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "../utils/gameManagerUtils"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { CommandPhase } from "#app/phases/command-phase.js"; const TIMEOUT = 20 * 1000; @@ -46,11 +47,11 @@ describe("Moves - Quick Guard", () => { const leadPokemon = game.scene.getPlayerField(); - game.move.select(Moves.QUICK_GUARD); + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_GUARD)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(BerryPhase, false); @@ -68,11 +69,11 @@ describe("Moves - Quick Guard", () => { const leadPokemon = game.scene.getPlayerField(); - game.move.select(Moves.QUICK_GUARD); + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_GUARD)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(BerryPhase, false); @@ -90,11 +91,11 @@ describe("Moves - Quick Guard", () => { const leadPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); - game.move.select(Moves.QUICK_GUARD); + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_GUARD)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.FOLLOW_ME, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.FOLLOW_ME)); await game.phaseInterceptor.to(BerryPhase, false); diff --git a/src/test/moves/rage_powder.test.ts b/src/test/moves/rage_powder.test.ts index 3e78c6fe0c9..17b687feead 100644 --- a/src/test/moves/rage_powder.test.ts +++ b/src/test/moves/rage_powder.test.ts @@ -1,11 +1,14 @@ -import { BattlerIndex } from "#app/battle"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { BattlerIndex } from "#app/battle.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { SelectTargetPhase } from "#app/phases/select-target-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -30,23 +33,35 @@ describe("Moves - Rage Powder", () => { game.override.enemySpecies(Species.SNORLAX); game.override.startingLevel(100); game.override.enemyLevel(100); - game.override.moveset([Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.moveset([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); test( "move effect should be bypassed by Grass type", async () => { - game.override.enemyMoveset([Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER]); + game.override.enemyMoveset([ Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER ]); - await game.startBattle([Species.AMOONGUSS, Species.VENUSAUR]); + await game.startBattle([ Species.AMOONGUSS, Species.VENUSAUR ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); const enemyStartingHp = enemyPokemon.map(p => p.hp); - game.move.select(Moves.QUICK_ATTACK, 0, BattlerIndex.ENEMY); - game.move.select(Moves.QUICK_ATTACK, 1, BattlerIndex.ENEMY_2); + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY_2); await game.phaseInterceptor.to(TurnEndPhase, false); // If redirection was bypassed, both enemies should be damaged @@ -59,17 +74,29 @@ describe("Moves - Rage Powder", () => { "move effect should be bypassed by Overcoat", async () => { game.override.ability(Abilities.OVERCOAT); - game.override.enemyMoveset([Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER]); + game.override.enemyMoveset([ Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER ]); // Test with two non-Grass type player Pokemon - await game.startBattle([Species.BLASTOISE, Species.CHARIZARD]); + await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); const enemyStartingHp = enemyPokemon.map(p => p.hp); - game.move.select(Moves.QUICK_ATTACK, 0, BattlerIndex.ENEMY); - game.move.select(Moves.QUICK_ATTACK, 1, BattlerIndex.ENEMY_2); + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY_2); await game.phaseInterceptor.to(TurnEndPhase, false); // If redirection was bypassed, both enemies should be damaged diff --git a/src/test/moves/reflect.test.ts b/src/test/moves/reflect.test.ts index 9780ede3c55..79dd4f8202b 100644 --- a/src/test/moves/reflect.test.ts +++ b/src/test/moves/reflect.test.ts @@ -1,13 +1,14 @@ -import { ArenaTagSide } from "#app/data/arena-tag"; -import Move, { allMoves } from "#app/data/move"; -import { Abilities } from "#app/enums/abilities"; -import { ArenaTagType } from "#app/enums/arena-tag-type"; -import Pokemon from "#app/field/pokemon"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { NumberHolder } from "#app/utils"; +import { ArenaTagSide } from "#app/data/arena-tag.js"; +import Move, { allMoves } from "#app/data/move.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { ArenaTagType } from "#app/enums/arena-tag-type.js"; +import Pokemon from "#app/field/pokemon.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { NumberHolder } from "#app/utils.js"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -16,7 +17,7 @@ describe("Moves - Reflect", () => { let phaserGame: Phaser.Game; let game: GameManager; const singleBattleMultiplier = 0.5; - const doubleBattleMultiplier = 2732 / 4096; + const doubleBattleMultiplier = 2732/4096; beforeAll(() => { phaserGame = new Phaser.Game({ @@ -39,11 +40,11 @@ describe("Moves - Reflect", () => { game.override.disableCrits(); }); - it("reduces damage of physical attacks by half in a single battle", async () => { + it("reduces damage of physical attacks by half in a single battle", async() => { const moveToUse = Moves.TACKLE; await game.startBattle([Species.SHUCKLE]); - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); const mockedDmg = getMockedMoveDamage(game.scene.getEnemyPokemon()!, game.scene.getPlayerPokemon()!, allMoves[moveToUse]); @@ -51,14 +52,14 @@ describe("Moves - Reflect", () => { expect(mockedDmg).toBe(allMoves[moveToUse].power * singleBattleMultiplier); }); - it("reduces damage of physical attacks by a third in a double battle", async () => { + it("reduces damage of physical attacks by a third in a double battle", async() => { game.override.battleType("double"); const moveToUse = Moves.ROCK_SLIDE; await game.startBattle([Species.SHUCKLE, Species.SHUCKLE]); - game.move.select(moveToUse); - game.move.select(moveToUse, 1); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); + game.doAttack(getMovePosition(game.scene, 1, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); const mockedDmg = getMockedMoveDamage(game.scene.getEnemyPokemon()!, game.scene.getPlayerPokemon()!, allMoves[moveToUse]); @@ -66,11 +67,11 @@ describe("Moves - Reflect", () => { expect(mockedDmg).toBe(allMoves[moveToUse].power * doubleBattleMultiplier); }); - it("does not affect special attacks", async () => { + it("does not affect special attacks", async() => { const moveToUse = Moves.ABSORB; await game.startBattle([Species.SHUCKLE]); - game.move.select(moveToUse); + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); await game.phaseInterceptor.to(TurnEndPhase); diff --git a/src/test/moves/rollout.test.ts b/src/test/moves/rollout.test.ts index ddb0b22e642..1fc208c6724 100644 --- a/src/test/moves/rollout.test.ts +++ b/src/test/moves/rollout.test.ts @@ -1,16 +1,18 @@ -import { allMoves } from "#app/data/move"; -import { CommandPhase } from "#app/phases/command-phase"; +import { allMoves } from "#app/data/move.js"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; describe("Moves - Rollout", () => { let phaserGame: Phaser.Game; let game: GameManager; + const TIMEOUT = 20 * 1000; beforeAll(() => { phaserGame = new Phaser.Game({ @@ -27,9 +29,9 @@ describe("Moves - Rollout", () => { game.override.disableCrits(); game.override.battleType("single"); game.override.starterSpecies(Species.RATTATA); - game.override.ability(Abilities.BALL_FETCH); + game.override.ability(Abilities.NONE); game.override.enemySpecies(Species.BIDOOF); - game.override.enemyAbility(Abilities.BALL_FETCH); + game.override.enemyAbility(Abilities.NONE); game.override.startingLevel(100); game.override.enemyLevel(100); game.override.enemyMoveset(SPLASH_ONLY); @@ -56,7 +58,7 @@ describe("Moves - Rollout", () => { let previousHp = enemyPkm.hp; for (let i = 0; i < turns; i++) { - game.move.select(Moves.ROLLOUT); + game.doAttack(getMovePosition(game.scene, 0, Moves.ROLLOUT)); await game.phaseInterceptor.to(CommandPhase); dmgHistory.push(previousHp - enemyPkm.hp); @@ -76,5 +78,5 @@ describe("Moves - Rollout", () => { // reset expect(turn6Dmg).toBeGreaterThanOrEqual(turn1Dmg - variance); expect(turn6Dmg).toBeLessThanOrEqual(turn1Dmg + variance); - }); + }, TIMEOUT); }); diff --git a/src/test/moves/roost.test.ts b/src/test/moves/roost.test.ts index cf07a3485e7..c40bb18cdb1 100644 --- a/src/test/moves/roost.test.ts +++ b/src/test/moves/roost.test.ts @@ -1,12 +1,13 @@ -import { Abilities } from "#app/enums/abilities"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { Moves } from "#app/enums/moves"; -import { Species } from "#app/enums/species"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { Abilities } from "#app/enums/abilities.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { Moves } from "#app/enums/moves.js"; +import { Species } from "#app/enums/species.js"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -31,8 +32,8 @@ describe("Moves - Roost", () => { game.override.enemyAbility(Abilities.INSOMNIA); game.override.startingLevel(100); game.override.enemyLevel(100); - game.override.moveset([Moves.STOMPING_TANTRUM]); - game.override.enemyMoveset([Moves.ROOST, Moves.ROOST, Moves.ROOST, Moves.ROOST]); + game.override.moveset([ Moves.STOMPING_TANTRUM ]); + game.override.enemyMoveset([Moves.ROOST,Moves.ROOST,Moves.ROOST,Moves.ROOST]); }); test( @@ -44,7 +45,7 @@ describe("Moves - Roost", () => { const enemyStartingHp = enemyPokemon.hp; - game.move.select(Moves.STOMPING_TANTRUM); + game.doAttack(getMovePosition(game.scene, 0, Moves.STOMPING_TANTRUM)); await game.phaseInterceptor.to(MoveEffectPhase); diff --git a/src/test/moves/shell_trap.test.ts b/src/test/moves/shell_trap.test.ts index 4549a8b2b73..c600b1ee1cc 100644 --- a/src/test/moves/shell_trap.test.ts +++ b/src/test/moves/shell_trap.test.ts @@ -1,15 +1,16 @@ -import { BattlerIndex } from "#app/battle"; -import { allMoves } from "#app/data/move"; -import { Moves } from "#app/enums/moves"; -import { Species } from "#app/enums/species"; -import { MoveResult } from "#app/field/pokemon"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { MovePhase } from "#app/phases/move-phase"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import GameManager from "#test/utils/gameManager"; +import { Moves } from "#app/enums/moves.js"; +import { Species } from "#app/enums/species.js"; +import { allMoves } from "#app/data/move.js"; +import { BattlerIndex } from "#app/battle.js"; +import { getMovePosition } from "../utils/gameManagerUtils"; import { SPLASH_ONLY } from "../utils/testUtils"; +import { MoveResult } from "#app/field/pokemon.js"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { MovePhase } from "#app/phases/move-phase.js"; const TIMEOUT = 20 * 1000; @@ -48,8 +49,8 @@ describe("Moves - Shell Trap", () => { const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); - game.move.select(Moves.SPLASH); - game.move.select(Moves.SHELL_TRAP, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SHELL_TRAP)); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2]); @@ -74,8 +75,8 @@ describe("Moves - Shell Trap", () => { const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); - game.move.select(Moves.SPLASH); - game.move.select(Moves.SHELL_TRAP, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SHELL_TRAP)); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2]); @@ -100,8 +101,8 @@ describe("Moves - Shell Trap", () => { const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); - game.move.select(Moves.SPLASH); - game.move.select(Moves.SHELL_TRAP, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SHELL_TRAP)); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2]); @@ -126,8 +127,8 @@ describe("Moves - Shell Trap", () => { const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); - game.move.select(Moves.SHELL_TRAP); - game.move.select(Moves.BULLDOZE, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.SHELL_TRAP)); + game.doAttack(getMovePosition(game.scene, 1, Moves.BULLDOZE)); await game.phaseInterceptor.to(MoveEndPhase); @@ -153,7 +154,7 @@ describe("Moves - Shell Trap", () => { const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.SHELL_TRAP); + game.doAttack(getMovePosition(game.scene, 0, Moves.SHELL_TRAP)); await game.phaseInterceptor.to(BerryPhase, false); diff --git a/src/test/moves/spikes.test.ts b/src/test/moves/spikes.test.ts index c4096111c6f..ae3c676b893 100644 --- a/src/test/moves/spikes.test.ts +++ b/src/test/moves/spikes.test.ts @@ -1,8 +1,8 @@ -import { CommandPhase } from "#app/phases/command-phase"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import GameManager from "#test/utils/gameManager"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -31,11 +31,14 @@ describe("Moves - Spikes", () => { game.override.ability(Abilities.HYDRATION); game.override.passiveAbility(Abilities.HYDRATION); game.override.startingWave(3); - game.override.enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); - game.override.moveset([Moves.SPIKES, Moves.SPLASH, Moves.ROAR]); + game.override.enemyMoveset([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]); + game.override.moveset([Moves.SPIKES,Moves.SPLASH, Moves.ROAR]); }); - it("single - wild - stay on field - no damage", async () => { + it("single - wild - stay on field - no damage", async() => { + // player set spikes on the field and do splash for 3 turns + // opponent do splash for 4 turns + // nobody should take damage await game.classicMode.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA, @@ -43,14 +46,21 @@ describe("Moves - Spikes", () => { await game.phaseInterceptor.to(CommandPhase, true); const initialHp = game.scene.getParty()[0].hp; expect(game.scene.getParty()[0].hp).toBe(initialHp); - game.move.select(Moves.SPIKES); + game.doAttack(0); await game.toNextTurn(); - game.move.select(Moves.SPLASH); + game.doAttack(1); + await game.toNextTurn(); + game.doAttack(1); + await game.toNextTurn(); + game.doAttack(1); + await game.toNextTurn(); + game.doAttack(1); await game.toNextTurn(); expect(game.scene.getParty()[0].hp).toBe(initialHp); + console.log(game.textInterceptor.logs); }, 20000); - it("single - wild - take some damage", async () => { + it("single - wild - take some damage", async() => { // player set spikes on the field and switch back to back // opponent do splash for 2 turns // nobody should take damage @@ -72,7 +82,7 @@ describe("Moves - Spikes", () => { expect(game.scene.getParty()[0].hp).toBe(initialHp); }, 20000); - it("trainer - wild - force switch opponent - should take damage", async () => { + it("trainer - wild - force switch opponent - should take damage", async() => { game.override.startingWave(5); // player set spikes on the field and do splash for 3 turns // opponent do splash for 4 turns @@ -83,14 +93,14 @@ describe("Moves - Spikes", () => { ]); await game.phaseInterceptor.to(CommandPhase, true); const initialHpOpponent = game.scene.currentBattle.enemyParty[1].hp; - game.move.select(Moves.SPIKES); + game.doAttack(0); await game.toNextTurn(); - game.move.select(Moves.ROAR); + game.doAttack(2); await game.toNextTurn(); expect(game.scene.currentBattle.enemyParty[0].hp).toBeLessThan(initialHpOpponent); }, 20000); - it("trainer - wild - force switch by himself opponent - should take damage", async () => { + it("trainer - wild - force switch by himself opponent - should take damage", async() => { game.override.startingWave(5); game.override.startingLevel(5000); game.override.enemySpecies(0); @@ -103,11 +113,11 @@ describe("Moves - Spikes", () => { ]); await game.phaseInterceptor.to(CommandPhase, true); const initialHpOpponent = game.scene.currentBattle.enemyParty[1].hp; - game.move.select(Moves.SPIKES); + game.doAttack(0); await game.toNextTurn(); game.forceOpponentToSwitch(); - game.move.select(Moves.SPLASH); + game.doAttack(1); await game.toNextTurn(); expect(game.scene.currentBattle.enemyParty[0].hp).toBeLessThan(initialHpOpponent); }, 20000); diff --git a/src/test/moves/spit_up.test.ts b/src/test/moves/spit_up.test.ts index ab47e65d653..51d84a5e151 100644 --- a/src/test/moves/spit_up.test.ts +++ b/src/test/moves/spit_up.test.ts @@ -1,17 +1,17 @@ import { BattleStat } from "#app/data/battle-stat"; -import { StockpilingTag } from "#app/data/battler-tags"; -import { allMoves } from "#app/data/move"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { MoveResult, TurnMove } from "#app/field/pokemon"; -import { MovePhase } from "#app/phases/move-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import { StockpilingTag } from "#app/data/battler-tags.js"; +import { allMoves } from "#app/data/move.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { MoveResult, TurnMove } from "#app/field/pokemon.js"; +import GameManager from "#test/utils/gameManager"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { MovePhase } from "#app/phases/move-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; describe("Moves - Spit Up", () => { let phaserGame: Phaser.Game; @@ -55,7 +55,7 @@ describe("Moves - Spit Up", () => { vi.spyOn(allMoves[Moves.SPIT_UP], "calculateBattlePower"); - game.move.select(Moves.SPIT_UP); + game.doAttack(0); await game.phaseInterceptor.to(TurnInitPhase); expect(allMoves[Moves.SPIT_UP].calculateBattlePower).toHaveBeenCalledOnce(); @@ -80,7 +80,7 @@ describe("Moves - Spit Up", () => { vi.spyOn(allMoves[Moves.SPIT_UP], "calculateBattlePower"); - game.move.select(Moves.SPIT_UP); + game.doAttack(0); await game.phaseInterceptor.to(TurnInitPhase); expect(allMoves[Moves.SPIT_UP].calculateBattlePower).toHaveBeenCalledOnce(); @@ -106,7 +106,7 @@ describe("Moves - Spit Up", () => { vi.spyOn(allMoves[Moves.SPIT_UP], "calculateBattlePower"); - game.move.select(Moves.SPIT_UP); + game.doAttack(0); await game.phaseInterceptor.to(TurnInitPhase); expect(allMoves[Moves.SPIT_UP].calculateBattlePower).toHaveBeenCalledOnce(); @@ -126,7 +126,7 @@ describe("Moves - Spit Up", () => { vi.spyOn(allMoves[Moves.SPIT_UP], "calculateBattlePower"); - game.move.select(Moves.SPIT_UP); + game.doAttack(0); await game.phaseInterceptor.to(TurnInitPhase); expect(pokemon.getMoveHistory().at(-1)).toMatchObject({ move: Moves.SPIT_UP, result: MoveResult.FAIL }); @@ -146,7 +146,7 @@ describe("Moves - Spit Up", () => { vi.spyOn(allMoves[Moves.SPIT_UP], "calculateBattlePower"); - game.move.select(Moves.SPIT_UP); + game.doAttack(0); await game.phaseInterceptor.to(MovePhase); expect(pokemon.summonData.battleStats[BattleStat.DEF]).toBe(1); @@ -186,7 +186,7 @@ describe("Moves - Spit Up", () => { vi.spyOn(allMoves[Moves.SPIT_UP], "calculateBattlePower"); - game.move.select(Moves.SPIT_UP); + game.doAttack(0); await game.phaseInterceptor.to(TurnInitPhase); expect(pokemon.getMoveHistory().at(-1)).toMatchObject({ move: Moves.SPIT_UP, result: MoveResult.SUCCESS }); diff --git a/src/test/moves/spotlight.test.ts b/src/test/moves/spotlight.test.ts index e5f4719d1d3..40ab78471ae 100644 --- a/src/test/moves/spotlight.test.ts +++ b/src/test/moves/spotlight.test.ts @@ -1,11 +1,14 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#app/battle.js"; import { Stat } from "#app/data/pokemon-stat"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { SelectTargetPhase } from "#app/phases/select-target-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; const TIMEOUT = 20 * 1000; @@ -30,21 +33,33 @@ describe("Moves - Spotlight", () => { game.override.enemySpecies(Species.SNORLAX); game.override.startingLevel(100); game.override.enemyLevel(100); - game.override.moveset([Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.moveset([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); test( "move should redirect attacks to the target", async () => { - await game.startBattle([Species.AMOONGUSS, Species.CHARIZARD]); + await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); const enemyStartingHp = enemyPokemon.map(p => p.hp); - game.move.select(Moves.SPOTLIGHT, 0, BattlerIndex.ENEMY); - game.move.select(Moves.QUICK_ATTACK, 1, BattlerIndex.ENEMY_2); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPOTLIGHT)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY_2); await game.phaseInterceptor.to(TurnEndPhase, false); expect(enemyPokemon[0].hp).toBeLessThan(enemyStartingHp[0]); @@ -55,11 +70,17 @@ describe("Moves - Spotlight", () => { test( "move should cause other redirection moves to fail", async () => { - game.override.enemyMoveset([Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME]); + game.override.enemyMoveset([ Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME ]); - await game.startBattle([Species.AMOONGUSS, Species.CHARIZARD]); + await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); /** * Spotlight will target the slower enemy. In this situation without Spotlight being used, @@ -71,8 +92,14 @@ describe("Moves - Spotlight", () => { const enemyStartingHp = enemyPokemon.map(p => p.hp); - game.move.select(Moves.SPOTLIGHT, 0, spotTarget); - game.move.select(Moves.QUICK_ATTACK, 1, attackTarget); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPOTLIGHT)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(spotTarget); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(attackTarget); await game.phaseInterceptor.to(TurnEndPhase, false); expect(enemyPokemon[1].hp).toBeLessThan(enemyStartingHp[1]); diff --git a/src/test/moves/stockpile.test.ts b/src/test/moves/stockpile.test.ts index b1941b9f9b3..0b208e20f81 100644 --- a/src/test/moves/stockpile.test.ts +++ b/src/test/moves/stockpile.test.ts @@ -1,15 +1,16 @@ import { BattleStat } from "#app/data/battle-stat"; -import { StockpilingTag } from "#app/data/battler-tags"; -import { MoveResult, TurnMove } from "#app/field/pokemon"; -import { CommandPhase } from "#app/phases/command-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import { StockpilingTag } from "#app/data/battler-tags.js"; +import { MoveResult, TurnMove } from "#app/field/pokemon.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; describe("Moves - Stockpile", () => { describe("integration tests", () => { @@ -56,7 +57,7 @@ describe("Moves - Stockpile", () => { await game.phaseInterceptor.to(CommandPhase); } - game.move.select(Moves.STOCKPILE); + game.doAttack(getMovePosition(game.scene, 0, Moves.STOCKPILE)); await game.phaseInterceptor.to(TurnInitPhase); const stockpilingTag = user.getTag(StockpilingTag)!; @@ -91,7 +92,7 @@ describe("Moves - Stockpile", () => { expect(user.summonData.battleStats[BattleStat.DEF]).toBe(6); expect(user.summonData.battleStats[BattleStat.SPDEF]).toBe(6); - game.move.select(Moves.STOCKPILE); + game.doAttack(getMovePosition(game.scene, 0, Moves.STOCKPILE)); await game.phaseInterceptor.to(TurnInitPhase); const stockpilingTag = user.getTag(StockpilingTag)!; @@ -103,7 +104,7 @@ describe("Moves - Stockpile", () => { // do it again, just for good measure await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.STOCKPILE); + game.doAttack(getMovePosition(game.scene, 0, Moves.STOCKPILE)); await game.phaseInterceptor.to(TurnInitPhase); const stockpilingTagAgain = user.getTag(StockpilingTag)!; diff --git a/src/test/moves/swallow.test.ts b/src/test/moves/swallow.test.ts index 202f25fee74..6a054393acc 100644 --- a/src/test/moves/swallow.test.ts +++ b/src/test/moves/swallow.test.ts @@ -1,16 +1,16 @@ import { BattleStat } from "#app/data/battle-stat"; -import { StockpilingTag } from "#app/data/battler-tags"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { MoveResult, TurnMove } from "#app/field/pokemon"; -import { MovePhase } from "#app/phases/move-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import { StockpilingTag } from "#app/data/battler-tags.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { MoveResult, TurnMove } from "#app/field/pokemon.js"; +import GameManager from "#test/utils/gameManager"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { MovePhase } from "#app/phases/move-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; describe("Moves - Swallow", () => { let phaserGame: Phaser.Game; @@ -57,7 +57,7 @@ describe("Moves - Swallow", () => { vi.spyOn(pokemon, "heal"); - game.move.select(Moves.SWALLOW); + game.doAttack(0); await game.phaseInterceptor.to(TurnInitPhase); expect(pokemon.heal).toHaveBeenCalledOnce(); @@ -85,7 +85,7 @@ describe("Moves - Swallow", () => { vi.spyOn(pokemon, "heal"); - game.move.select(Moves.SWALLOW); + game.doAttack(0); await game.phaseInterceptor.to(TurnInitPhase); expect(pokemon.heal).toHaveBeenCalledOnce(); @@ -114,7 +114,7 @@ describe("Moves - Swallow", () => { vi.spyOn(pokemon, "heal"); - game.move.select(Moves.SWALLOW); + game.doAttack(0); await game.phaseInterceptor.to(TurnInitPhase); expect(pokemon.heal).toHaveBeenCalledOnce(); @@ -132,7 +132,7 @@ describe("Moves - Swallow", () => { const stockpilingTag = pokemon.getTag(StockpilingTag)!; expect(stockpilingTag).toBeUndefined(); - game.move.select(Moves.SWALLOW); + game.doAttack(0); await game.phaseInterceptor.to(TurnInitPhase); expect(pokemon.getMoveHistory().at(-1)).toMatchObject({ move: Moves.SWALLOW, result: MoveResult.FAIL }); @@ -148,7 +148,7 @@ describe("Moves - Swallow", () => { const stockpilingTag = pokemon.getTag(StockpilingTag)!; expect(stockpilingTag).toBeDefined(); - game.move.select(Moves.SWALLOW); + game.doAttack(0); await game.phaseInterceptor.to(MovePhase); expect(pokemon.summonData.battleStats[BattleStat.DEF]).toBe(1); @@ -184,7 +184,7 @@ describe("Moves - Swallow", () => { [BattleStat.SPDEF]: 2, }); - game.move.select(Moves.SWALLOW); + game.doAttack(0); await game.phaseInterceptor.to(TurnInitPhase); expect(pokemon.getMoveHistory().at(-1)).toMatchObject({ move: Moves.SWALLOW, result: MoveResult.SUCCESS }); diff --git a/src/test/moves/tackle.test.ts b/src/test/moves/tackle.test.ts index 5eca9e344c8..f442645baa9 100644 --- a/src/test/moves/tackle.test.ts +++ b/src/test/moves/tackle.test.ts @@ -1,11 +1,15 @@ import { Stat } from "#app/data/pokemon-stat"; -import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Command } from "#app/ui/command-ui-handler"; +import { Mode } from "#app/ui/ui"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { EnemyCommandPhase } from "#app/phases/enemy-command-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Moves - Tackle", () => { @@ -30,24 +34,30 @@ describe("Moves - Tackle", () => { game.override.startingLevel(1); game.override.startingWave(97); game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.GROWTH, Moves.GROWTH, Moves.GROWTH, Moves.GROWTH]); + game.override.enemyMoveset([Moves.GROWTH,Moves.GROWTH,Moves.GROWTH,Moves.GROWTH]); game.override.disableCrits(); }); - it("TACKLE against ghost", async () => { + it("TACKLE against ghost", async() => { const moveToUse = Moves.TACKLE; game.override.enemySpecies(Species.GENGAR); await game.startBattle([ Species.MIGHTYENA, ]); const hpOpponent = game.scene.currentBattle.enemyParty[0].hp; - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnEndPhase); const hpLost = hpOpponent - game.scene.currentBattle.enemyParty[0].hp; expect(hpLost).toBe(0); }, 20000); - it("TACKLE against not resistant", async () => { + it("TACKLE against not resistant", async() => { const moveToUse = Moves.TACKLE; await game.startBattle([ Species.MIGHTYENA, @@ -58,10 +68,16 @@ describe("Moves - Tackle", () => { const hpOpponent = game.scene.currentBattle.enemyParty[0].hp; - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnEndPhase); const hpLost = hpOpponent - game.scene.currentBattle.enemyParty[0].hp; expect(hpLost).toBeGreaterThan(0); - expect(hpLost).toBeLessThan(4); + expect(hpLost).toBe(4); }, 20000); }); diff --git a/src/test/moves/tail_whip.test.ts b/src/test/moves/tail_whip.test.ts index 0a999fe1920..ba4a7459094 100644 --- a/src/test/moves/tail_whip.test.ts +++ b/src/test/moves/tail_whip.test.ts @@ -1,12 +1,16 @@ import { BattleStat } from "#app/data/battle-stat"; -import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { Command } from "#app/ui/command-ui-handler"; +import { Mode } from "#app/ui/ui"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { EnemyCommandPhase } from "#app/phases/enemy-command-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; describe("Moves - Tail whip", () => { @@ -32,10 +36,10 @@ describe("Moves - Tail whip", () => { game.override.ability(Abilities.INSOMNIA); game.override.startingLevel(2000); game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); - it("TAIL_WHIP", async () => { + it("TAIL_WHIP", async() => { const moveToUse = Moves.TAIL_WHIP; await game.startBattle([ Species.MIGHTYENA, @@ -45,7 +49,13 @@ describe("Moves - Tail whip", () => { let battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats; expect(battleStatsOpponent[BattleStat.DEF]).toBe(0); - game.move.select(moveToUse); + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase); battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats; expect(battleStatsOpponent[BattleStat.DEF]).toBe(-1); diff --git a/src/test/moves/tailwind.test.ts b/src/test/moves/tailwind.test.ts index 6b70122d08d..115a97f3be4 100644 --- a/src/test/moves/tailwind.test.ts +++ b/src/test/moves/tailwind.test.ts @@ -1,13 +1,14 @@ -import { ArenaTagSide } from "#app/data/arena-tag"; -import { Stat } from "#app/data/pokemon-stat"; -import { ArenaTagType } from "#app/enums/arena-tag-type"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { ArenaTagSide } from "#app/data/arena-tag.js"; +import { Stat } from "#app/data/pokemon-stat.js"; +import { ArenaTagType } from "#app/enums/arena-tag-type.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; describe("Moves - Tailwind", () => { let phaserGame: Phaser.Game; @@ -41,8 +42,8 @@ describe("Moves - Tailwind", () => { expect(magikarp.getBattleStat(Stat.SPD)).equal(magikarpSpd); expect(meowth.getBattleStat(Stat.SPD)).equal(meowthSpd); - game.move.select(Moves.TAILWIND); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 0, Moves.TAILWIND)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(TurnEndPhase); @@ -56,19 +57,19 @@ describe("Moves - Tailwind", () => { await game.startBattle([Species.MAGIKARP]); - game.move.select(Moves.TAILWIND); + game.doAttack(getMovePosition(game.scene, 0, Moves.TAILWIND)); await game.toNextTurn(); expect(game.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.PLAYER)).toBeDefined(); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.toNextTurn(); expect(game.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.PLAYER)).toBeDefined(); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.toNextTurn(); expect(game.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.PLAYER)).toBeDefined(); - game.move.select(Moves.SPLASH); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); await game.toNextTurn(); expect(game.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.PLAYER)).toBeUndefined(); @@ -91,7 +92,7 @@ describe("Moves - Tailwind", () => { expect(game.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.PLAYER)).toBeUndefined(); expect(game.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.ENEMY)).toBeUndefined(); - game.move.select(Moves.TAILWIND); + game.doAttack(getMovePosition(game.scene, 0, Moves.TAILWIND)); await game.phaseInterceptor.to(TurnEndPhase); diff --git a/src/test/moves/tera_blast.test.ts b/src/test/moves/tera_blast.test.ts deleted file mode 100644 index d261d4b856b..00000000000 --- a/src/test/moves/tera_blast.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { BattlerIndex } from "#app/battle"; -import { BattleStat } from "#app/data/battle-stat"; -import { allMoves } from "#app/data/move"; -import { Type } from "#app/data/type"; -import { Abilities } from "#app/enums/abilities"; -import { Stat } from "#app/enums/stat"; -import { HitResult } from "#app/field/pokemon"; -import { Moves } from "#enums/moves"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { SPLASH_ONLY } from "../utils/testUtils"; - -describe("Moves - Tera Blast", () => { - let phaserGame: Phaser.Game; - let game: GameManager; - const moveToCheck = allMoves[Moves.TERA_BLAST]; - - beforeAll(() => { - phaserGame = new Phaser.Game({ - type: Phaser.HEADLESS, - }); - }); - - afterEach(() => { - game.phaseInterceptor.restoreOg(); - }); - - beforeEach(() => { - game = new GameManager(phaserGame); - - game.override - .battleType("single") - .disableCrits() - .starterSpecies(Species.FEEBAS) - .moveset([Moves.TERA_BLAST]) - .ability(Abilities.BALL_FETCH) - .startingHeldItems([{ name: "TERA_SHARD", type: Type.FIRE }]) - .enemySpecies(Species.MAGIKARP) - .enemyMoveset(SPLASH_ONLY) - .enemyAbility(Abilities.BALL_FETCH) - .enemyLevel(20); - - vi.spyOn(moveToCheck, "calculateBattlePower"); - }); - - it("changes type to match user's tera type", async () => { - game.override - .enemySpecies(Species.FURRET) - .startingHeldItems([{ name: "TERA_SHARD", type: Type.FIGHTING }]); - await game.startBattle(); - const enemyPokemon = game.scene.getEnemyPokemon()!; - vi.spyOn(enemyPokemon, "apply"); - - game.move.select(Moves.TERA_BLAST); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); - await game.phaseInterceptor.to("MoveEffectPhase"); - - expect(enemyPokemon.apply).toHaveReturnedWith(HitResult.SUPER_EFFECTIVE); - }, 20000); - - it("increases power if user is Stellar tera type", async () => { - game.override.startingHeldItems([{ name: "TERA_SHARD", type: Type.STELLAR }]); - const stellarTypeMultiplier = 2; - const stellarTypeDmgBonus = 20; - const basePower = moveToCheck.power; - - await game.startBattle(); - - game.move.select(Moves.TERA_BLAST); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); - await game.phaseInterceptor.to("MoveEffectPhase"); - - expect(moveToCheck.calculateBattlePower).toHaveReturnedWith((basePower + stellarTypeDmgBonus) * stellarTypeMultiplier); - }, 20000); - - // Currently abilities are bugged and can't see when a move's category is changed - it.skip("uses the higher stat of the user's Atk and SpAtk for damage calculation", async () => { - game.override.enemyAbility(Abilities.TOXIC_DEBRIS); - await game.startBattle(); - - const playerPokemon = game.scene.getPlayerPokemon()!; - playerPokemon.stats[Stat.ATK] = 100; - playerPokemon.stats[Stat.SPATK] = 1; - - game.move.select(Moves.TERA_BLAST); - await game.phaseInterceptor.to("TurnEndPhase"); - expect(game.scene.getEnemyPokemon()!.battleData.abilityRevealed).toBe(true); - }, 20000); - - it("causes stat drops if user is Stellar tera type", async () => { - game.override.startingHeldItems([{ name: "TERA_SHARD", type: Type.STELLAR }]); - await game.startBattle(); - - const playerPokemon = game.scene.getPlayerPokemon()!; - - game.move.select(Moves.TERA_BLAST); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); - await game.phaseInterceptor.to("MoveEndPhase"); - - expect(playerPokemon.summonData.battleStats[BattleStat.SPATK]).toBe(-1); - expect(playerPokemon.summonData.battleStats[BattleStat.ATK]).toBe(-1); - }, 20000); -}); diff --git a/src/test/moves/thousand_arrows.test.ts b/src/test/moves/thousand_arrows.test.ts index 8d1d6ee5f4a..d72f3ed3fac 100644 --- a/src/test/moves/thousand_arrows.test.ts +++ b/src/test/moves/thousand_arrows.test.ts @@ -1,12 +1,13 @@ -import { Abilities } from "#app/enums/abilities"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import { Abilities } from "#app/enums/abilities.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; const TIMEOUT = 20 * 1000; @@ -30,18 +31,18 @@ describe("Moves - Thousand Arrows", () => { game.override.enemySpecies(Species.TOGETIC); game.override.startingLevel(100); game.override.enemyLevel(100); - game.override.moveset([Moves.THOUSAND_ARROWS]); - game.override.enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + game.override.moveset([ Moves.THOUSAND_ARROWS ]); + game.override.enemyMoveset([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]); }); it( "move should hit and ground Flying-type targets", async () => { - await game.startBattle([Species.ILLUMISE]); + await game.startBattle([ Species.ILLUMISE ]); const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.THOUSAND_ARROWS); + game.doAttack(getMovePosition(game.scene, 0, Moves.THOUSAND_ARROWS)); await game.phaseInterceptor.to(MoveEffectPhase, false); // Enemy should not be grounded before move effect is applied @@ -60,11 +61,11 @@ describe("Moves - Thousand Arrows", () => { game.override.enemySpecies(Species.SNORLAX); game.override.enemyAbility(Abilities.LEVITATE); - await game.startBattle([Species.ILLUMISE]); + await game.startBattle([ Species.ILLUMISE ]); const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.select(Moves.THOUSAND_ARROWS); + game.doAttack(getMovePosition(game.scene, 0, Moves.THOUSAND_ARROWS)); await game.phaseInterceptor.to(MoveEffectPhase, false); // Enemy should not be grounded before move effect is applied @@ -82,13 +83,13 @@ describe("Moves - Thousand Arrows", () => { async () => { game.override.enemySpecies(Species.SNORLAX); - await game.startBattle([Species.ILLUMISE]); + await game.startBattle([ Species.ILLUMISE ]); const enemyPokemon = game.scene.getEnemyPokemon()!; enemyPokemon.addTag(BattlerTagType.MAGNET_RISEN, undefined, Moves.MAGNET_RISE); - game.move.select(Moves.THOUSAND_ARROWS); + game.doAttack(getMovePosition(game.scene, 0, Moves.THOUSAND_ARROWS)); await game.phaseInterceptor.to(BerryPhase, false); diff --git a/src/test/moves/tidy_up.test.ts b/src/test/moves/tidy_up.test.ts index 1ef7933c114..64a63df08df 100644 --- a/src/test/moves/tidy_up.test.ts +++ b/src/test/moves/tidy_up.test.ts @@ -1,14 +1,15 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { ArenaTagType } from "#app/enums/arena-tag-type"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { ArenaTagType } from "#app/enums/arena-tag-type.js"; +import GameManager from "#test/utils/gameManager"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Moves - Tidy Up", () => { @@ -37,81 +38,81 @@ describe("Moves - Tidy Up", () => { game.override.startingLevel(50); }); - it("spikes are cleared", async () => { + it("spikes are cleared", async() => { game.override.moveset([Moves.SPIKES, Moves.TIDY_UP]); game.override.enemyMoveset([Moves.SPIKES, Moves.SPIKES, Moves.SPIKES, Moves.SPIKES]); await game.startBattle(); - game.move.select(Moves.SPIKES); + game.doAttack(getMovePosition(game.scene, 0, Moves.SPIKES)); await game.phaseInterceptor.to(TurnEndPhase); - game.move.select(Moves.TIDY_UP); + game.doAttack(getMovePosition(game.scene, 0, Moves.TIDY_UP)); await game.phaseInterceptor.to(MoveEndPhase); expect(game.scene.arena.getTag(ArenaTagType.SPIKES)).toBeUndefined(); }, 20000); - it("stealth rocks are cleared", async () => { + it("stealth rocks are cleared", async() => { game.override.moveset([Moves.STEALTH_ROCK, Moves.TIDY_UP]); game.override.enemyMoveset([Moves.STEALTH_ROCK, Moves.STEALTH_ROCK, Moves.STEALTH_ROCK, Moves.STEALTH_ROCK]); await game.startBattle(); - game.move.select(Moves.STEALTH_ROCK); + game.doAttack(getMovePosition(game.scene, 0, Moves.STEALTH_ROCK)); await game.phaseInterceptor.to(TurnEndPhase); - game.move.select(Moves.TIDY_UP); + game.doAttack(getMovePosition(game.scene, 0, Moves.TIDY_UP)); await game.phaseInterceptor.to(MoveEndPhase); expect(game.scene.arena.getTag(ArenaTagType.STEALTH_ROCK)).toBeUndefined(); }, 20000); - it("toxic spikes are cleared", async () => { + it("toxic spikes are cleared", async() => { game.override.moveset([Moves.TOXIC_SPIKES, Moves.TIDY_UP]); game.override.enemyMoveset([Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES]); await game.startBattle(); - game.move.select(Moves.TOXIC_SPIKES); + game.doAttack(getMovePosition(game.scene, 0, Moves.TOXIC_SPIKES)); await game.phaseInterceptor.to(TurnEndPhase); - game.move.select(Moves.TIDY_UP); + game.doAttack(getMovePosition(game.scene, 0, Moves.TIDY_UP)); await game.phaseInterceptor.to(MoveEndPhase); expect(game.scene.arena.getTag(ArenaTagType.TOXIC_SPIKES)).toBeUndefined(); }, 20000); - it("sticky webs are cleared", async () => { + it("sticky webs are cleared", async() => { game.override.moveset([Moves.STICKY_WEB, Moves.TIDY_UP]); game.override.enemyMoveset([Moves.STICKY_WEB, Moves.STICKY_WEB, Moves.STICKY_WEB, Moves.STICKY_WEB]); await game.startBattle(); - game.move.select(Moves.STICKY_WEB); + game.doAttack(getMovePosition(game.scene, 0, Moves.STICKY_WEB)); await game.phaseInterceptor.to(TurnEndPhase); - game.move.select(Moves.TIDY_UP); + game.doAttack(getMovePosition(game.scene, 0, Moves.TIDY_UP)); await game.phaseInterceptor.to(MoveEndPhase); expect(game.scene.arena.getTag(ArenaTagType.STICKY_WEB)).toBeUndefined(); }, 20000); - it.skip("substitutes are cleared", async () => { + it.skip("substitutes are cleared", async() => { game.override.moveset([Moves.SUBSTITUTE, Moves.TIDY_UP]); game.override.enemyMoveset([Moves.SUBSTITUTE, Moves.SUBSTITUTE, Moves.SUBSTITUTE, Moves.SUBSTITUTE]); await game.startBattle(); - game.move.select(Moves.SUBSTITUTE); + game.doAttack(getMovePosition(game.scene, 0, Moves.SUBSTITUTE)); await game.phaseInterceptor.to(TurnEndPhase); - game.move.select(Moves.TIDY_UP); + game.doAttack(getMovePosition(game.scene, 0, Moves.TIDY_UP)); await game.phaseInterceptor.to(MoveEndPhase); // TODO: check for subs here once the move is implemented }, 20000); - it("user's stats are raised with no traps set", async () => { + it("user's stats are raised with no traps set", async() => { await game.startBattle(); const player = game.scene.getPlayerPokemon()!.summonData.battleStats; expect(player[BattleStat.ATK]).toBe(0); expect(player[BattleStat.SPD]).toBe(0); - game.move.select(Moves.TIDY_UP); + game.doAttack(getMovePosition(game.scene, 0, Moves.TIDY_UP)); await game.phaseInterceptor.to(TurnEndPhase); expect(player[BattleStat.ATK]).toBe(+1); diff --git a/src/test/moves/u_turn.test.ts b/src/test/moves/u_turn.test.ts index ae55302bb42..b93f997c487 100644 --- a/src/test/moves/u_turn.test.ts +++ b/src/test/moves/u_turn.test.ts @@ -1,13 +1,14 @@ -import { Abilities } from "#app/enums/abilities"; -import { StatusEffect } from "#app/enums/status-effect"; -import { SwitchPhase } from "#app/phases/switch-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { Abilities } from "#app/enums/abilities.js"; import GameManager from "#app/test/utils/gameManager"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; 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 { StatusEffect } from "#app/enums/status-effect.js"; import { SPLASH_ONLY } from "../utils/testUtils"; +import { SwitchPhase } from "#app/phases/switch-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; describe("Moves - U-turn", () => { let phaserGame: Phaser.Game; @@ -35,7 +36,7 @@ describe("Moves - U-turn", () => { .disableCrits(); }); - it("triggers regenerator a single time when a regenerator user switches out with u-turn", async () => { + it("triggers regenerator a single time when a regenerator user switches out with u-turn", async() => { // arrange const playerHp = 1; game.override.ability(Abilities.REGENERATOR); @@ -46,7 +47,7 @@ describe("Moves - U-turn", () => { game.scene.getPlayerPokemon()!.hp = playerHp; // act - game.move.select(Moves.U_TURN); + game.doAttack(getMovePosition(game.scene, 0, Moves.U_TURN)); game.doSelectPartyPokemon(1); await game.phaseInterceptor.to(TurnEndPhase); @@ -56,7 +57,7 @@ describe("Moves - U-turn", () => { expect(game.scene.getPlayerPokemon()!.species.speciesId).toBe(Species.SHUCKLE); }, 20000); - it("triggers rough skin on the u-turn user before a new pokemon is switched in", async () => { + it("triggers rough skin on the u-turn user before a new pokemon is switched in", async() => { // arrange game.override.enemyAbility(Abilities.ROUGH_SKIN); await game.startBattle([ @@ -65,7 +66,7 @@ describe("Moves - U-turn", () => { ]); // act - game.move.select(Moves.U_TURN); + game.doAttack(getMovePosition(game.scene, 0, Moves.U_TURN)); game.doSelectPartyPokemon(1); await game.phaseInterceptor.to(SwitchPhase, false); @@ -77,7 +78,7 @@ describe("Moves - U-turn", () => { expect(game.phaseInterceptor.log).not.toContain("SwitchSummonPhase"); }, 20000); - it("triggers contact abilities on the u-turn user (eg poison point) before a new pokemon is switched in", async () => { + it("triggers contact abilities on the u-turn user (eg poison point) before a new pokemon is switched in", async() => { // arrange game.override.enemyAbility(Abilities.POISON_POINT); await game.startBattle([ @@ -87,7 +88,7 @@ describe("Moves - U-turn", () => { vi.spyOn(game.scene.getEnemyPokemon()!, "randSeedInt").mockReturnValue(0); // act - game.move.select(Moves.U_TURN); + game.doAttack(getMovePosition(game.scene, 0, Moves.U_TURN)); await game.phaseInterceptor.to(SwitchPhase, false); // assert diff --git a/src/test/moves/wide_guard.test.ts b/src/test/moves/wide_guard.test.ts index 616972de01b..1f22428de4b 100644 --- a/src/test/moves/wide_guard.test.ts +++ b/src/test/moves/wide_guard.test.ts @@ -1,12 +1,13 @@ -import { BattleStat } from "#app/data/battle-stat"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { CommandPhase } from "#app/phases/command-phase"; -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, test } from "vitest"; import GameManager from "../utils/gameManager"; +import { Species } from "#enums/species"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "../utils/gameManagerUtils"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { CommandPhase } from "#app/phases/command-phase.js"; const TIMEOUT = 20 * 1000; @@ -46,11 +47,11 @@ describe("Moves - Wide Guard", () => { const leadPokemon = game.scene.getPlayerField(); - game.move.select(Moves.WIDE_GUARD); + game.doAttack(getMovePosition(game.scene, 0, Moves.WIDE_GUARD)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(BerryPhase, false); @@ -67,11 +68,11 @@ describe("Moves - Wide Guard", () => { const leadPokemon = game.scene.getPlayerField(); - game.move.select(Moves.WIDE_GUARD); + game.doAttack(getMovePosition(game.scene, 0, Moves.WIDE_GUARD)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(BerryPhase, false); @@ -88,11 +89,11 @@ describe("Moves - Wide Guard", () => { const leadPokemon = game.scene.getPlayerField(); - game.move.select(Moves.WIDE_GUARD); + game.doAttack(getMovePosition(game.scene, 0, Moves.WIDE_GUARD)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SPLASH, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); await game.phaseInterceptor.to(BerryPhase, false); @@ -110,11 +111,11 @@ describe("Moves - Wide Guard", () => { const leadPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); - game.move.select(Moves.WIDE_GUARD); + game.doAttack(getMovePosition(game.scene, 0, Moves.WIDE_GUARD)); await game.phaseInterceptor.to(CommandPhase); - game.move.select(Moves.SURF, 1); + game.doAttack(getMovePosition(game.scene, 1, Moves.SURF)); await game.phaseInterceptor.to(BerryPhase, false); diff --git a/src/test/phases/phases.test.ts b/src/test/phases/phases.test.ts index 5ef25361a3f..2ed1e48c706 100644 --- a/src/test/phases/phases.test.ts +++ b/src/test/phases/phases.test.ts @@ -1,11 +1,11 @@ -import BattleScene from "#app/battle-scene"; -import { LoginPhase } from "#app/phases/login-phase"; -import { TitlePhase } from "#app/phases/title-phase"; -import { UnavailablePhase } from "#app/phases/unavailable-phase"; -import { Mode } from "#app/ui/ui"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; +import BattleScene from "#app/battle-scene.js"; +import { Mode } from "#app/ui/ui.js"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { LoginPhase } from "#app/phases/login-phase.js"; +import { TitlePhase } from "#app/phases/title-phase.js"; +import { UnavailablePhase } from "#app/phases/unavailable-phase.js"; describe("Phases", () => { let phaserGame: Phaser.Game; diff --git a/src/test/settingMenu/helpers/inGameManip.ts b/src/test/settingMenu/helpers/inGameManip.ts index b81e577f5b9..e18a82ca571 100644 --- a/src/test/settingMenu/helpers/inGameManip.ts +++ b/src/test/settingMenu/helpers/inGameManip.ts @@ -1,6 +1,6 @@ import { getIconForLatestInput, getSettingNameWithKeycode } from "#app/configs/inputs/configHandler"; -import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; import { expect } from "vitest"; +import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; export class InGameManip { private config; diff --git a/src/test/settingMenu/helpers/menuManip.ts b/src/test/settingMenu/helpers/menuManip.ts index 90b3f1e96e6..4fd5f526897 100644 --- a/src/test/settingMenu/helpers/menuManip.ts +++ b/src/test/settingMenu/helpers/menuManip.ts @@ -1,6 +1,6 @@ -import { assign, canIAssignThisKey, canIDeleteThisKey, canIOverrideThisSetting, deleteBind, getIconWithKeycode, getIconWithSettingName, getKeyWithKeycode, getKeyWithSettingName, getSettingNameWithKeycode } from "#app/configs/inputs/configHandler"; -import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; import { expect } from "vitest"; +import { deleteBind, getIconWithKeycode, getIconWithSettingName, getKeyWithKeycode, getKeyWithSettingName, assign, getSettingNameWithKeycode, canIAssignThisKey, canIDeleteThisKey, canIOverrideThisSetting } from "#app/configs/inputs/configHandler"; +import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; export class MenuManip { private config; diff --git a/src/test/settingMenu/rebinding_setting.test.ts b/src/test/settingMenu/rebinding_setting.test.ts index ec2343cfb41..eead23972c2 100644 --- a/src/test/settingMenu/rebinding_setting.test.ts +++ b/src/test/settingMenu/rebinding_setting.test.ts @@ -1,13 +1,13 @@ -import cfg_keyboard_qwerty from "#app/configs/inputs/cfg_keyboard_qwerty"; -import { getKeyWithKeycode, getKeyWithSettingName } from "#app/configs/inputs/configHandler"; -import { InterfaceConfig } from "#app/inputs-controller"; -import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; -import { deepCopy } from "#app/utils"; -import { Button } from "#enums/buttons"; -import { Device } from "#enums/devices"; -import { InGameManip } from "#test/settingMenu/helpers/inGameManip"; -import { MenuManip } from "#test/settingMenu/helpers/menuManip"; import { beforeEach, describe, expect, it } from "vitest"; +import { deepCopy } from "#app/utils"; +import { getKeyWithKeycode, getKeyWithSettingName } from "#app/configs/inputs/configHandler"; +import { MenuManip } from "#test/settingMenu/helpers/menuManip"; +import { InGameManip } from "#test/settingMenu/helpers/inGameManip"; +import { InterfaceConfig } from "#app/inputs-controller"; +import cfg_keyboard_qwerty from "#app/configs/inputs/cfg_keyboard_qwerty"; +import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; +import { Device } from "#enums/devices"; +import { Button } from "#enums/buttons"; describe("Test Rebinding", () => { diff --git a/src/test/sprites/pokemonSprite.test.ts b/src/test/sprites/pokemonSprite.test.ts index faf0626b365..deb5844d677 100644 --- a/src/test/sprites/pokemonSprite.test.ts +++ b/src/test/sprites/pokemonSprite.test.ts @@ -1,8 +1,8 @@ -import { getAppRootDir } from "#test/sprites/spritesUtils"; -import fs from "fs"; -import path from "path"; import { beforeAll, describe, expect, it } from "vitest"; import _masterlist from "../../../public/images/pokemon/variant/_masterlist.json"; +import fs from "fs"; +import path from "path"; +import { getAppRootDir } from "#test/sprites/spritesUtils"; type PokemonVariantMasterlist = typeof _masterlist; diff --git a/src/test/ui/starter-select.test.ts b/src/test/ui/starter-select.test.ts index 8ef1ea16b4a..dbbdb1999b9 100644 --- a/src/test/ui/starter-select.test.ts +++ b/src/test/ui/starter-select.test.ts @@ -1,21 +1,21 @@ -import { Gender } from "#app/data/gender"; -import { Nature } from "#app/data/nature"; -import { allSpecies } from "#app/data/pokemon-species"; -import { GameModes } from "#app/game-mode"; -import { EncounterPhase } from "#app/phases/encounter-phase"; -import { SelectStarterPhase } from "#app/phases/select-starter-phase"; -import { TitlePhase } from "#app/phases/title-phase"; -import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; -import SaveSlotSelectUiHandler from "#app/ui/save-slot-select-ui-handler"; -import OptionSelectUiHandler from "#app/ui/settings/option-select-ui-handler"; -import StarterSelectUiHandler from "#app/ui/starter-select-ui-handler"; -import { Mode } from "#app/ui/ui"; -import { Abilities } from "#enums/abilities"; -import { Button } from "#enums/buttons"; -import { Species } from "#enums/species"; -import GameManager from "#test/utils/gameManager"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { Mode } from "#app/ui/ui"; +import { GameModes } from "#app/game-mode"; +import StarterSelectUiHandler from "#app/ui/starter-select-ui-handler"; +import OptionSelectUiHandler from "#app/ui/settings/option-select-ui-handler"; +import SaveSlotSelectUiHandler from "#app/ui/save-slot-select-ui-handler"; +import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; +import { Gender } from "#app/data/gender"; +import { allSpecies } from "#app/data/pokemon-species"; +import { Nature} from "#app/data/nature"; +import { Button } from "#enums/buttons"; +import { Abilities } from "#enums/abilities"; +import { Species } from "#enums/species"; +import { EncounterPhase } from "#app/phases/encounter-phase.js"; +import { SelectStarterPhase } from "#app/phases/select-starter-phase.js"; +import { TitlePhase } from "#app/phases/title-phase.js"; describe("UI - Starter select", () => { diff --git a/src/test/ui/transfer-item.test.ts b/src/test/ui/transfer-item.test.ts index f7dea463574..21aed9b5b87 100644 --- a/src/test/ui/transfer-item.test.ts +++ b/src/test/ui/transfer-item.test.ts @@ -2,15 +2,16 @@ import { BerryType } from "#app/enums/berry-type"; import { Button } from "#app/enums/buttons"; import { Moves } from "#app/enums/moves"; import { Species } from "#app/enums/species"; -import { BattleEndPhase } from "#app/phases/battle-end-phase"; -import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; +import GameManager from "#test/utils/gameManager"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; import PartyUiHandler, { PartyUiMode } from "#app/ui/party-ui-handler"; import { Mode } from "#app/ui/ui"; -import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { getMovePosition } from "#test/utils/gameManagerUtils"; +import { BattleEndPhase } from "#app/phases/battle-end-phase.js"; +import { SelectModifierPhase } from "#app/phases/select-modifier-phase.js"; describe("UI - Transfer Items", () => { @@ -43,7 +44,7 @@ describe("UI - Transfer Items", () => { await game.startBattle([Species.RAYQUAZA, Species.RAYQUAZA, Species.RAYQUAZA]); - game.move.select(Moves.DRAGON_CLAW); + game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_CLAW)); game.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => { expect(game.scene.ui.getHandler()).toBeInstanceOf(ModifierSelectUiHandler); @@ -87,7 +88,6 @@ describe("UI - Transfer Items", () => { handler.processInput(Button.ACTION); // select Pokemon expect(handler.optionsContainer.list.some((option) => (option as BBCodeText).text?.includes("Transfer"))).toBe(true); - game.phaseInterceptor.unlock(); }); diff --git a/src/test/ui/type-hints.test.ts b/src/test/ui/type-hints.test.ts index ccab02b82bf..f93260f15b7 100644 --- a/src/test/ui/type-hints.test.ts +++ b/src/test/ui/type-hints.test.ts @@ -1,14 +1,14 @@ -import { Button } from "#app/enums/buttons"; +import { Button } from "#app/enums/buttons.js"; import { Moves } from "#app/enums/moves"; import { Species } from "#app/enums/species"; -import { CommandPhase } from "#app/phases/command-phase"; -import FightUiHandler from "#app/ui/fight-ui-handler"; -import { Mode } from "#app/ui/ui"; +import FightUiHandler from "#app/ui/fight-ui-handler.js"; +import { Mode } from "#app/ui/ui.js"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import MockText from "../utils/mocks/mocksContainer/mockText"; import { SPLASH_ONLY } from "../utils/testUtils"; +import { CommandPhase } from "#app/phases/command-phase.js"; describe("UI - Type Hints", () => { let phaserGame: Phaser.Game; diff --git a/src/test/utils/gameManager.ts b/src/test/utils/gameManager.ts index cb3c547744b..d60cbd62836 100644 --- a/src/test/utils/gameManager.ts +++ b/src/test/utils/gameManager.ts @@ -1,47 +1,47 @@ -import { updateUserInfo } from "#app/account"; -import { BattlerIndex } from "#app/battle"; -import BattleScene from "#app/battle-scene"; -import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; -import Trainer from "#app/field/trainer"; -import { GameModes, getGameMode } from "#app/game-mode"; -import { ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type"; -import { CommandPhase } from "#app/phases/command-phase"; -import { EncounterPhase } from "#app/phases/encounter-phase"; -import { FaintPhase } from "#app/phases/faint-phase"; -import { LoginPhase } from "#app/phases/login-phase"; -import { MovePhase } from "#app/phases/move-phase"; -import { NewBattlePhase } from "#app/phases/new-battle-phase"; -import { SelectStarterPhase } from "#app/phases/select-starter-phase"; -import { SelectTargetPhase } from "#app/phases/select-target-phase"; -import { TitlePhase } from "#app/phases/title-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; -import { TurnStartPhase } from "#app/phases/turn-start-phase"; -import ErrorInterceptor from "#app/test/utils/errorInterceptor"; -import InputsHandler from "#app/test/utils/inputsHandler"; -import { MockClock } from "#app/test/utils/mocks/mockClock"; -import CommandUiHandler from "#app/ui/command-ui-handler"; -import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; -import PartyUiHandler from "#app/ui/party-ui-handler"; -import TargetSelectUiHandler from "#app/ui/target-select-ui-handler"; +import GameWrapper from "#test/utils/gameWrapper"; import { Mode } from "#app/ui/ui"; -import { Button } from "#enums/buttons"; +import { generateStarter, waitUntil } from "#test/utils/gameManagerUtils"; +import BattleScene from "#app/battle-scene.js"; +import PhaseInterceptor from "#test/utils/phaseInterceptor"; +import TextInterceptor from "#test/utils/TextInterceptor"; +import { GameModes, getGameMode } from "#app/game-mode"; +import fs from "fs"; +import { AES, enc } from "crypto-js"; +import { updateUserInfo } from "#app/account"; +import InputsHandler from "#app/test/utils/inputsHandler"; +import ErrorInterceptor from "#app/test/utils/errorInterceptor"; +import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; +import { MockClock } from "#app/test/utils/mocks/mockClock"; +import PartyUiHandler from "#app/ui/party-ui-handler"; +import CommandUiHandler, { Command } from "#app/ui/command-ui-handler"; +import Trainer from "#app/field/trainer"; import { ExpNotification } from "#enums/exp-notification"; import { GameDataType } from "#enums/game-data-type"; import { PlayerGender } from "#enums/player-gender"; import { Species } from "#enums/species"; -import { generateStarter, waitUntil } from "#test/utils/gameManagerUtils"; -import GameWrapper from "#test/utils/gameWrapper"; -import PhaseInterceptor from "#test/utils/phaseInterceptor"; -import TextInterceptor from "#test/utils/TextInterceptor"; -import { AES, enc } from "crypto-js"; -import fs from "fs"; +import { Button } from "#enums/buttons"; +import { BattlerIndex } from "#app/battle.js"; +import TargetSelectUiHandler from "#app/ui/target-select-ui-handler.js"; +import { OverridesHelper } from "./helpers/overridesHelper"; +import { ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type.js"; +import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler.js"; +import { MoveHelper } from "./helpers/moveHelper"; import { vi } from "vitest"; import { ClassicModeHelper } from "./helpers/classicModeHelper"; import { DailyModeHelper } from "./helpers/dailyModeHelper"; -import { MoveHelper } from "./helpers/moveHelper"; -import { OverridesHelper } from "./helpers/overridesHelper"; import { SettingsHelper } from "./helpers/settingsHelper"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { EncounterPhase } from "#app/phases/encounter-phase.js"; +import { FaintPhase } from "#app/phases/faint-phase.js"; +import { LoginPhase } from "#app/phases/login-phase.js"; +import { MovePhase } from "#app/phases/move-phase.js"; +import { NewBattlePhase } from "#app/phases/new-battle-phase.js"; +import { SelectStarterPhase } from "#app/phases/select-starter-phase.js"; +import { SelectTargetPhase } from "#app/phases/select-target-phase.js"; +import { TitlePhase } from "#app/phases/title-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; +import { TurnStartPhase } from "#app/phases/turn-start-phase.js"; /** * Class to manage the game state and transitions between phases. @@ -192,23 +192,38 @@ export default class GameManager { } /** - * Emulate a player's target selection after a move is chosen, usually called automatically by {@linkcode MoveHelper.select}. - * Will trigger during the next {@linkcode SelectTargetPhase} - * @param {BattlerIndex} targetIndex The index of the attack target, or `undefined` for multi-target attacks - * @param movePosition The index of the move in the pokemon's moveset array + * Emulate a player attack + * @param movePosition the index of the move in the pokemon's moveset array */ - selectTarget(movePosition: integer, targetIndex?: BattlerIndex) { + doAttack(movePosition: integer) { + this.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + this.scene.ui.setMode(Mode.FIGHT, (this.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + this.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + (this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + + // Confirm target selection if move is multi-target this.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { const handler = this.scene.ui.getHandler() as TargetSelectUiHandler; const move = (this.scene.getCurrentPhase() as SelectTargetPhase).getPokemon().getMoveset()[movePosition]!.getMove(); // TODO: is the bang correct? - if (!move.isMultiTarget()) { - handler.setCursor(targetIndex !== undefined ? targetIndex : BattlerIndex.ENEMY); - } - if (move.isMultiTarget() && targetIndex !== undefined) { - throw new Error(`targetIndex was passed to selectMove() but move ("${move.name}") is not targetted`); + if (move.isMultiTarget()) { + handler.processInput(Button.ACTION); } + }, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(MovePhase) || this.isCurrentPhase(TurnEndPhase)); + } + + /** + * Emulate a player's target selection after an attack is chosen, + * usually called after {@linkcode doAttack} in a double battle. + * @param {BattlerIndex} targetIndex the index of the attack target + */ + doSelectTarget(targetIndex: BattlerIndex) { + this.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = this.scene.ui.getHandler() as TargetSelectUiHandler; + handler.setCursor(targetIndex); handler.processInput(Button.ACTION); - }, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(MovePhase) || this.isCurrentPhase(TurnStartPhase) || this.isCurrentPhase(TurnEndPhase)); + }, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(TurnStartPhase)); } /** Faint all opponents currently on the field */ @@ -306,7 +321,7 @@ export default class GameManager { */ async importData(path): Promise<[boolean, integer]> { const saveKey = "x0i2O7WRiANTqPmZ"; - const dataRaw = fs.readFileSync(path, { encoding: "utf8", flag: "r" }); + const dataRaw = fs.readFileSync(path, {encoding: "utf8", flag: "r"}); let dataStr = AES.decrypt(dataRaw, saveKey).toString(enc.Utf8); dataStr = this.scene.gameData.convertSystemDataStr(dataStr); const systemData = this.scene.gameData.parseSystemData(dataStr); @@ -320,7 +335,7 @@ export default class GameManager { async killPokemon(pokemon: PlayerPokemon | EnemyPokemon) { (this.scene.time as MockClock).overrideDelay = 0.01; - return new Promise(async (resolve, reject) => { + return new Promise(async(resolve, reject) => { pokemon.hp = 0; this.scene.pushPhase(new FaintPhase(this.scene, pokemon.getBattlerIndex(), true)); await this.phaseInterceptor.to(FaintPhase).catch((e) => reject(e)); diff --git a/src/test/utils/gameManagerUtils.ts b/src/test/utils/gameManagerUtils.ts index 20a3fd179fd..dfba55fc75c 100644 --- a/src/test/utils/gameManagerUtils.ts +++ b/src/test/utils/gameManagerUtils.ts @@ -1,12 +1,12 @@ -import BattleScene from "#app/battle-scene"; import { getDailyRunStarters } from "#app/data/daily-run"; import { Gender } from "#app/data/gender"; -import { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species"; -import { Moves } from "#app/enums/moves"; -import { PlayerPokemon } from "#app/field/pokemon"; -import { GameModes, getGameMode } from "#app/game-mode"; -import { Starter } from "#app/ui/starter-select-ui-handler"; import { Species } from "#enums/species"; +import { Starter } from "#app/ui/starter-select-ui-handler"; +import { GameModes, getGameMode } from "#app/game-mode"; +import { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species"; +import { PlayerPokemon } from "#app/field/pokemon"; +import { Moves } from "#app/enums/moves"; +import BattleScene from "#app/battle-scene"; /** Function to convert Blob to string */ export function blobToString(blob) { diff --git a/src/test/utils/gameWrapper.ts b/src/test/utils/gameWrapper.ts index f3098fa9b71..49044c260fa 100644 --- a/src/test/utils/gameWrapper.ts +++ b/src/test/utils/gameWrapper.ts @@ -1,28 +1,31 @@ /* eslint-disable */ // @ts-nocheck -import BattleScene, * as battleScene from "#app/battle-scene"; -import { MoveAnim } from "#app/data/battle-anims"; -import Pokemon from "#app/field/pokemon"; -import * as Utils from "#app/utils"; -import { blobToString } from "#test/utils/gameManagerUtils"; -import { MockClock } from "#test/utils/mocks/mockClock"; -import mockConsoleLog from "#test/utils/mocks/mockConsoleLog"; -import { MockFetch } from "#test/utils/mocks/mockFetch"; -import MockLoader from "#test/utils/mocks/mockLoader"; -import mockLocalStorage from "#test/utils/mocks/mockLocalStorage"; -import MockImage from "#test/utils/mocks/mocksContainer/mockImage"; -import MockTextureManager from "#test/utils/mocks/mockTextureManager"; +import * as main from "#app/main"; import fs from "fs"; -import Phaser from "phaser"; -import InputText from "phaser3-rex-plugins/plugins/inputtext"; -import { vi } from "vitest"; -import { MockGameObjectCreator } from "./mocks/mockGameObjectCreator"; import InputManager = Phaser.Input.InputManager; import KeyboardManager = Phaser.Input.Keyboard.KeyboardManager; import KeyboardPlugin = Phaser.Input.Keyboard.KeyboardPlugin; import GamepadPlugin = Phaser.Input.Gamepad.GamepadPlugin; import EventEmitter = Phaser.Events.EventEmitter; import UpdateList = Phaser.GameObjects.UpdateList; +import MockGraphics from "#test/utils/mocks/mocksContainer/mockGraphics"; +import MockTextureManager from "#test/utils/mocks/mockTextureManager"; +import Phaser from "phaser"; +import { blobToString } from "#test/utils/gameManagerUtils"; +import { vi } from "vitest"; +import mockLocalStorage from "#test/utils/mocks/mockLocalStorage"; +import mockConsoleLog from "#test/utils/mocks/mockConsoleLog"; +import MockLoader from "#test/utils/mocks/mockLoader"; +import { MockFetch } from "#test/utils/mocks/mockFetch"; +import * as Utils from "#app/utils"; +import InputText from "phaser3-rex-plugins/plugins/inputtext"; +import { MockClock } from "#test/utils/mocks/mockClock"; +import BattleScene from "#app/battle-scene.js"; +import { MoveAnim } from "#app/data/battle-anims"; +import Pokemon from "#app/field/pokemon"; +import * as battleScene from "#app/battle-scene"; +import MockImage from "#test/utils/mocks/mocksContainer/mockImage.js"; +import { MockGameObjectCreator } from "./mocks/mockGameObjectCreator"; Object.defineProperty(window, "localStorage", { value: mockLocalStorage(), diff --git a/src/test/utils/helpers/classicModeHelper.ts b/src/test/utils/helpers/classicModeHelper.ts index f41472303b4..cf59dd81183 100644 --- a/src/test/utils/helpers/classicModeHelper.ts +++ b/src/test/utils/helpers/classicModeHelper.ts @@ -1,9 +1,9 @@ -import { Species } from "#app/enums/species"; -import { GameModes, getGameMode } from "#app/game-mode"; -import overrides from "#app/overrides"; -import { EncounterPhase } from "#app/phases/encounter-phase"; -import { SelectStarterPhase } from "#app/phases/select-starter-phase"; -import { Mode } from "#app/ui/ui"; +import { Species } from "#app/enums/species.js"; +import { GameModes, getGameMode } from "#app/game-mode.js"; +import overrides from "#app/overrides.js"; +import { EncounterPhase } from "#app/phases/encounter-phase.js"; +import { SelectStarterPhase } from "#app/phases/select-starter-phase.js"; +import { Mode } from "#app/ui/ui.js"; import { generateStarter } from "../gameManagerUtils"; import { GameManagerHelper } from "./gameManagerHelper"; diff --git a/src/test/utils/helpers/dailyModeHelper.ts b/src/test/utils/helpers/dailyModeHelper.ts index 8f60981f4d8..a143e212fcb 100644 --- a/src/test/utils/helpers/dailyModeHelper.ts +++ b/src/test/utils/helpers/dailyModeHelper.ts @@ -1,9 +1,9 @@ -import { Button } from "#app/enums/buttons"; -import overrides from "#app/overrides"; -import { EncounterPhase } from "#app/phases/encounter-phase"; -import { TitlePhase } from "#app/phases/title-phase"; -import SaveSlotSelectUiHandler from "#app/ui/save-slot-select-ui-handler"; -import { Mode } from "#app/ui/ui"; +import { Button } from "#app/enums/buttons.js"; +import overrides from "#app/overrides.js"; +import { EncounterPhase } from "#app/phases/encounter-phase.js"; +import { TitlePhase } from "#app/phases/title-phase.js"; +import SaveSlotSelectUiHandler from "#app/ui/save-slot-select-ui-handler.js"; +import { Mode } from "#app/ui/ui.js"; import { GameManagerHelper } from "./gameManagerHelper"; /** diff --git a/src/test/utils/helpers/moveHelper.ts b/src/test/utils/helpers/moveHelper.ts index a53fa521785..3179e63a6d0 100644 --- a/src/test/utils/helpers/moveHelper.ts +++ b/src/test/utils/helpers/moveHelper.ts @@ -1,12 +1,6 @@ -import { BattlerIndex } from "#app/battle"; -import { Moves } from "#app/enums/moves"; -import { CommandPhase } from "#app/phases/command-phase"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { Command } from "#app/ui/command-ui-handler"; -import { Mode } from "#app/ui/ui"; import { vi } from "vitest"; -import { getMovePosition } from "../gameManagerUtils"; import { GameManagerHelper } from "./gameManagerHelper"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; /** * Helper to handle a Pokemon's move @@ -38,25 +32,4 @@ export class MoveHelper extends GameManagerHelper { hitCheck.mockReturnValue(false); } } - - /** - * Select the move to be used by the given Pokemon(-index). Triggers during the next {@linkcode CommandPhase} - * @param move the move to use - * @param pkmIndex the pokemon index. Relevant for double-battles only (defaults to 0) - * @param targetIndex The {@linkcode BattlerIndex} of the Pokemon to target for single-target moves, or `null` if a manual call to `selectTarget()` is required - */ - select(move: Moves, pkmIndex: 0 | 1 = 0, targetIndex?: BattlerIndex | null) { - const movePosition = getMovePosition(this.game.scene, pkmIndex, move); - - this.game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { - this.game.scene.ui.setMode(Mode.FIGHT, (this.game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); - }); - this.game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { - (this.game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); - }); - - if (targetIndex !== null) { - this.game.selectTarget(movePosition, targetIndex); - } - } } diff --git a/src/test/utils/inputsHandler.ts b/src/test/utils/inputsHandler.ts index 30dd101f43d..148329ada32 100644 --- a/src/test/utils/inputsHandler.ts +++ b/src/test/utils/inputsHandler.ts @@ -1,11 +1,11 @@ import BattleScene from "#app/battle-scene"; -import pad_xbox360 from "#app/configs/inputs/pad_xbox360"; -import { InputsController } from "#app/inputs-controller"; -import TouchControl from "#app/touch-controls"; -import { holdOn } from "#test/utils/gameManagerUtils"; -import fs from "fs"; -import { JSDOM } from "jsdom"; import Phaser from "phaser"; +import { InputsController } from "#app/inputs-controller"; +import pad_xbox360 from "#app/configs/inputs/pad_xbox360"; +import { holdOn } from "#test/utils/gameManagerUtils"; +import TouchControl from "#app/touch-controls"; +import { JSDOM } from "jsdom"; +import fs from "fs"; interface LogEntry { type: string; diff --git a/src/test/utils/misc.test.ts b/src/test/utils/misc.test.ts index a49b2894ca2..c1947dbe8a2 100644 --- a/src/test/utils/misc.test.ts +++ b/src/test/utils/misc.test.ts @@ -1,8 +1,8 @@ -import { apiFetch } from "#app/utils"; -import GameManager from "#test/utils/gameManager"; -import { waitUntil } from "#test/utils/gameManagerUtils"; -import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#test/utils/gameManager"; +import { apiFetch } from "#app/utils"; +import { waitUntil } from "#test/utils/gameManagerUtils"; describe("Test misc", () => { let phaserGame: Phaser.Game; diff --git a/src/test/utils/mocks/mockTextureManager.ts b/src/test/utils/mocks/mockTextureManager.ts index 16d94da28ad..330409e9776 100644 --- a/src/test/utils/mocks/mockTextureManager.ts +++ b/src/test/utils/mocks/mockTextureManager.ts @@ -1,12 +1,12 @@ import MockContainer from "#test/utils/mocks/mocksContainer/mockContainer"; -import MockImage from "#test/utils/mocks/mocksContainer/mockImage"; -import MockNineslice from "#test/utils/mocks/mocksContainer/mockNineslice"; -import MockPolygon from "#test/utils/mocks/mocksContainer/mockPolygon"; -import MockRectangle from "#test/utils/mocks/mocksContainer/mockRectangle"; import MockSprite from "#test/utils/mocks/mocksContainer/mockSprite"; +import MockRectangle from "#test/utils/mocks/mocksContainer/mockRectangle"; +import MockNineslice from "#test/utils/mocks/mocksContainer/mockNineslice"; +import MockImage from "#test/utils/mocks/mocksContainer/mockImage"; import MockText from "#test/utils/mocks/mocksContainer/mockText"; -import MockTexture from "#test/utils/mocks/mocksContainer/mockTexture"; +import MockPolygon from "#test/utils/mocks/mocksContainer/mockPolygon"; import { MockGameObject } from "./mockGameObject"; +import MockTexture from "#test/utils/mocks/mocksContainer/mockTexture"; /** * Stub class for Phaser.Textures.TextureManager diff --git a/src/test/utils/mocks/mocksContainer/mockSprite.ts b/src/test/utils/mocks/mocksContainer/mockSprite.ts index 35cd2d5faab..9c566fc4bcb 100644 --- a/src/test/utils/mocks/mocksContainer/mockSprite.ts +++ b/src/test/utils/mocks/mocksContainer/mockSprite.ts @@ -1,7 +1,7 @@ -import Phaser from "phaser"; import { MockGameObject } from "../mockGameObject"; import Sprite = Phaser.GameObjects.Sprite; import Frame = Phaser.Textures.Frame; +import Phaser from "phaser"; export default class MockSprite implements MockGameObject { diff --git a/src/test/utils/mocks/mocksContainer/mockTexture.ts b/src/test/utils/mocks/mocksContainer/mockTexture.ts index cb31480cc60..03bedb4751b 100644 --- a/src/test/utils/mocks/mocksContainer/mockTexture.ts +++ b/src/test/utils/mocks/mocksContainer/mockTexture.ts @@ -1,5 +1,5 @@ -import MockTextureManager from "#test/utils/mocks/mockTextureManager"; import { MockGameObject } from "../mockGameObject"; +import MockTextureManager from "#test/utils/mocks/mockTextureManager"; /** diff --git a/src/test/utils/phaseInterceptor.ts b/src/test/utils/phaseInterceptor.ts index ca3d55137fa..2304d726757 100644 --- a/src/test/utils/phaseInterceptor.ts +++ b/src/test/utils/phaseInterceptor.ts @@ -1,42 +1,42 @@ -import { Phase } from "#app/phase"; -import { BattleEndPhase } from "#app/phases/battle-end-phase"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { CheckSwitchPhase } from "#app/phases/check-switch-phase"; -import { CommandPhase } from "#app/phases/command-phase"; -import { DamagePhase } from "#app/phases/damage-phase"; -import { EggLapsePhase } from "#app/phases/egg-lapse-phase"; -import { EncounterPhase } from "#app/phases/encounter-phase"; -import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; -import { FaintPhase } from "#app/phases/faint-phase"; -import { LoginPhase } from "#app/phases/login-phase"; -import { MessagePhase } from "#app/phases/message-phase"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { MovePhase } from "#app/phases/move-phase"; -import { NewBattlePhase } from "#app/phases/new-battle-phase"; -import { NextEncounterPhase } from "#app/phases/next-encounter-phase"; -import { PartyHealPhase } from "#app/phases/party-heal-phase"; -import { PostSummonPhase } from "#app/phases/post-summon-phase"; -import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; -import { SelectGenderPhase } from "#app/phases/select-gender-phase"; -import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; -import { SelectStarterPhase } from "#app/phases/select-starter-phase"; -import { SelectTargetPhase } from "#app/phases/select-target-phase"; -import { ShinySparklePhase } from "#app/phases/shiny-sparkle-phase"; -import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; -import { StatChangePhase } from "#app/phases/stat-change-phase"; -import { SummonPhase } from "#app/phases/summon-phase"; -import { SwitchPhase } from "#app/phases/switch-phase"; -import { SwitchSummonPhase } from "#app/phases/switch-summon-phase"; -import { TitlePhase } from "#app/phases/title-phase"; -import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; -import { TurnStartPhase } from "#app/phases/turn-start-phase"; -import { UnavailablePhase } from "#app/phases/unavailable-phase"; -import { VictoryPhase } from "#app/phases/victory-phase"; -import ErrorInterceptor from "#app/test/utils/errorInterceptor"; import UI, { Mode } from "#app/ui/ui"; +import { Phase } from "#app/phase"; +import ErrorInterceptor from "#app/test/utils/errorInterceptor"; +import { BattleEndPhase } from "#app/phases/battle-end-phase.js"; +import { BerryPhase } from "#app/phases/berry-phase.js"; +import { CheckSwitchPhase } from "#app/phases/check-switch-phase.js"; +import { CommandPhase } from "#app/phases/command-phase.js"; +import { DamagePhase } from "#app/phases/damage-phase.js"; +import { EggLapsePhase } from "#app/phases/egg-lapse-phase.js"; +import { EncounterPhase } from "#app/phases/encounter-phase.js"; +import { EnemyCommandPhase } from "#app/phases/enemy-command-phase.js"; +import { FaintPhase } from "#app/phases/faint-phase.js"; +import { LoginPhase } from "#app/phases/login-phase.js"; +import { MessagePhase } from "#app/phases/message-phase.js"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase.js"; +import { MoveEndPhase } from "#app/phases/move-end-phase.js"; +import { MovePhase } from "#app/phases/move-phase.js"; +import { NewBattlePhase } from "#app/phases/new-battle-phase.js"; +import { NextEncounterPhase } from "#app/phases/next-encounter-phase.js"; +import { PostSummonPhase } from "#app/phases/post-summon-phase.js"; +import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase.js"; +import { SelectGenderPhase } from "#app/phases/select-gender-phase.js"; +import { SelectModifierPhase } from "#app/phases/select-modifier-phase.js"; +import { SelectStarterPhase } from "#app/phases/select-starter-phase.js"; +import { SelectTargetPhase } from "#app/phases/select-target-phase.js"; +import { ShinySparklePhase } from "#app/phases/shiny-sparkle-phase.js"; +import { ShowAbilityPhase } from "#app/phases/show-ability-phase.js"; +import { StatChangePhase } from "#app/phases/stat-change-phase.js"; +import { SummonPhase } from "#app/phases/summon-phase.js"; +import { SwitchPhase } from "#app/phases/switch-phase.js"; +import { SwitchSummonPhase } from "#app/phases/switch-summon-phase.js"; +import { TitlePhase } from "#app/phases/title-phase.js"; +import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase.js"; +import { TurnEndPhase } from "#app/phases/turn-end-phase.js"; +import { TurnInitPhase } from "#app/phases/turn-init-phase.js"; +import { TurnStartPhase } from "#app/phases/turn-start-phase.js"; +import { UnavailablePhase } from "#app/phases/unavailable-phase.js"; +import { VictoryPhase } from "#app/phases/victory-phase.js"; +import { PartyHealPhase } from "#app/phases/party-heal-phase.js"; export default class PhaseInterceptor { public scene; diff --git a/src/test/vitest.setup.ts b/src/test/vitest.setup.ts index eaa987c1a66..b2861b7071c 100644 --- a/src/test/vitest.setup.ts +++ b/src/test/vitest.setup.ts @@ -9,8 +9,8 @@ import { initMoves } from "#app/data/move"; import { initPokemonPrevolutions } from "#app/data/pokemon-evolutions"; import { initPokemonForms } from "#app/data/pokemon-forms"; import { initSpecies } from "#app/data/pokemon-species"; -import { initAchievements } from "#app/system/achv"; -import { initVouchers } from "#app/system/voucher"; +import { initAchievements } from "#app/system/achv.js"; +import { initVouchers } from "#app/system/voucher.js"; import { initStatsKeys } from "#app/ui/game-stats-ui-handler"; import { beforeAll, vi } from "vitest"; diff --git a/src/ui/target-select-ui-handler.ts b/src/ui/target-select-ui-handler.ts index 6ca580dc2b2..42c7fef5660 100644 --- a/src/ui/target-select-ui-handler.ts +++ b/src/ui/target-select-ui-handler.ts @@ -118,7 +118,7 @@ export default class TargetSelectUiHandler extends UiHandler { this.targetFlashTween = this.scene.tweens.add({ targets: this.targetsHighlighted, - key: { start: 1, to: 0.25 }, + key: { start: 0.55, to: 1 }, loop: -1, loopDelay: 150, duration: Utils.fixedInt(450), diff --git a/src/utils.ts b/src/utils.ts index a9bbc93d684..c51ac2b5b0b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -560,17 +560,3 @@ export function capitalizeString(str: string, sep: string, lowerFirstChar: boole export function isNullOrUndefined(object: any): boolean { return null === object || undefined === object; } - -/** - * This function is used in the context of a Pokémon battle game to calculate the actual integer damage value from a float result. - * Many damage calculation formulas involve various parameters and result in float values. - * The actual damage applied to a Pokémon's HP must be an integer. - * This function helps in ensuring that by flooring the float value and enforcing a minimum damage value. - * - * @param value - The float value to convert. - * @param minValue - The minimum integer value to return. Defaults to 1. - * @returns The converted value as an integer. - */ -export function toDmgValue(value: number, minValue: number = 1) { - return Math.max(Math.floor(value), minValue); -}