From 737ccda398fd7f12b975aa597878d62b1e93db31 Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Wed, 15 May 2024 01:23:06 -0500 Subject: [PATCH] Remove Target Requirement of SacrificialAttr --- src/data/move.ts | 22 ++++------------------ src/phases.ts | 25 ++++++++----------------- 2 files changed, 12 insertions(+), 35 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 6c6bddb9a77..4cbd1d7539c 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -744,7 +744,7 @@ export class RecoilAttr extends MoveEffectAttr { **/ export class SacrificialAttr extends MoveEffectAttr { constructor() { - super(true, MoveEffectTrigger.PRE_APPLY); + super(true, MoveEffectTrigger.POST_TARGET); } /** @@ -757,18 +757,11 @@ export class SacrificialAttr extends MoveEffectAttr { **/ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { user.damageAndUpdate(user.hp, HitResult.OTHER, false, true, true); - user.turnData.damageTaken += user.hp; + user.turnData.damageTaken += user.hp; return true; } - /** - * The AI is calculating how beneficial it is to use this move. Bosses will always return -20. Otherwise, the score is calculated based on the user's current hp ratio and the move's type effectiveness against the user - * @param user Pokemon that used the move - * @param target The target of the move - * @param move Move with this attribute - * @returns The benefit score of using this move (how likely the AI is to use this move) - **/ getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { if (user.isBoss()) return -20; @@ -781,11 +774,11 @@ export class SacrificialAttr extends MoveEffectAttr { **/ export class SacrificialAttrOnHit extends MoveEffectAttr { constructor() { - super(true, MoveEffectTrigger.PRE_APPLY); + super(true, MoveEffectTrigger.POST_TARGET); } /** - * Deals damage to the user equal to their current hp + * Deals damage to the user equal to their current hp if the move lands * @param user Pokemon that used the move * @param target The target of the move * @param move Move with this attribute @@ -804,13 +797,6 @@ export class SacrificialAttrOnHit extends MoveEffectAttr { return true; } - /** - * The AI is calculating how beneficial it is to use this move. Bosses will always return -20. Otherwise, the score is calculated based on the user's current hp ratio and the move's type effectiveness against the user - * @param user Pokemon that used the move - * @param target The target of the move - * @param move Move with this attribute - * @returns The benefit score of using this move (how likely the AI is to use this move) - **/ getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { if (user.isBoss()) return -20; diff --git a/src/phases.ts b/src/phases.ts index 2630789fc6d..4d8e88a8502 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2304,12 +2304,6 @@ export class MovePhase extends BattlePhase { return this.end(); } - // Check if the move has no valid targets (because they are flying, etc.) - if the used move is sacrificial it does not need a target so we add the user as a target so the move does not fail - if (targets.length === 0 && this.move.getMove().getAttrs(SacrificialAttr).length) { - // Add the user as a target if the move is sacrificial - targets.push(this.pokemon); - } - if (!moveQueue.length || !moveQueue.shift().ignorePP) // using .shift here clears out two turn moves once they've been used this.move.usePp(ppUsed); @@ -2473,17 +2467,8 @@ export class MoveEffectPhase extends PokemonPhase { // Move animation only needs one target new MoveAnim(this.move.getMove().id as Moves, user, this.getTarget()?.getBattlerIndex()).play(this.scene, () => { - // Check if the user is in the targets list for sacrificial moves, if not add them - if (this.move.getMove().getAttrs(SacrificialAttr).length && !targets.includes(user)) { - targets.push(user); - targetHitChecks[user.getBattlerIndex()] = true; - } for (let target of targets) { if (!targetHitChecks[target.getBattlerIndex()]) { - // If we have a sacrifical move, and the target isnt the user - it should not "miss". So we skip the miss check - if (this.move.getMove().getAttrs(SacrificialAttr).length && target !== user) { - continue; - } user.turnData.hitCount = 1; user.turnData.hitsLeft = 1; this.scene.queueMessage(getPokemonMessage(user, '\'s\nattack missed!')); @@ -2544,8 +2529,14 @@ 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()) + const postTarget = applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.POST_TARGET, + user, null, this.move.getMove()); + + if (applyAttrs.length) // If there is a pending asynchronous move effect, do this after + applyAttrs[applyAttrs.length - 1]?.then(() => postTarget); + else // Otherwise, push a new asynchronous move effect + applyAttrs.push(postTarget); + Promise.allSettled(applyAttrs).then(() => this.end()); }); });