diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 3cc109df264..ce3f16e408a 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -2051,7 +2051,7 @@ export class StockpilingTag extends BattlerTag { super(BattlerTagType.STOCKPILING, BattlerTagLapseType.CUSTOM, 1, sourceMove); } - private onStatStagesChanged: StatStageChangeCallback = (_, statsChanged, statChanges) => { + private onStatStagesChanged: StatStageChangeCallback = (statsChanged, statChanges, _target) => { const defChange = statChanges[statsChanged.indexOf(Stat.DEF)] ?? 0; const spDefChange = statChanges[statsChanged.indexOf(Stat.SPDEF)] ?? 0; diff --git a/src/phases/check-switch-phase.ts b/src/phases/check-switch-phase.ts index 8849d304435..44cdcc2ba65 100644 --- a/src/phases/check-switch-phase.ts +++ b/src/phases/check-switch-phase.ts @@ -50,7 +50,7 @@ export class CheckSwitchPhase extends BattlePhase { this.scene.ui.showText(i18next.t("battle:switchQuestion", { pokemonName: this.useName ? getPokemonNameWithAffix(pokemon) : i18next.t("battle:pokemon") }), null, () => { this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.MESSAGE); - this.scene.tryRemovePhase(p => p instanceof PostSummonPhase && p.player && p.fieldIndex === this.fieldIndex); + this.scene.tryRemovePhase(p => p instanceof PostSummonPhase && p.isPlayer && p.fieldIndex === this.fieldIndex); this.scene.unshiftPhase(new SwitchPhase(this.scene, SwitchType.SWITCH, this.fieldIndex, false, true)); this.end(); }, () => { diff --git a/src/phases/common-anim-phase.ts b/src/phases/common-anim-phase.ts index c4071488eef..fea15fba308 100644 --- a/src/phases/common-anim-phase.ts +++ b/src/phases/common-anim-phase.ts @@ -21,7 +21,7 @@ export class CommonAnimPhase extends PokemonPhase { } start() { - const target = this.targetIndex !== undefined ? (this.player ? this.scene.getEnemyField() : this.scene.getPlayerField())[this.targetIndex] : this.getPokemon(); + const target = this.targetIndex !== undefined ? (this.isPlayer ? this.scene.getEnemyField() : this.scene.getPlayerField())[this.targetIndex] : this.getPokemon(); new CommonBattleAnim(this.anim, this.getPokemon(), target).play(this.scene, false, () => { this.end(); }); diff --git a/src/phases/faint-phase.ts b/src/phases/faint-phase.ts index 66bb22899be..08a6de4ae5e 100644 --- a/src/phases/faint-phase.ts +++ b/src/phases/faint-phase.ts @@ -33,13 +33,13 @@ export class FaintPhase extends PokemonPhase { super.start(); if (!this.preventEndure) { - const instantReviveModifier = this.scene.applyModifier(PokemonInstantReviveModifier, this.player, this.getPokemon()) as PokemonInstantReviveModifier; + const instantReviveModifier = this.scene.applyModifier(PokemonInstantReviveModifier, this.isPlayer, this.getPokemon()) as PokemonInstantReviveModifier; if (instantReviveModifier) { if (!--instantReviveModifier.stackCount) { this.scene.removeModifier(instantReviveModifier); } - this.scene.updateModifiers(this.player); + this.scene.updateModifiers(this.isPlayer); return this.end(); } } @@ -88,7 +88,7 @@ export class FaintPhase extends PokemonPhase { } } - if (this.player) { + if (this.isPlayer) { /** The total number of Pokemon in the player's party that can legally fight */ const legalPlayerPokemon = this.scene.getParty().filter(p => p.isAllowedInBattle()); /** The total number of legal player Pokemon that aren't currently on the field */ @@ -159,7 +159,7 @@ export class FaintPhase extends PokemonPhase { tryOverrideForBattleSpec(): boolean { switch (this.scene.currentBattle.battleSpec) { case BattleSpec.FINAL_BOSS: - if (!this.player) { + if (!this.isPlayer) { const enemy = this.getPokemon(); if (enemy.formIndex) { this.scene.ui.showDialogue(battleSpecDialogue[BattleSpec.FINAL_BOSS].secondStageWin, enemy.species.name, null, () => this.doFaint()); diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index b2d429a4313..900c0dcfd70 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -290,7 +290,7 @@ export class MoveEffectPhase extends PokemonPhase { * steal an item from the target granted by Grip Claw */ if (this.move.getMove() instanceof AttackMove) { - this.scene.applyModifiers(ContactHeldItemTransferChanceModifier, this.player, user, target); + this.scene.applyModifiers(ContactHeldItemTransferChanceModifier, this.isPlayer, user, target); } resolve(); }); @@ -360,7 +360,7 @@ export class MoveEffectPhase extends PokemonPhase { // If there are multiple hits, or if there are hits of the multi-hit move left this.scene.queueMessage(i18next.t("battle:attackHitsCount", { count: hitsTotal })); } - this.scene.applyModifiers(HitHealModifier, this.player, user); + this.scene.applyModifiers(HitHealModifier, this.isPlayer, user); // Clear all cached move effectiveness values among targets this.getTargets().forEach((target) => target.turnData.moveEffectiveness = null); } @@ -429,7 +429,7 @@ export class MoveEffectPhase extends PokemonPhase { if (this.battlerIndex > BattlerIndex.ENEMY_2) { return this.scene.getPokemonById(this.battlerIndex) ?? undefined; } - return (this.player ? this.scene.getPlayerField() : this.scene.getEnemyField())[this.fieldIndex]; + return (this.isPlayer ? this.scene.getPlayerField() : this.scene.getEnemyField())[this.fieldIndex]; } /** Returns an array of all {@linkcode Pokemon} targeted by this phase's invoked move */ diff --git a/src/phases/pokemon-heal-phase.ts b/src/phases/pokemon-heal-phase.ts index dc0bd235bb5..fa9c1350666 100644 --- a/src/phases/pokemon-heal-phase.ts +++ b/src/phases/pokemon-heal-phase.ts @@ -61,7 +61,7 @@ export class PokemonHealPhase extends CommonAnimPhase { } else if (healOrDamage) { const hpRestoreMultiplier = new Utils.IntegerHolder(1); if (!this.revive) { - this.scene.applyModifiers(HealingBoosterModifier, this.player, hpRestoreMultiplier); + this.scene.applyModifiers(HealingBoosterModifier, this.isPlayer, hpRestoreMultiplier); } const healAmount = new Utils.NumberHolder(Math.floor(this.hpHealed * hpRestoreMultiplier.value)); if (healAmount.value < 0) { diff --git a/src/phases/pokemon-phase.ts b/src/phases/pokemon-phase.ts index b980c1d1719..e2cc0b9c0c3 100644 --- a/src/phases/pokemon-phase.ts +++ b/src/phases/pokemon-phase.ts @@ -1,29 +1,33 @@ -import BattleScene from "#app/battle-scene"; import { BattlerIndex } from "#app/battle"; +import BattleScene from "#app/battle-scene"; import Pokemon from "#app/field/pokemon"; -import { FieldPhase } from "./field-phase"; +import { FieldPhase } from "#app/phases/field-phase"; export abstract class PokemonPhase extends FieldPhase { - protected battlerIndex: BattlerIndex | integer; - public player: boolean; - public fieldIndex: integer; + protected battlerIndex: BattlerIndex | number; + public isPlayer: boolean; + public fieldIndex: number; - constructor(scene: BattleScene, battlerIndex?: BattlerIndex | integer) { + constructor(scene: BattleScene, battlerIndex?: BattlerIndex | number) { super(scene); if (battlerIndex === undefined) { - battlerIndex = scene.getField().find(p => p?.isActive())!.getBattlerIndex(); // TODO: is the bang correct here? + battlerIndex = scene.getField().find(p => p?.isActive())?.getBattlerIndex(); } - this.battlerIndex = battlerIndex; - this.player = battlerIndex < 2; - this.fieldIndex = battlerIndex % 2; + if (battlerIndex !== undefined) { + this.battlerIndex = battlerIndex; + this.isPlayer = battlerIndex < 2; + this.fieldIndex = battlerIndex % 2; + } else { + console.warn("Unable to find pokemon battlerIndex!"); + } } getPokemon(): Pokemon { if (this.battlerIndex > BattlerIndex.ENEMY_2) { return this.scene.getPokemonById(this.battlerIndex)!; //TODO: is this bang correct? } - return this.scene.getField()[this.battlerIndex]!; //TODO: is this bang correct? + return this.scene.getField()[this.battlerIndex]; } } diff --git a/src/phases/stat-stage-change-phase.ts b/src/phases/stat-stage-change-phase.ts index 4418c38c849..71f03e321cd 100644 --- a/src/phases/stat-stage-change-phase.ts +++ b/src/phases/stat-stage-change-phase.ts @@ -1,64 +1,64 @@ import { BattlerIndex } from "#app/battle"; import BattleScene from "#app/battle-scene"; -import { applyAbAttrs, applyPostStatStageChangeAbAttrs, applyPreStatStageChangeAbAttrs, PostStatStageChangeAbAttr, ProtectStatAbAttr, StatStageChangeCopyAbAttr, StatStageChangeMultiplierAbAttr } from "#app/data/ability"; +import { + applyAbAttrs, applyPostStatStageChangeAbAttrs, applyPreStatStageChangeAbAttrs, + PostStatStageChangeAbAttr, ProtectStatAbAttr, StatStageChangeCopyAbAttr, StatStageChangeMultiplierAbAttr +} from "#app/data/ability"; import { ArenaTagSide, MistTag } from "#app/data/arena-tag"; import Pokemon from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; import { ResetNegativeStatStageModifier } from "#app/modifier/modifier"; +import { PokemonPhase } from "#app/phases/pokemon-phase"; import { handleTutorial, Tutorial } from "#app/tutorial"; -import { NumberHolder, BooleanHolder } from "#app/utils"; +import { BooleanHolder, NumberHolder } from "#app/utils"; +import { getStatKey, getStatStageChangeDescriptionKey, Stat, type BattleStat } from "#enums/stat"; import i18next from "i18next"; -import { PokemonPhase } from "./pokemon-phase"; -import { Stat, type BattleStat, getStatKey, getStatStageChangeDescriptionKey } from "#enums/stat"; -export type StatStageChangeCallback = (target: Pokemon | null, changed: BattleStat[], relativeChanges: number[]) => void; +export type StatStageChangeCallback = (changed: BattleStat[], relativeChanges: number[], target?: Pokemon) => void; export class StatStageChangePhase extends PokemonPhase { - private stats: BattleStat[]; - private selfTarget: boolean; - private stages: integer; - private showMessage: boolean; - private ignoreAbilities: boolean; - private canBeCopied: boolean; - private onChange: StatStageChangeCallback | null; + private filteredStats: BattleStat[]; + private stagesHolder: NumberHolder; + private relLevels: number[]; - - constructor(scene: BattleScene, battlerIndex: BattlerIndex, selfTarget: boolean, stats: BattleStat[], stages: integer, showMessage: boolean = true, ignoreAbilities: boolean = false, canBeCopied: boolean = true, onChange: StatStageChangeCallback | null = null) { + constructor( + scene: BattleScene, + battlerIndex: BattlerIndex, + protected selfTarget: boolean, + protected stats: BattleStat[], + protected stages: number, + protected showMessage: boolean = true, + protected ignoreAbilities: boolean = false, + protected canBeCopied: boolean = true, + protected onChange?: StatStageChangeCallback + ) { super(scene, battlerIndex); - - this.selfTarget = selfTarget; - this.stats = stats; - this.stages = stages; - this.showMessage = showMessage; - this.ignoreAbilities = ignoreAbilities; - this.canBeCopied = canBeCopied; - this.onChange = onChange; } - start() { + public override start(): void { const pokemon = this.getPokemon(); if (!pokemon.isActive(true)) { - return this.end(); + return super.end(); } - const stages = new NumberHolder(this.stages); + this.stagesHolder = new NumberHolder(this.stages); if (!this.ignoreAbilities) { - applyAbAttrs(StatStageChangeMultiplierAbAttr, pokemon, null, false, stages); + applyAbAttrs(StatStageChangeMultiplierAbAttr, pokemon, null, false, this.stagesHolder); } let simulate = false; - const filteredStats = this.stats.filter(stat => { + this.filteredStats = this.stats.filter(stat => { const cancelled = new BooleanHolder(false); - if (!this.selfTarget && stages.value < 0) { + if (!this.selfTarget && this.stagesHolder.value < 0) { // TODO: Include simulate boolean when tag applications can be simulated this.scene.arena.applyTagsForSide(MistTag, pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, cancelled); } - if (!cancelled.value && !this.selfTarget && stages.value < 0) { + if (!cancelled.value && !this.selfTarget && this.stagesHolder.value < 0) { applyPreStatStageChangeAbAttrs(ProtectStatAbAttr, pokemon, stat, cancelled, simulate); } @@ -70,83 +70,35 @@ export class StatStageChangePhase extends PokemonPhase { return !cancelled.value; }); - const relLevels = filteredStats.map(s => (stages.value >= 1 ? Math.min(pokemon.getStatStage(s) + stages.value, 6) : Math.max(pokemon.getStatStage(s) + stages.value, -6)) - pokemon.getStatStage(s)); + this.relLevels = this.filteredStats.map(s => + (this.stagesHolder.value >= 1 + ? Math.min(pokemon.getStatStage(s) + this.stagesHolder.value, 6) + : Math.max(pokemon.getStatStage(s) + this.stagesHolder.value, -6) + ) - pokemon.getStatStage(s)); - this.onChange && this.onChange(this.getPokemon(), filteredStats, relLevels); + if (this.onChange) { + this.onChange(this.filteredStats, this.relLevels, this.getPokemon()); + } - const end = () => { - if (this.showMessage) { - const messages = this.getStatStageChangeMessages(filteredStats, stages.value, relLevels); - for (const message of messages) { - this.scene.queueMessage(message); - } - } - - for (const s of filteredStats) { - if (stages.value > 0 && pokemon.getStatStage(s) < 6) { - if (!pokemon.turnData) { - // Temporary fix for missing turn data struct on turn 1 - pokemon.resetTurnData(); - } - pokemon.turnData.statStagesIncreased = true; - } else if (stages.value < 0 && pokemon.getStatStage(s) > -6) { - if (!pokemon.turnData) { - // Temporary fix for missing turn data struct on turn 1 - pokemon.resetTurnData(); - } - pokemon.turnData.statStagesDecreased = true; - } - - pokemon.setStatStage(s, pokemon.getStatStage(s) + stages.value); - } - - if (stages.value > 0 && this.canBeCopied) { - for (const opponent of pokemon.getOpponents()) { - applyAbAttrs(StatStageChangeCopyAbAttr, opponent, null, false, this.stats, stages.value); - } - } - - applyPostStatStageChangeAbAttrs(PostStatStageChangeAbAttr, pokemon, filteredStats, this.stages, this.selfTarget); - - // Look for any other stat change phases; if this is the last one, do White Herb check - const existingPhase = this.scene.findPhase(p => p instanceof StatStageChangePhase && p.battlerIndex === this.battlerIndex); - if (!(existingPhase instanceof StatStageChangePhase)) { - // Apply White Herb if needed - const whiteHerb = this.scene.applyModifier(ResetNegativeStatStageModifier, this.player, pokemon) as ResetNegativeStatStageModifier; - // If the White Herb was applied, consume it - if (whiteHerb) { - whiteHerb.stackCount--; - if (whiteHerb.stackCount <= 0) { - this.scene.removeModifier(whiteHerb); - } - this.scene.updateModifiers(this.player); - } - } - - pokemon.updateInfo(); - - handleTutorial(this.scene, Tutorial.Stat_Change).then(() => super.end()); - }; - - if (relLevels.filter(l => l).length && this.scene.moveAnimations) { + if (this.relLevels.filter(l => l).length && this.scene.moveAnimations) { pokemon.enableMask(); const pokemonMaskSprite = pokemon.maskSprite; - const tileX = (this.player ? 106 : 236) * pokemon.getSpriteScale() * this.scene.field.scale; - const tileY = ((this.player ? 148 : 84) + (stages.value >= 1 ? 160 : 0)) * pokemon.getSpriteScale() * this.scene.field.scale; + const tileX = (this.isPlayer ? 106 : 236) * pokemon.getSpriteScale() * this.scene.field.scale; + const tileY = ((this.isPlayer ? 148 : 84) + (this.stagesHolder.value >= 1 ? 160 : 0)) * pokemon.getSpriteScale() * this.scene.field.scale; const tileWidth = 156 * this.scene.field.scale * pokemon.getSpriteScale(); const tileHeight = 316 * this.scene.field.scale * pokemon.getSpriteScale(); // On increase, show the red sprite located at ATK // On decrease, show the blue sprite located at SPD - const spriteColor = stages.value >= 1 ? Stat[Stat.ATK].toLowerCase() : Stat[Stat.SPD].toLowerCase(); + const spriteColor = this.stagesHolder.value >= 1 ? Stat[Stat.ATK].toLowerCase() : Stat[Stat.SPD].toLowerCase(); const statSprite = this.scene.add.tileSprite(tileX, tileY, tileWidth, tileHeight, "battle_stats", spriteColor); statSprite.setPipeline(this.scene.fieldSpritePipeline); statSprite.setAlpha(0); statSprite.setScale(6); statSprite.setOrigin(0.5, 1); - this.scene.playSound(`se/stat_${stages.value >= 1 ? "up" : "down"}`); + this.scene.playSound(`se/stat_${this.stagesHolder.value >= 1 ? "up" : "down"}`); statSprite.setMask(new Phaser.Display.Masks.BitmapMask(this.scene, pokemonMaskSprite ?? undefined)); @@ -167,44 +119,74 @@ export class StatStageChangePhase extends PokemonPhase { this.scene.tweens.add({ targets: statSprite, duration: 1500, - y: `${stages.value >= 1 ? "-" : "+"}=${160 * 6}` + y: `${this.stagesHolder.value >= 1 ? "-" : "+"}=${160 * 6}` }); this.scene.time.delayedCall(1750, () => { pokemon.disableMask(); - end(); + this.end(); }); } else { - end(); + this.end(); } } - aggregateStatStageChanges(): void { - const accEva: BattleStat[] = [ Stat.ACC, Stat.EVA ]; - const isAccEva = accEva.some(s => this.stats.includes(s)); - let existingPhase: StatStageChangePhase; - if (this.stats.length === 1) { - while ((existingPhase = (this.scene.findPhase(p => p instanceof StatStageChangePhase && p.battlerIndex === this.battlerIndex && p.stats.length === 1 - && (p.stats[0] === this.stats[0]) - && p.selfTarget === this.selfTarget && p.showMessage === this.showMessage && p.ignoreAbilities === this.ignoreAbilities) as StatStageChangePhase))) { - this.stages += existingPhase.stages; + public override end(): void { + const pokemon = this.getPokemon(); + if (this.showMessage) { + const messages = this.getStatStageChangeMessages(this.filteredStats, this.stagesHolder.value, this.relLevels); + for (const message of messages) { + this.scene.queueMessage(message); + } + } - if (!this.scene.tryRemovePhase(p => p === existingPhase)) { - break; + for (const s of this.filteredStats) { + if (this.stagesHolder.value > 0 && pokemon.getStatStage(s) < 6) { + if (!pokemon.turnData) { + // Temporary fix for missing turn data struct on turn 1 + pokemon.resetTurnData(); } + pokemon.turnData.statStagesIncreased = true; + } else if (this.stagesHolder.value < 0 && pokemon.getStatStage(s) > -6) { + if (!pokemon.turnData) { + // Temporary fix for missing turn data struct on turn 1 + pokemon.resetTurnData(); + } + pokemon.turnData.statStagesDecreased = true; + } + + pokemon.setStatStage(s, pokemon.getStatStage(s) + this.stagesHolder.value); + } + + if (this.stagesHolder.value > 0 && this.canBeCopied) { + for (const opponent of pokemon.getOpponents()) { + applyAbAttrs(StatStageChangeCopyAbAttr, opponent, null, false, this.stats, this.stagesHolder.value); } } - while ((existingPhase = (this.scene.findPhase(p => p instanceof StatStageChangePhase && p.battlerIndex === this.battlerIndex && p.selfTarget === this.selfTarget - && (accEva.some(s => p.stats.includes(s)) === isAccEva) - && p.stages === this.stages && p.showMessage === this.showMessage && p.ignoreAbilities === this.ignoreAbilities) as StatStageChangePhase))) { - this.stats.push(...existingPhase.stats); - if (!this.scene.tryRemovePhase(p => p === existingPhase)) { - break; + + applyPostStatStageChangeAbAttrs(PostStatStageChangeAbAttr, pokemon, this.filteredStats, this.stages, this.selfTarget); + + // Look for any other stat change phases; if this is the last one, do White Herb check + const existingPhase = this.scene.findPhase(p => p instanceof StatStageChangePhase && p.battlerIndex === this.battlerIndex); + if (!(existingPhase instanceof StatStageChangePhase)) { + // Apply White Herb if needed + const whiteHerb = this.scene.applyModifier(ResetNegativeStatStageModifier, this.isPlayer, pokemon) as ResetNegativeStatStageModifier; + // If the White Herb was applied, consume it + if (whiteHerb) { + whiteHerb.stackCount--; + if (whiteHerb.stackCount <= 0) { + this.scene.removeModifier(whiteHerb); + } + this.scene.updateModifiers(this.isPlayer); } } + + pokemon.updateInfo(); + + handleTutorial(this.scene, Tutorial.Stat_Change).then(() => super.end()); } - getStatStageChangeMessages(stats: BattleStat[], stages: integer, relStages: integer[]): string[] { + protected getStatStageChangeMessages(stats: BattleStat[], stages: number, relStages: number[]): string[] { const messages: string[] = []; const relStageStatIndexes = {}; diff --git a/src/test/battlerTags/stockpiling.test.ts b/src/test/battlerTags/stockpiling.test.ts index dab189853c5..b09103fb442 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 { beforeEach, describe, expect, it, vi } from "vitest"; -import Pokemon, { PokemonSummonData } from "#app/field/pokemon"; import { StockpilingTag } from "#app/data/battler-tags"; -import { Stat } from "#enums/stat"; +import Pokemon, { PokemonSummonData } from "#app/field/pokemon"; import * as messages from "#app/messages"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; +import { Stat } from "#enums/stat"; +import { beforeEach, describe, expect, it, vi } from "vitest"; beforeEach(() => { vi.spyOn(messages, "getPokemonNameWithAffix").mockImplementation(() => ""); @@ -27,7 +27,7 @@ describe("BattlerTag - StockpilingTag", () => { expect((phase as StatStageChangePhase)["stages"]).toEqual(1); expect((phase as StatStageChangePhase)["stats"]).toEqual(expect.arrayContaining([ Stat.DEF, Stat.SPDEF ])); - (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.DEF, Stat.SPDEF ], [ 1, 1 ]); + (phase as StatStageChangePhase)["onChange"]!([ Stat.DEF, Stat.SPDEF ], [ 1, 1 ], mockPokemon); }); subject.onAdd(mockPokemon); @@ -54,7 +54,7 @@ describe("BattlerTag - StockpilingTag", () => { expect((phase as StatStageChangePhase)["stages"]).toEqual(1); expect((phase as StatStageChangePhase)["stats"]).toEqual(expect.arrayContaining([ Stat.DEF, Stat.SPDEF ])); - (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.DEF, Stat.SPDEF ], [ 1, 1 ]); + (phase as StatStageChangePhase)["onChange"]!([ Stat.DEF, Stat.SPDEF ], [ 1, 1 ], mockPokemon); }); subject.onAdd(mockPokemon); @@ -79,7 +79,7 @@ describe("BattlerTag - StockpilingTag", () => { expect((phase as StatStageChangePhase)["stages"]).toEqual(1); expect((phase as StatStageChangePhase)["stats"]).toEqual(expect.arrayContaining([ Stat.DEF, Stat.SPDEF ])); - (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.DEF, Stat.SPDEF ], [ 1, 1 ]); + (phase as StatStageChangePhase)["onChange"]!([ Stat.DEF, Stat.SPDEF ], [ 1, 1 ], mockPokemon); }); subject.onOverlap(mockPokemon); @@ -109,7 +109,7 @@ describe("BattlerTag - StockpilingTag", () => { expect((phase as StatStageChangePhase)["stats"]).toEqual(expect.arrayContaining([ Stat.DEF, Stat.SPDEF ])); // def doesn't change - (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.SPDEF ], [ 1 ]); + (phase as StatStageChangePhase)["onChange"]!([ Stat.SPDEF ], [ 1 ], mockPokemon); }); subject.onAdd(mockPokemon); @@ -121,7 +121,7 @@ describe("BattlerTag - StockpilingTag", () => { expect((phase as StatStageChangePhase)["stats"]).toEqual(expect.arrayContaining([ Stat.DEF, Stat.SPDEF ])); // def doesn't change - (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.SPDEF ], [ 1 ]); + (phase as StatStageChangePhase)["onChange"]!([ Stat.SPDEF ], [ 1 ], mockPokemon); }); subject.onOverlap(mockPokemon);