From d85c1ce5dbe4d94c51003d969de105f7c27234a2 Mon Sep 17 00:00:00 2001 From: Dean Date: Sat, 1 Feb 2025 17:02:25 -0800 Subject: [PATCH] Partially implement postAttack --- src/data/ability.ts | 59 ++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 0669446e5a4..4d35a995ccc 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1604,24 +1604,17 @@ export class PostAttackAbAttr extends AbAttr { } /** - * Please override {@link applyPostAttackAfterMoveTypeCheck} instead of this method. By default, this method checks that the move used is a damaging attack before + * By default, this method checks that the move used is a damaging attack before * applying the effect of any inherited class. This can be changed by providing a different {@link attackCondition} to the constructor. See {@link ConfusionOnStatusEffectAbAttr} * for an example of an effect that does not require a damaging move. */ - applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise { + willSucceedPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { // When attackRequired is true, we require the move to be an attack move and to deal damage before checking secondary requirements. // If attackRequired is false, we always defer to the secondary requirements. - if (this.attackCondition(pokemon, defender, move)) { - return this.applyPostAttackAfterMoveTypeCheck(pokemon, passive, simulated, defender, move, hitResult, args); - } else { - return false; - } + return this.attackCondition(pokemon, defender, move); } - /** - * This method is only called after {@link applyPostAttack} has already been applied. Use this for handling checks specific to the ability in question. - */ - applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise { + applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise { return false; } } @@ -1635,6 +1628,10 @@ export class GorillaTacticsAbAttr extends PostAttackAbAttr { super((user, target, move) => true, false); } + willSucceedPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return simulated || !pokemon.getTag(BattlerTagType.GORILLA_TACTICS); + } + /** * * @param {Pokemon} pokemon the {@linkcode Pokemon} with this ability @@ -1646,15 +1643,11 @@ export class GorillaTacticsAbAttr extends PostAttackAbAttr { * @param args n/a * @returns `true` if the ability is applied */ - applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise { + applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise { if (simulated) { return simulated; } - if (pokemon.getTag(BattlerTagType.GORILLA_TACTICS)) { - return false; - } - pokemon.addTag(BattlerTagType.GORILLA_TACTICS); return true; } @@ -1669,7 +1662,11 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { this.stealCondition = stealCondition ?? null; } - applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise { + willSucceedPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return super.willSucceedPostAttack(pokemon, passive, simulated, defender, move, hitResult, args); // && SUCCESS CHECK + } + + applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise { return new Promise(resolve => { if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.stealCondition || this.stealCondition(pokemon, defender, move))) { const heldItems = this.getTargetHeldItems(defender).filter(i => i.isTransferable); @@ -1707,18 +1704,23 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { this.effects = effects; } - applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (pokemon !== attacker && move.hitsSubstitute(attacker, pokemon)) { - return false; - } - - /**Status inflicted by abilities post attacking are also considered additional effects.*/ - if (!attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && !simulated && pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) { + willSucceedPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + if ( + super.willSucceedPostAttack(pokemon, passive, simulated, attacker, move, hitResult, args) + && !(pokemon !== attacker && move.hitsSubstitute(attacker, pokemon)) + && (simulated || !attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && pokemon !== attacker + && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) + ) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; - return attacker.trySetStatus(effect, true, pokemon); + return simulated || attacker.canSetStatus(effect, true, false, pokemon); } - return simulated; + return false; + } + + applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + return attacker.trySetStatus(effect, true, pokemon); } } @@ -2826,6 +2828,8 @@ export class ConfusionOnStatusEffectAbAttr extends PostAttackAbAttr { super((user, target, move) => true); this.effects = effects; } + + /** * Applies confusion to the target pokemon. * @param pokemon {@link Pokemon} attacking @@ -5258,7 +5262,8 @@ export function applyPreAttackAbAttrs(attrType: Constructor, export function applyPostAttackAbAttrs(attrType: Constructor, pokemon: Pokemon, defender: Pokemon, move: Move, hitResult: HitResult | null, simulated: boolean = false, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args), args, false, simulated); + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args), + (attr, passive) => attr.willSucceedPostAttack(pokemon, passive, simulated, defender, move, hitResult, args), args, false, simulated); } export function applyPostKnockOutAbAttrs(attrType: Constructor,