diff --git a/src/data/ability.ts b/src/data/ability.ts index d09bb2eba..6c00f86d5 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1558,6 +1558,35 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr { } } +export class PostFaintAbAttr extends AbAttr { + applyPostFaint(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + return false; + } +} + +export class PostFaintContactDamageAbAttr extends PostFaintAbAttr { + private damageRatio: integer; + + constructor(damageRatio: integer) { + super(); + + this.damageRatio = damageRatio; + } + + applyPostFaint(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { + attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); + return true; + } + + return false; + } + + getTriggerMessage(pokemon: Pokemon, ...args: any[]): string { + return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name} hurt\nits attacker!`); + } +} + export class RedirectMoveAbAttr extends AbAttr { apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (this.canRedirect(args[0] as Moves)) { @@ -1860,6 +1889,11 @@ export function applyPostBattleAbAttrs(attrType: { new(...args: any[]): PostBatt return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostBattle(pokemon, args), args); } +export function applyPostFaintAbAttrs(attrType: { new(...args: any[]): PostFaintAbAttr }, + pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, attr => attr.applyPostFaint(pokemon, attacker, move, hitResult, args), args); +} + function canApplyAttr(pokemon: Pokemon, attr: AbAttr): boolean { const condition = attr.getCondition(); return !condition || condition(pokemon); @@ -2250,7 +2284,8 @@ export function initAbilities() { .attr(ArenaTrapAbAttr), new Ability(Abilities.ROUGH_SKIN, "Rough Skin", "This Pokémon inflicts damage with its rough skin to the attacker on contact.", 3) .attr(PostDefendContactDamageAbAttr, 8) - .ignorable(), + .ignorable() + .passive(), new Ability(Abilities.WONDER_GUARD, "Wonder Guard", "Its mysterious power only lets supereffective moves hit the Pokémon.", 3) .attr(NonSuperEffectiveImmunityAbAttr) .attr(ProtectAbilityAbAttr) @@ -2439,7 +2474,9 @@ export function initAbilities() { .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, ' breaks the mold!')) .attr(MoveAbilityBypassAbAttr), new Ability(Abilities.SUPER_LUCK, "Super Luck (N)", "The Pokémon is so lucky that the critical-hit ratios of its moves are boosted.", 4), - new Ability(Abilities.AFTERMATH, "Aftermath (N)", "Damages the attacker if it contacts the Pokémon with a finishing hit.", 4), + new Ability(Abilities.AFTERMATH, "Aftermath", "Damages the attacker if it contacts the Pokémon with a finishing hit.", 4) + .attr(PostFaintContactDamageAbAttr,4) + .passive(), new Ability(Abilities.ANTICIPATION, "Anticipation (N)", "The Pokémon can sense an opposing Pokémon's dangerous moves.", 4), new Ability(Abilities.FOREWARN, "Forewarn (N)", "When it enters a battle, the Pokémon can tell one of the moves an opposing Pokémon has.", 4), new Ability(Abilities.UNAWARE, "Unaware", "When attacking, the Pokémon ignores the target Pokémon's stat changes.", 4) @@ -2558,7 +2595,8 @@ export function initAbilities() { .attr(BlockWeatherDamageAttr, WeatherType.SANDSTORM) .condition(getWeatherCondition(WeatherType.SANDSTORM)), new Ability(Abilities.IRON_BARBS, "Iron Barbs", "Inflicts damage on the attacker upon contact with iron barbs.", 5) - .attr(PostDefendContactDamageAbAttr, 8), + .attr(PostDefendContactDamageAbAttr, 8) + .passive(), new Ability(Abilities.ZEN_MODE, "Zen Mode", "Changes the Pokémon's shape when HP is half or less.", 5) .attr(PostBattleInitFormChangeAbAttr, p => p.getHpRatio() >= 0.5 ? 0 : 1) .attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() >= 0.5 ? 0 : 1) diff --git a/src/phases.ts b/src/phases.ts index f768a1186..489a8c768 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get import { TempBattleStat } from "./data/temp-battle-stat"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; import { ArenaTagType } from "./data/enums/arena-tag-type"; -import { Abilities, CheckTrappedAbAttr, MoveAbilityBypassAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr } from "./data/ability"; +import { Abilities, CheckTrappedAbAttr, MoveAbilityBypassAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr } from "./data/ability"; import { Unlockables, getUnlockableName } from "./system/unlockables"; import { getBiomeKey } from "./field/arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; @@ -2876,6 +2876,13 @@ export class FaintPhase extends PokemonPhase { this.scene.queueMessage(getPokemonMessage(pokemon, ' fainted!'), null, true); + if (pokemon.getAbility().hasAttr(PostFaintAbAttr)) { + if (pokemon.turnData?.attacksReceived?.length) { + const lastAttack = pokemon.turnData.attacksReceived[0]; + applyPostFaintAbAttrs(PostFaintAbAttr,pokemon, this.scene.getPokemonById(lastAttack.sourceId), new PokemonMove(lastAttack.move), lastAttack.result); + } + } + const alivePlayField = this.scene.getField(true); alivePlayField.forEach(p => applyPostKnockOutAbAttrs(PostKnockOutAbAttr, p)); if (pokemon.turnData?.attacksReceived?.length) {