From 4012c9a89ef9c137ecd1f0feea78ee6047ec41a8 Mon Sep 17 00:00:00 2001 From: Christopher Schmidt Date: Tue, 18 Feb 2025 23:00:12 -0500 Subject: [PATCH] Refactors implementation per Wlowscha's suggestions: removes damageSources array and preventEndure variable --- src/data/ability.ts | 2 +- src/data/battler-tags.ts | 4 ++-- src/data/move.ts | 16 ++++++++-------- src/field/pokemon.ts | 26 +++++++++++--------------- src/modifier/modifier.ts | 6 +----- src/phases/weather-effect-phase.ts | 2 +- src/test/items/reviver_seed.test.ts | 3 --- 7 files changed, 24 insertions(+), 35 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index bf3b04e1f63..247902b3dc0 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -4659,7 +4659,7 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr { (args[0] as Utils.NumberHolder).value = this.multiplier; pokemon.removeTag(this.tagType); if (this.recoilDamageFunc) { - pokemon.damageAndUpdate(this.recoilDamageFunc(pokemon), HitResult.OTHER, false, false, true, true); + pokemon.damageAndUpdate(this.recoilDamageFunc(pokemon), HitResult.OTHER, false, true, true); } } return true; diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index cef75e7908e..7c769ee7af7 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -723,7 +723,7 @@ export class DestinyBondTag extends BattlerTag { pokemonNameWithAffix2: getPokemonNameWithAffix(pokemon) }) ); - pokemon.damageAndUpdate(pokemon.hp, HitResult.OTHER, false, false, true); + pokemon.damageAndUpdate(pokemon.hp, HitResult.OTHER, false, true); return false; } } @@ -1613,7 +1613,7 @@ export class PerishSongTag extends BattlerTag { }) ); } else { - pokemon.damageAndUpdate(pokemon.hp, HitResult.ONE_HIT_KO, false, true, true); + pokemon.damageAndUpdate(pokemon.hp, HitResult.ONE_HIT_KO, false, true); } return ret; diff --git a/src/data/move.ts b/src/data/move.ts index 016dae6ab0d..4a8973e2979 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1568,7 +1568,7 @@ export class RecoilAttr extends MoveEffectAttr { return false; } - user.damageAndUpdate(recoilDamage, HitResult.OTHER, false, true, true); + user.damageAndUpdate(recoilDamage, HitResult.OTHER, false, true); globalScene.queueMessage(i18next.t("moveTriggers:hitWithRecoil", { pokemonName: getPokemonNameWithAffix(user) })); user.turnData.damageTaken += recoilDamage; @@ -1600,7 +1600,7 @@ export class SacrificialAttr extends MoveEffectAttr { * @returns true if the function succeeds **/ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - user.damageAndUpdate(user.hp, HitResult.OTHER, false, true, true); + user.damageAndUpdate(user.hp, HitResult.OTHER, false, true); user.turnData.damageTaken += user.hp; return true; @@ -1638,7 +1638,7 @@ export class SacrificialAttrOnHit extends MoveEffectAttr { return false; } - user.damageAndUpdate(user.hp, HitResult.OTHER, false, true, true); + user.damageAndUpdate(user.hp, HitResult.OTHER, false, true); user.turnData.damageTaken += user.hp; return true; @@ -1680,7 +1680,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(Utils.toDmgValue(user.getMaxHp() / 2), HitResult.OTHER, false, true); globalScene.queueMessage(i18next.t("moveTriggers:cutHpPowerUpMove", { pokemonName: getPokemonNameWithAffix(user) })); // Queue recoil message } return true; @@ -1723,7 +1723,7 @@ export class AddSubstituteAttr extends MoveEffectAttr { return false; } - user.damageAndUpdate(Math.floor(user.getMaxHp() * this.hpCost), HitResult.OTHER, false, true, true); + user.damageAndUpdate(Math.floor(user.getMaxHp() * this.hpCost), HitResult.OTHER, false, true); user.addTag(BattlerTagType.SUBSTITUTE, 0, move.id, user.id); return true; } @@ -3326,7 +3326,7 @@ export class CutHpStatStageBoostAttr extends StatStageChangeAttr { 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(Utils.toDmgValue(user.getMaxHp() / this.cutRatio), HitResult.OTHER, false); user.updateInfo().then(() => { const ret = super.apply(user, target, move, args); if (this.messageCallback) { @@ -5236,7 +5236,7 @@ const crashDamageFunc = (user: Pokemon, move: Move) => { return false; } - user.damageAndUpdate(Utils.toDmgValue(user.getMaxHp() / 2), HitResult.OTHER, false, true); + user.damageAndUpdate(Utils.toDmgValue(user.getMaxHp() / 2), HitResult.OTHER, false); globalScene.queueMessage(i18next.t("moveTriggers:keptGoingAndCrashed", { pokemonName: getPokemonNameWithAffix(user) })); user.turnData.damageTaken += Utils.toDmgValue(user.getMaxHp() / 2); @@ -5532,7 +5532,7 @@ export class CurseAttr extends MoveEffectAttr { return false; } const curseRecoilDamage = Math.max(1, Math.floor(user.getMaxHp() / 2)); - user.damageAndUpdate(curseRecoilDamage, HitResult.OTHER, false, true, true); + user.damageAndUpdate(curseRecoilDamage, HitResult.OTHER, false, true); globalScene.queueMessage( i18next.t("battlerTags:cursedOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(user), diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index f20e3dd937f..ecd7405136f 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -3014,8 +3014,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const destinyTag = this.getTag(BattlerTagType.DESTINY_BOND); const grudgeTag = this.getTag(BattlerTagType.GRUDGE); - const isOneHitKo = result === HitResult.ONE_HIT_KO; - if (dmg) { this.lapseTags(BattlerTagLapseType.HIT); @@ -3032,7 +3030,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * We explicitly require to ignore the faint phase here, as we want to show the messages * about the critical hit and the super effective/not very effective messages before the faint phase. */ - const damage = this.damageAndUpdate(isBlockedBySubstitute ? 0 : dmg, result as DamageResult, isCritical, isOneHitKo, false, true, source); + const damage = this.damageAndUpdate(isBlockedBySubstitute ? 0 : dmg, result as DamageResult, isCritical, false, true, source); if (damage > 0) { if (source.isPlayer()) { @@ -3101,7 +3099,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } const surviveDamage = new Utils.BooleanHolder(false); - if (!preventEndure && this.hp - damage <= 0 && this.turnData?.damageSources?.at(0) !== HitResult.OTHER) { + if (!preventEndure && this.hp - damage <= 0) { if (this.hp >= 1 && this.getTag(BattlerTagType.ENDURING)) { surviveDamage.value = this.lapseTag(BattlerTagType.ENDURING); } else if (this.hp > 1 && this.getTag(BattlerTagType.STURDY)) { @@ -3128,7 +3126,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * Once the MoveEffectPhase is over (and calls it's .end() function, shiftPhase() will reset the PhaseQueueSplice via clearPhaseQueueSplice() ) */ globalScene.setPhaseQueueSplice(); - globalScene.unshiftPhase(new FaintPhase(this.getBattlerIndex())); + globalScene.unshiftPhase(new FaintPhase(this.getBattlerIndex(), preventEndure)); this.destroySubstitute(); this.lapseTag(BattlerTagType.COMMANDED); this.resetSummonData(); @@ -3146,19 +3144,21 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param ignoreFaintPhase boolean to ignore adding a FaintPhase, passsed to damage() * @returns integer of damage done */ - damageAndUpdate(damage: number, result?: DamageResult, critical: boolean = false, ignoreSegments: boolean = false, preventEndure: boolean = false, ignoreFaintPhase: boolean = false, source?: Pokemon): number { - // When damage is done from any source (Move or Indirect damage, e.g. weather), store latest occurrence in damageSources[0] + damageAndUpdate(damage: number, result?: DamageResult, critical: boolean = false, ignoreSegments: boolean = false, ignoreFaintPhase: boolean = false, source?: Pokemon): number { + let isIndirectDamage: boolean = true; if (result !== undefined) { - this.turnData?.damageSources?.unshift(result); - } else { - this.turnData?.damageSources?.unshift(HitResult.OTHER); + if (result === HitResult.OTHER) { + isIndirectDamage = true; + } else { + isIndirectDamage = false; + } } const damagePhase = new DamageAnimPhase(this.getBattlerIndex(), damage, result as DamageResult, critical); globalScene.unshiftPhase(damagePhase); if (this.switchOutStatus && source) { damage = 0; } - damage = this.damage(damage, ignoreSegments, preventEndure, ignoreFaintPhase); + damage = this.damage(damage, ignoreSegments, isIndirectDamage, ignoreFaintPhase); // Damage amount may have changed, but needed to be queued before calling damage function damagePhase.updateAmount(damage); /** @@ -5464,10 +5464,6 @@ export class PokemonTurnData { * forced to act again in the same turn */ public extraTurns: number = 0; - /** - * Used to track damage sources from HitResult.OTHER - */ - public damageSources: DamageResult[] = []; } export enum AiType { diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 4a9f97ddde6..f6bc62fb5d3 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -5,7 +5,7 @@ import { allMoves } from "#app/data/move"; import { MAX_PER_TYPE_POKEBALLS } from "#app/data/pokeball"; import { type FormChangeItem, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms"; import { getStatusEffectHealText } from "#app/data/status-effect"; -import Pokemon, { HitResult, type PlayerPokemon } from "#app/field/pokemon"; +import Pokemon, { type PlayerPokemon } from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; import Overrides from "#app/overrides"; import { EvolutionPhase } from "#app/phases/evolution-phase"; @@ -1860,10 +1860,6 @@ export class PokemonInstantReviveModifier extends PokemonHeldItemModifier { * @returns always `true` */ override apply(pokemon: Pokemon): boolean { - // Do not revive if damage is indirect - if (pokemon.turnData?.damageSources?.at(0) === HitResult.OTHER) { - return false; - } // Restore the Pokemon to half HP globalScene.unshiftPhase(new PokemonHealPhase(pokemon.getBattlerIndex(), toDmgValue(pokemon.getMaxHp() / 2), i18next.t("modifier:pokemonInstantReviveApply", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), typeName: this.type.name }), false, false, true)); diff --git a/src/phases/weather-effect-phase.ts b/src/phases/weather-effect-phase.ts index ae5fd07b56a..e5915837f9f 100644 --- a/src/phases/weather-effect-phase.ts +++ b/src/phases/weather-effect-phase.ts @@ -49,7 +49,7 @@ export class WeatherEffectPhase extends CommonAnimPhase { const damage = Utils.toDmgValue(pokemon.getMaxHp() / 16); globalScene.queueMessage(getWeatherDamageMessage(this.weather?.weatherType!, pokemon)!); // TODO: are those bangs correct? - pokemon.damageAndUpdate(damage, HitResult.OTHER, false, false, true); + pokemon.damageAndUpdate(damage, HitResult.OTHER, false, true); }; this.executeForAll((pokemon: Pokemon) => { diff --git a/src/test/items/reviver_seed.test.ts b/src/test/items/reviver_seed.test.ts index 2a1182a9005..131da53b40c 100644 --- a/src/test/items/reviver_seed.test.ts +++ b/src/test/items/reviver_seed.test.ts @@ -63,7 +63,6 @@ describe("Items - Reviver Seed", () => { game.move.select(Moves.TACKLE); await game.phaseInterceptor.to("BerryPhase"); - expect(reviverSeed.apply).toHaveReturnedWith(true); // Reviver Seed triggers expect(player.isFainted()).toBeFalsy(); }); @@ -84,7 +83,6 @@ describe("Items - Reviver Seed", () => { game.move.select(Moves.TACKLE); await game.phaseInterceptor.to("BerryPhase"); - expect(reviverSeed.apply).toHaveReturnedWith(true); // Reviver Seed triggers expect(player.isFainted()).toBeFalsy(); }); @@ -136,7 +134,6 @@ describe("Items - Reviver Seed", () => { game.move.select(move); await game.phaseInterceptor.to("TurnEndPhase"); - expect(playerSeed.apply).toHaveReturnedWith(false); // Reviver Seed triggers expect(player.isFainted()).toBeTruthy(); });