From 97ed62d5d7f7d9fc032ca93e606f9c906fcb1bda Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Thu, 17 Apr 2025 16:25:26 -0500 Subject: [PATCH] Remove hitsSubstitute check from postDefend abilities --- src/data/abilities/ability.ts | 42 +++++++++++++++------------------ src/phases/move-effect-phase.ts | 2 -- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index d2cc93ed02b..53d024ac655 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -653,8 +653,8 @@ export class MoveImmunityStatStageChangeAbAttr extends MoveImmunityAbAttr { */ export class ReverseDrainAbAttr extends PostDefendAbAttr { - override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { - return move.hasAttr(HitHealAttr) && !move.hitsSubstitute(attacker, pokemon); + override canApplyPostDefend(_pokemon: Pokemon, _passive: boolean, _simulated: boolean, _attacker: Pokemon, move: Move, _hitResult: HitResult | null, args: any[]): boolean { + return move.hasAttr(HitHealAttr); } /** @@ -693,7 +693,7 @@ export class PostDefendStatStageChangeAbAttr extends PostDefendAbAttr { } override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { - return this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon); + return this.condition(pokemon, attacker, move); } override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { @@ -734,7 +734,7 @@ export class PostDefendHpGatedStatStageChangeAbAttr extends PostDefendAbAttr { const hpGateFlat: number = Math.ceil(pokemon.getMaxHp() * this.hpGate); const lastAttackReceived = pokemon.turnData.attacksReceived[pokemon.turnData.attacksReceived.length - 1]; const damageReceived = lastAttackReceived?.damage || 0; - return this.condition(pokemon, attacker, move) && (pokemon.hp <= hpGateFlat && (pokemon.hp + damageReceived) > hpGateFlat) && !move.hitsSubstitute(attacker, pokemon); + return this.condition(pokemon, attacker, move) && (pokemon.hp <= hpGateFlat && (pokemon.hp + damageReceived) > hpGateFlat); } override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { @@ -757,7 +757,7 @@ export class PostDefendApplyArenaTrapTagAbAttr extends PostDefendAbAttr { override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { const tag = globalScene.arena.getTag(this.tagType) as ArenaTrapTag; - return (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) + return (this.condition(pokemon, attacker, move)) && (!globalScene.arena.getTag(this.tagType) || tag.layers < tag.maxLayers); } @@ -779,7 +779,7 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr { } override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { - return this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon); + return this.condition(pokemon, attacker, move); } override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { @@ -796,7 +796,7 @@ export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr { override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { this.type = attacker.getMoveType(move); const pokemonTypes = pokemon.getTypes(true); - return hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon) && (simulated || pokemonTypes.length !== 1 || pokemonTypes[0] !== this.type); + return hitResult < HitResult.NO_EFFECT && (simulated || pokemonTypes.length !== 1 || pokemonTypes[0] !== this.type); } override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): void { @@ -823,7 +823,7 @@ export class PostDefendTerrainChangeAbAttr extends PostDefendAbAttr { } override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - return hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon) && globalScene.arena.canSetTerrain(this.terrainType); + return hitResult < HitResult.NO_EFFECT && globalScene.arena.canSetTerrain(this.terrainType); } override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): void { @@ -847,7 +847,7 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; return move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && !attacker.status - && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && !move.hitsSubstitute(attacker, pokemon) + && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && attacker.canSetStatus(effect, true, false, pokemon); } @@ -887,7 +887,7 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr { override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { return move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && pokemon.randSeedInt(100) < this.chance - && !move.hitsSubstitute(attacker, pokemon) && attacker.canAddTag(this.tagType); + && attacker.canAddTag(this.tagType); } override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { @@ -908,10 +908,6 @@ export class PostDefendCritStatStageChangeAbAttr extends PostDefendAbAttr { this.stages = stages; } - override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { - return !move.hitsSubstitute(attacker, pokemon); - } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { if (!simulated) { globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ this.stat ], this.stages)); @@ -934,7 +930,7 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr { override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { return !simulated && move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) - && !attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr) && !move.hitsSubstitute(attacker, pokemon); + && !attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr); } override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { @@ -993,7 +989,7 @@ export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr { } override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { - return (!(this.condition && !this.condition(pokemon, attacker, move) || move.hitsSubstitute(attacker, pokemon)) + return (!(this.condition && !this.condition(pokemon, attacker, move)) && !globalScene.arena.weather?.isImmutable() && globalScene.arena.canSetWeather(this.weatherType)); } @@ -1011,7 +1007,7 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr { override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { return move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) - && attacker.getAbility().isSwappable && !move.hitsSubstitute(attacker, pokemon); + && attacker.getAbility().isSwappable; } override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, args: any[]): void { @@ -1037,10 +1033,10 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr { override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { return move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && attacker.getAbility().isSuppressable - && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr) && !move.hitsSubstitute(attacker, pokemon); + && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr); } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { + override applyPostDefend(_pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { if (!simulated) { attacker.setTempAbility(allAbilities[this.ability]); } @@ -1066,7 +1062,7 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr { } override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { - return attacker.getTag(BattlerTagType.DISABLED) === null && !move.hitsSubstitute(attacker, pokemon) + return attacker.getTag(BattlerTagType.DISABLED) === null && move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance); } @@ -1770,7 +1766,6 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { override canApplyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { if ( super.canApplyPostAttack(pokemon, passive, simulated, attacker, move, hitResult, args) - && !(pokemon !== attacker && move.hitsSubstitute(attacker, pokemon)) && (simulated || !attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && pokemon !== attacker && (!this.contactRequired || move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon})) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) ) { @@ -1837,8 +1832,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { if ( !simulated && hitResult < HitResult.NO_EFFECT && - (!this.condition || this.condition(pokemon, attacker, move)) && - !move.hitsSubstitute(attacker, pokemon) + (!this.condition || this.condition(pokemon, attacker, move)) ) { const heldItems = this.getTargetHeldItems(attacker).filter((i) => i.isTransferable); if (heldItems.length) { @@ -5063,6 +5057,8 @@ export class PostSummonStatStageChangeOnArenaAbAttr extends PostSummonStatStageC /** * Takes no damage from the first hit of a damaging move. * This is used in the Disguise and Ice Face abilities. + * + * Does not apply to a user's substitute * @extends ReceivedMoveDamageMultiplierAbAttr */ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr { diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index a0906c97610..49691b6d5d1 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -13,7 +13,6 @@ import { PostDamageAbAttr, PostDefendAbAttr, ReflectStatusMoveAbAttr, - TypeImmunityAbAttr, } from "#app/data/abilities/ability"; import { ArenaTagSide, ConditionalProtectTag } from "#app/data/arena-tag"; import { MoveAnim } from "#app/data/battle-anims"; @@ -25,7 +24,6 @@ import { SubstituteTag, TypeBoostTag, } from "#app/data/battler-tags"; -import type { BattlerTag } from "#app/data/battler-tags"; import type { MoveAttr } from "#app/data/moves/move"; import { applyFilteredMoveAttrs,