From e6fd3319319da03c3e47105f0019dead3602a173 Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Sun, 5 May 2024 16:37:43 -0500 Subject: [PATCH] Fix HalfSacrificialAttr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mind Blown targets all users and was triggering recoil every time it hit. Changed so that it only applies once after all targets take damage by adding a new MoveEffectTrigger, POST_TARGET. This also fixes an issue where dying to recoil stopped the rest of the damage from hitting the remaining targets. This change also applies fixes for Steel Beam since they are have the same effect but is single target. Also added missing messages for Damp and Recoil. All messaging is in line with Pokémon Showdown. --- src/data/move.ts | 23 +++++++++++++++++++++-- src/phases.ts | 3 +++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index fa2401e61..480740007 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -447,7 +447,9 @@ export abstract class MoveAttr { export enum MoveEffectTrigger { PRE_APPLY, POST_APPLY, - HIT + HIT, + /** Triggers one time after all target effects have applied */ + POST_TARGET, } export class MoveEffectAttr extends MoveAttr { @@ -740,19 +742,33 @@ export class SacrificialAttr extends MoveEffectAttr { } } +/** + * Attribute used for moves which cut the user's Max HP in half. + * Triggers using POST_TARGET. + */ export class HalfSacrificialAttr extends MoveEffectAttr { constructor() { - super(true, MoveEffectTrigger.PRE_APPLY); + super(true, MoveEffectTrigger.POST_TARGET); } + /** + * Cut's the user's Max HP in half and displays the appropriate recoil message + * @param user Pokemon that used the move + * @param target N/A + * @param move Move with this attribute + * @param args N/A + * @returns true if the function succeeds + */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { if (!super.apply(user, target, move, args)) return false; const cancelled = new Utils.BooleanHolder(false); + // Check to see if the Pokemon has an ability that blocks non-direct damage applyAbAttrs(BlockNonDirectDamageAbAttr, user, cancelled); if (!cancelled.value){ user.damageAndUpdate(Math.ceil(user.getMaxHp()/2), HitResult.OTHER, false, true, true); + user.scene.queueMessage(getPokemonMessage(user, ' cut its own HP to power up its move!')); // Queue recoil message } return true; } @@ -3805,6 +3821,9 @@ const failOnMaxCondition: MoveConditionFunc = (user, target, move) => !target.is const failIfDampCondition: MoveConditionFunc = (user, target, move) => { const cancelled = new Utils.BooleanHolder(false); user.scene.getField(true).map(p=>applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled)); + // Queue a message if an ability prevented usage of the move + if (cancelled.value) + user.scene.queueMessage(getPokemonMessage(user, ` cannot use ${move.name}!`)); return !cancelled.value; } diff --git a/src/phases.ts b/src/phases.ts index 6e329bda6..751cac166 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2494,6 +2494,9 @@ export class MoveEffectPhase extends PokemonPhase { }); })); } + // Trigger effect which should only apply one time after all targeted effects have already applied + applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.POST_TARGET, + user, null, this.move.getMove()) Promise.allSettled(applyAttrs).then(() => this.end()); }); });