diff --git a/src/data/ability.ts b/src/data/ability.ts index 0e7cfc4d33d..519e2411612 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1823,22 +1823,29 @@ export class MultCritAbAttr extends AbAttr { } /** - * Attribute used by Merciless - * Guarantees a critical hit if the target is poisoned, except if target prevents critical hits. + * Guarantees a critical hit according to the given condition, except if target prevents critical hits. ie. Merciless + * @extends AbAttr + * @see {@linkcode apply} */ -export class CritIfTargetPoisonedAbAttr extends AbAttr { +export class ConditionalCritAbAttr extends AbAttr { + private condition: PokemonAttackCondition; + + constructor(condition: PokemonAttackCondition, checkUser?: Boolean) { + super(); + + this.condition = condition; + } + /** - * Multiplies the base additional effect chance by the given multiplier. - * @param {Pokemon} pokemon N/A - * @param {boolean} passive N/A - * @param {cancelled} cancelled N/A - * @param {any[]} args args[0]: BooleanHolder, If true critical hit is guaranteed. args[1]: Target Pokémon. - * @returns {boolean} true if function succeeds. + * @param pokemon {@linkcode Pokemon} user. + * @param args [0] {@linkcode Utils.BooleanHolder} If true critical hit is guaranteed. + * [1] {@linkcode Pokemon} Target. + * [2] {@linkcode Move} used by ability user. */ apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { const target = (args[1] as Pokemon); - if(target.status) - if(!(target.status.effect === StatusEffect.TOXIC || target.status.effect === StatusEffect.POISON)) + const move = (args[2] as Move); + if(!this.condition(pokemon,target,move)) return false; (args[0] as Utils.BooleanHolder).value = true; @@ -3465,7 +3472,7 @@ export function initAbilities() { new Ability(Abilities.WATER_COMPACTION, 7) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.type === Type.WATER && move.category !== MoveCategory.STATUS, BattleStat.DEF, 2), new Ability(Abilities.MERCILESS, 7) - .attr(CritIfTargetPoisonedAbAttr), + .attr(ConditionalCritAbAttr, (user, target, move) => target.status?.effect === StatusEffect.TOXIC || target.status?.effect === StatusEffect.POISON), new Ability(Abilities.SHIELDS_DOWN, 7) .attr(PostBattleInitFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) .attr(PostSummonFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index b733f6d2ebf..57ee798967e 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -27,7 +27,7 @@ import { TempBattleStat } from '../data/temp-battle-stat'; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, CritIfTargetPoisonedAbAttr } from '../data/ability'; +import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr } from '../data/ability'; import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; import Battle, { BattlerIndex } from '../battle'; @@ -1490,7 +1490,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const critOnly = new Utils.BooleanHolder(false); const critAlways = source.getTag(BattlerTagType.ALWAYS_CRIT); applyMoveAttrs(CritOnlyAttr, source, this, move, critOnly); - applyAbAttrs(CritIfTargetPoisonedAbAttr, source, null, critOnly, this); + applyAbAttrs(ConditionalCritAbAttr, source, null, critOnly, this, move); if (critOnly.value || critAlways) isCritical = true; else {