diff --git a/src/data/ability.ts b/src/data/ability.ts index 7cf4c8d0b..3deef28b4 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -131,6 +131,15 @@ export class PreDefendAbAttr extends AbAttr { } } +export class PreDefendEndureAbAttr extends PreDefendAbAttr { + applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (pokemon.getHpRatio() < 1 || (args[0] as Utils.NumberHolder).value < pokemon.hp) + return false; + + return pokemon.addTag(BattlerTagType.ENDURING, 1); + } +} + export class BlockItemTheftAbAttr extends AbAttr { apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; @@ -798,6 +807,13 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { export class BlockCritAbAttr extends AbAttr { } +export class BlockOneHitKOAbAttr extends AbAttr { + apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { + cancelled.value = false; + return true; + } +} + export class IgnoreContactAbAttr extends AbAttr { } export class PreWeatherEffectAbAttr extends AbAttr { @@ -1610,7 +1626,9 @@ export function initAbilities() { .attr(PostTurnStatChangeAbAttr, BattleStat.SPD, 1), new Ability(Abilities.BATTLE_ARMOR, "Battle Armor", "Hard armor protects the Pokémon from critical hits.", 3) .attr(BlockCritAbAttr), - new Ability(Abilities.STURDY, "Sturdy (N)", "It cannot be knocked out with one hit. One-hit KO moves cannot knock it out, either.", 3), + new Ability(Abilities.STURDY, "Sturdy", "It cannot be knocked out with one hit. One-hit KO moves cannot knock it out, either.", 3) + .attr(PreDefendEndureAbAttr) + .attr(BlockOneHitKOAbAttr), new Ability(Abilities.DAMP, "Damp (N)", "Prevents the use of explosive moves, such as Self-Destruct, by dampening its surroundings.", 3), new Ability(Abilities.LIMBER, "Limber", "Its limber body protects the Pokémon from paralysis.", 3) .attr(StatusEffectImmunityAbAttr, StatusEffect.PARALYSIS), diff --git a/src/data/move.ts b/src/data/move.ts index 943b69e32..b09d82142 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -12,7 +12,7 @@ import * as Utils from "../utils"; import { WeatherType } from "./weather"; import { ArenaTagSide, ArenaTrapTag } from "./arena-tag"; import { ArenaTagType } from "./enums/arena-tag-type"; -import { Abilities, ProtectAbilityAbAttr, BlockRecoilDamageAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs } from "./ability"; +import { Abilities, ProtectAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs } from "./ability"; import { PokemonHeldItemModifier } from "../modifier/modifier"; import { BattlerIndex } from "../battle"; import { Stat } from "./pokemon-stat"; @@ -913,7 +913,11 @@ export class OneHitKOAttr extends MoveAttr { } getCondition(): MoveConditionFunc { - return (user, target, move) => user.level >= target.level; + return (user, target, move) => { + const cancelled = new Utils.BooleanHolder(false); + applyAbAttrs(BlockOneHitKOAbAttr, target, cancelled); + return !cancelled && user.level >= target.level; + } } } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 63721d3e6..a248dcf75 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -25,7 +25,7 @@ import { TempBattleStat } from '../data/temp-battle-stat'; import { WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Abilities, Ability, BattleStatMultiplierAbAttr, BlockCritAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from '../data/ability'; +import { Abilities, Ability, BattleStatMultiplierAbAttr, BlockCritAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from '../data/ability'; import PokemonData from '../system/pokemon-data'; import { BattlerIndex } from '../battle'; import { BattleSpec } from "../enums/battle-spec"; @@ -47,7 +47,7 @@ export enum FieldPosition { } const ABILITY_OVERRIDE = Abilities.NONE; -const MOVE_OVERRIDE = Moves.NONE; +const MOVE_OVERRIDE = Moves.NONE;; const OPP_ABILITY_OVERRIDE = Abilities.NONE; const OPP_MOVE_OVERRIDE = Moves.NONE; @@ -1126,6 +1126,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } if (damage) { + applyPreDefendAbAttrs(PreDefendEndureAbAttr, this, source, battlerMove, cancelled, damage); + const oneHitKo = result === HitResult.ONE_HIT_KO; damage.value = this.damageAndUpdate(damage.value, result as DamageResult, isCritical, oneHitKo, oneHitKo); if (isCritical)