From 6b10497be571e3b08c9bbb013a74ff98a8bce3d9 Mon Sep 17 00:00:00 2001 From: Dread134 Date: Fri, 17 May 2024 11:41:42 -0400 Subject: [PATCH] Move MoveEffectTrigger.PRE_APPLY Application Moved where the MoveEffectTrigger.PRE_APPLY is being applied to the attack to resolve the issue with moves that need to apply an attribute before a move is calculated. --- src/data/move.ts | 25 +++++++++++++++++++++++++ src/field/pokemon.ts | 8 +++++--- src/phases.ts | 5 +---- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 99ef179ad30..2a7beb9338c 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1990,6 +1990,31 @@ export class SwapStatsAttr extends MoveEffectAttr } } +/** + * Attribute used for moves which steal the target's positive stat changes. + */ +export class StealPositiveStatsAttr extends MoveEffectAttr { + constructor() { + super(false, MoveEffectTrigger.PRE_APPLY) + } + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + console.log("StealPositiveStatsAttr"); + if (!super.apply(user, target, move, args)) + return false; + let StatRaised = false; + for (let i = 0; i < 7; i++) { + if (target.summonData.battleStats[i] > 0) { + user.scene.unshiftPhase(new StatChangePhase(user.scene, user.getBattlerIndex(), true, [i], target.summonData.battleStats[i])); + target.summonData.battleStats[i] = 0; + StatRaised = true; + } + } + if (StatRaised) + user.scene.queueMessage(getPokemonMessage(user, ` stole\n${target.name}'s boosted stats!`)); + target.updateInfo(); + } +} + export class HpSplitAttr extends MoveEffectAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise { return new Promise(resolve => { diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index eb08af3da55..58bf3a2d082 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -4,7 +4,7 @@ import { Variant, VariantSet, variantColorCache } from '#app/data/variant'; import { variantData } from '#app/data/variant'; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info'; import { Moves } from "../data/enums/moves"; -import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr } from "../data/move"; +import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, applyFilteredMoveAttrs, MoveAttr, MoveEffectAttr, MoveEffectTrigger } from "../data/move"; import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from '../data/pokemon-species'; import * as Utils from '../utils'; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type'; @@ -17,7 +17,7 @@ import { initMoveAnim, loadMoveAnimAssets } from '../data/battle-anims'; import { Status, StatusEffect, getRandomStatus } from '../data/status-effect'; import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from '../data/pokemon-evolutions'; import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from '../data/tms'; -import { DamagePhase, FaintPhase, LearnMovePhase, ObtainStatusEffectPhase, StatChangePhase, SwitchSummonPhase } from '../phases'; +import { DamagePhase, FaintPhase, LearnMovePhase, MoveEffectPhase, ObtainStatusEffectPhase, StatChangePhase, SwitchSummonPhase } from '../phases'; import { BattleStat } from '../data/battle-stat'; import { BattlerTag, BattlerTagLapseType, EncoreTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, getBattlerTag } from '../data/battler-tags'; import { BattlerTagType } from "../data/enums/battler-tag-type"; @@ -1412,7 +1412,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return (this.isPlayer() ? this.scene.getPlayerField() : this.scene.getEnemyField())[this.getFieldIndex() ? 0 : 1]; } - apply(source: Pokemon, battlerMove: PokemonMove): HitResult { + apply(source: Pokemon, battlerMove: PokemonMove, firstHit: boolean, moveEffectPhase: MoveEffectPhase): HitResult { let result: HitResult; const move = battlerMove.getMove(); let damage = new Utils.NumberHolder(0); @@ -1467,6 +1467,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (cancelled.value) result = HitResult.NO_EFFECT; else { + applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.PRE_APPLY && (!attr.firstHitOnly || firstHit), source, this, moveEffectPhase.move.getMove()) + let typeBoost = source.findTag(t => t instanceof TypeBoostTag && (t as TypeBoostTag).boostedType === type) as TypeBoostTag; if (typeBoost) { power.value *= typeBoost.boostValue; diff --git a/src/phases.ts b/src/phases.ts index 1137c85afa6..e024772b0dc 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2522,13 +2522,11 @@ export class MoveEffectPhase extends PokemonPhase { moveHistoryEntry.result = MoveResult.SUCCESS; - const hitResult = !isProtected ? target.apply(user, this.move) : HitResult.NO_EFFECT; + const hitResult = !isProtected ? target.apply(user, this.move, firstHit, this) : HitResult.NO_EFFECT; this.scene.triggerPokemonFormChange(user, SpeciesFormChangePostMoveTrigger); applyAttrs.push(new Promise(resolve => { - applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.PRE_APPLY && (!attr.firstHitOnly || firstHit), - user, target, this.move.getMove()).then(() => { if (hitResult !== HitResult.FAIL) { const chargeEffect = !!this.move.getMove().getAttrs(ChargeAttr).find(ca => (ca as ChargeAttr).usedChargeEffect(user, this.getTarget(), this.move.getMove())); // Charge attribute with charge effect takes all effect attributes and applies them to charge stage, so ignore them if this is present @@ -2563,7 +2561,6 @@ export class MoveEffectPhase extends PokemonPhase { }); } else resolve(); - }); })); } // Trigger effect which should only apply one time after all targeted effects have already applied