mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-20 16:42:45 +02:00
Update abattr callsites in battler-tags
Also removed stat drop ability application from cancelling ME stat boost effects
This commit is contained in:
parent
1deb74e926
commit
f432f8cbf6
@ -1402,6 +1402,12 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr {
|
||||
|
||||
export class PostStatStageChangeAbAttr extends AbAttr {
|
||||
private declare readonly _: never;
|
||||
|
||||
override canApply(_params: Closed<PostStatStageChangeAbAttrParams>) {
|
||||
return true;
|
||||
}
|
||||
|
||||
override apply(_params: Closed<PostStatStageChangeAbAttrParams>) {}
|
||||
}
|
||||
|
||||
export interface PostStatStageChangeAbAttrParams extends AbAttrBaseParams {
|
||||
@ -3415,9 +3421,12 @@ export interface PreStatStageChangeAbAttrParams extends AbAttrBaseParams {
|
||||
stat: BattleStat;
|
||||
/** The amount of stages to change by (negative if the stat is being decreased) */
|
||||
stages: number;
|
||||
/** The source of the stat stage drop */
|
||||
source: Pokemon;
|
||||
// Note: `cancelled` already exists in `AbAttrBaseParams`, though we redefine it here to change its tsdoc
|
||||
/** The source of the stat stage drop. May be omitted if the source of the stat drop is the user itself.
|
||||
*
|
||||
* @remarks
|
||||
* Currently, only used by {@linkcode ReflectStatStageChangeAbAttr} in order to reflect the stat stage change
|
||||
*/
|
||||
source?: Pokemon;
|
||||
/** Holder that will be set to true if the stat stage change should be cancelled due to the ability */
|
||||
cancelled: BooleanHolder;
|
||||
}
|
||||
@ -3440,10 +3449,17 @@ export class ReflectStatStageChangeAbAttr extends PreStatStageChangeAbAttr {
|
||||
/** {@linkcode BattleStat} to reflect */
|
||||
private reflectedStat?: BattleStat;
|
||||
|
||||
override canApply({ source, cancelled }: PreStatStageChangeAbAttrParams): boolean {
|
||||
return !!source && !cancelled.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the {@linkcode ReflectStatStageChangeAbAttr} to an interaction
|
||||
*/
|
||||
override apply({ source, cancelled, stat, simulated, stages }: PreStatStageChangeAbAttrParams): void {
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
this.reflectedStat = stat;
|
||||
if (!simulated) {
|
||||
globalScene.phaseManager.unshiftNew(
|
||||
|
@ -946,7 +946,7 @@ class StealthRockTag extends ArenaTrapTag {
|
||||
|
||||
override activateTrap(pokemon: Pokemon, simulated: boolean): boolean {
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", pokemon, cancelled);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", { pokemon, cancelled });
|
||||
if (cancelled.value) {
|
||||
return false;
|
||||
}
|
||||
@ -1003,7 +1003,12 @@ class StickyWebTag extends ArenaTrapTag {
|
||||
override activateTrap(pokemon: Pokemon, simulated: boolean): boolean {
|
||||
if (pokemon.isGrounded()) {
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyAbAttrs("ProtectStatAbAttr", pokemon, cancelled);
|
||||
applyAbAttrs("ProtectStatAbAttr", {
|
||||
pokemon,
|
||||
cancelled,
|
||||
stat: Stat.SPD,
|
||||
stages: -1,
|
||||
});
|
||||
|
||||
if (simulated) {
|
||||
return !cancelled.value;
|
||||
@ -1416,7 +1421,9 @@ export class SuppressAbilitiesTag extends ArenaTag {
|
||||
|
||||
for (const fieldPokemon of globalScene.getField(true)) {
|
||||
if (fieldPokemon && fieldPokemon.id !== pokemon.id) {
|
||||
[true, false].forEach(passive => applyOnLoseAbAttrs(fieldPokemon, passive));
|
||||
// TODO: investigate whether we can just remove the foreach and call `applyAbAttrs` directly, providing
|
||||
// the appropriate attributes (preLEaveField and IllusionBreak)
|
||||
[true, false].forEach(passive => applyOnLoseAbAttrs({ pokemon: fieldPokemon, passive }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -621,7 +621,7 @@ export class FlinchedTag extends BattlerTag {
|
||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||
}),
|
||||
);
|
||||
applyAbAttrs("FlinchEffectAbAttr", pokemon, null);
|
||||
applyAbAttrs("FlinchEffectAbAttr", { pokemon });
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -916,7 +916,7 @@ export class SeedTag extends BattlerTag {
|
||||
const source = pokemon.getOpponents().find(o => o.getBattlerIndex() === this.sourceIndex);
|
||||
if (source) {
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", pokemon, cancelled);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", { pokemon, cancelled });
|
||||
|
||||
if (!cancelled.value) {
|
||||
globalScene.phaseManager.unshiftNew(
|
||||
@ -1006,7 +1006,7 @@ export class PowderTag extends BattlerTag {
|
||||
globalScene.phaseManager.unshiftNew("CommonAnimPhase", idx, idx, CommonAnim.POWDER);
|
||||
|
||||
const cancelDamage = new BooleanHolder(false);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", pokemon, cancelDamage);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", { pokemon, cancelled: cancelDamage });
|
||||
if (!cancelDamage.value) {
|
||||
pokemon.damageAndUpdate(Math.floor(pokemon.getMaxHp() / 4), { result: HitResult.INDIRECT });
|
||||
}
|
||||
@ -1056,7 +1056,7 @@ export class NightmareTag extends BattlerTag {
|
||||
phaseManager.unshiftNew("CommonAnimPhase", pokemon.getBattlerIndex(), undefined, CommonAnim.CURSE); // TODO: Update animation type
|
||||
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", pokemon, cancelled);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", { pokemon, cancelled });
|
||||
|
||||
if (!cancelled.value) {
|
||||
pokemon.damageAndUpdate(toDmgValue(pokemon.getMaxHp() / 4), { result: HitResult.INDIRECT });
|
||||
@ -1409,7 +1409,7 @@ export abstract class DamagingTrapTag extends TrappedTag {
|
||||
phaseManager.unshiftNew("CommonAnimPhase", pokemon.getBattlerIndex(), undefined, this.commonAnim);
|
||||
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", pokemon, cancelled);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", { pokemon, cancelled });
|
||||
|
||||
if (!cancelled.value) {
|
||||
pokemon.damageAndUpdate(toDmgValue(pokemon.getMaxHp() / 8), { result: HitResult.INDIRECT });
|
||||
@ -1642,7 +1642,7 @@ export class ContactDamageProtectedTag extends ContactProtectedTag {
|
||||
*/
|
||||
override onContact(attacker: Pokemon, user: Pokemon): void {
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", user, cancelled);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", { pokemon: user, cancelled });
|
||||
if (!cancelled.value) {
|
||||
attacker.damageAndUpdate(toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)), {
|
||||
result: HitResult.INDIRECT,
|
||||
@ -2243,7 +2243,7 @@ export class SaltCuredTag extends BattlerTag {
|
||||
);
|
||||
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", pokemon, cancelled);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", { pokemon, cancelled });
|
||||
|
||||
if (!cancelled.value) {
|
||||
const pokemonSteelOrWater = pokemon.isOfType(PokemonType.STEEL) || pokemon.isOfType(PokemonType.WATER);
|
||||
@ -2297,7 +2297,7 @@ export class CursedTag extends BattlerTag {
|
||||
);
|
||||
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", pokemon, cancelled);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", { pokemon, cancelled });
|
||||
|
||||
if (!cancelled.value) {
|
||||
pokemon.damageAndUpdate(toDmgValue(pokemon.getMaxHp() / 4), { result: HitResult.INDIRECT });
|
||||
@ -2632,7 +2632,7 @@ export class GulpMissileTag extends BattlerTag {
|
||||
}
|
||||
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", attacker, cancelled);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", { pokemon: attacker, cancelled });
|
||||
|
||||
if (!cancelled.value) {
|
||||
attacker.damageAndUpdate(Math.max(1, Math.floor(attacker.getMaxHp() / 4)), { result: HitResult.INDIRECT });
|
||||
@ -3021,14 +3021,7 @@ export class MysteryEncounterPostSummonTag extends BattlerTag {
|
||||
const ret = super.lapse(pokemon, lapseType);
|
||||
|
||||
if (lapseType === BattlerTagLapseType.CUSTOM) {
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyAbAttrs("ProtectStatAbAttr", pokemon, cancelled);
|
||||
applyAbAttrs("ConditionalUserFieldProtectStatAbAttr", pokemon, cancelled, false, pokemon);
|
||||
if (!cancelled.value) {
|
||||
if (pokemon.mysteryEncounterBattleEffects) {
|
||||
pokemon.mysteryEncounterBattleEffects(pokemon);
|
||||
}
|
||||
}
|
||||
pokemon.mysteryEncounterBattleEffects?.(pokemon);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -14,7 +14,7 @@ export class NewBiomeEncounterPhase extends NextEncounterPhase {
|
||||
if (pokemon) {
|
||||
pokemon.resetBattleAndWaveData();
|
||||
if (pokemon.isOnField()) {
|
||||
applyAbAttrs("PostBiomeChangeAbAttr", pokemon, null);
|
||||
applyAbAttrs("PostBiomeChangeAbAttr", { pokemon });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import type Pokemon from "#app/field/pokemon";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { PokemonPhase } from "./pokemon-phase";
|
||||
import { SpeciesFormChangeStatusEffectTrigger } from "#app/data/pokemon-forms/form-change-triggers";
|
||||
import { applyPostSetStatusAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||
import { applyAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||
import { isNullOrUndefined } from "#app/utils/common";
|
||||
|
||||
export class ObtainStatusEffectPhase extends PokemonPhase {
|
||||
@ -53,7 +53,11 @@ export class ObtainStatusEffectPhase extends PokemonPhase {
|
||||
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeStatusEffectTrigger, true);
|
||||
// If mold breaker etc was used to set this status, it shouldn't apply to abilities activated afterwards
|
||||
globalScene.arena.setIgnoreAbilities(false);
|
||||
applyPostSetStatusAbAttrs("PostSetStatusAbAttr", pokemon, this.statusEffect, this.sourcePokemon);
|
||||
applyAbAttrs("PostSetStatusAbAttr", {
|
||||
pokemon,
|
||||
effect: this.statusEffect,
|
||||
sourcePokemon: this.sourcePokemon ?? undefined,
|
||||
});
|
||||
}
|
||||
this.end();
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { applyPostSummonAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||
import { applyAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||
import { PostSummonPhase } from "#app/phases/post-summon-phase";
|
||||
import type { BattlerIndex } from "#enums/battler-index";
|
||||
|
||||
@ -16,7 +16,8 @@ export class PostSummonActivateAbilityPhase extends PostSummonPhase {
|
||||
}
|
||||
|
||||
start() {
|
||||
applyPostSummonAbAttrs("PostSummonAbAttr", this.getPokemon(), this.passive, false);
|
||||
// TODO: Check with Dean on whether or not passive must be provided to `this.passive`
|
||||
applyAbAttrs("PostSummonAbAttr", { pokemon: this.getPokemon(), passive: this.passive });
|
||||
|
||||
this.end();
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ export class PostSummonPhase extends PokemonPhase {
|
||||
|
||||
const field = pokemon.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField();
|
||||
for (const p of field) {
|
||||
applyAbAttrs("CommanderAbAttr", p, null, false);
|
||||
applyAbAttrs("CommanderAbAttr", { pokemon: p });
|
||||
}
|
||||
|
||||
this.end();
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type { BattlerIndex } from "#enums/battler-index";
|
||||
import { applyAbAttrs, applyPostDamageAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||
import { applyAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||
import { CommonBattleAnim } from "#app/data/battle-anims";
|
||||
import { CommonAnim } from "#enums/move-anims-common";
|
||||
import { getStatusEffectActivationText } from "#app/data/status-effect";
|
||||
@ -22,8 +22,8 @@ export class PostTurnStatusEffectPhase extends PokemonPhase {
|
||||
if (pokemon?.isActive(true) && pokemon.status && pokemon.status.isPostTurn() && !pokemon.switchOutStatus) {
|
||||
pokemon.status.incrementTurn();
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", pokemon, cancelled);
|
||||
applyAbAttrs("BlockStatusDamageAbAttr", pokemon, cancelled);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", { pokemon, cancelled });
|
||||
applyAbAttrs("BlockStatusDamageAbAttr", { pokemon, cancelled });
|
||||
|
||||
if (!cancelled.value) {
|
||||
globalScene.phaseManager.queueMessage(
|
||||
@ -39,14 +39,14 @@ export class PostTurnStatusEffectPhase extends PokemonPhase {
|
||||
break;
|
||||
case StatusEffect.BURN:
|
||||
damage.value = Math.max(pokemon.getMaxHp() >> 4, 1);
|
||||
applyAbAttrs("ReduceBurnDamageAbAttr", pokemon, null, false, damage);
|
||||
applyAbAttrs("ReduceBurnDamageAbAttr", { pokemon, burnDamage: damage });
|
||||
break;
|
||||
}
|
||||
if (damage.value) {
|
||||
// Set preventEndure flag to avoid pokemon surviving thanks to focus band, sturdy, endure ...
|
||||
globalScene.damageNumberHandler.add(this.getPokemon(), pokemon.damage(damage.value, false, true));
|
||||
pokemon.updateInfo();
|
||||
applyPostDamageAbAttrs("PostDamageAbAttr", pokemon, damage.value, pokemon.hasPassive(), false, []);
|
||||
applyAbAttrs("PostDamageAbAttr", { pokemon, damage: damage.value });
|
||||
}
|
||||
new CommonBattleAnim(CommonAnim.POISON + (pokemon.status.effect - 1), pokemon).play(false, () => this.end());
|
||||
} else {
|
||||
|
@ -181,9 +181,10 @@ export class QuietFormChangePhase extends BattlePhase {
|
||||
}
|
||||
}
|
||||
if (this.formChange.trigger instanceof SpeciesFormChangeTeraTrigger) {
|
||||
applyAbAttrs("PostTeraFormChangeStatChangeAbAttr", this.pokemon, null);
|
||||
applyAbAttrs("ClearWeatherAbAttr", this.pokemon, null);
|
||||
applyAbAttrs("ClearTerrainAbAttr", this.pokemon, null);
|
||||
const params = { pokemon: this.pokemon };
|
||||
applyAbAttrs("PostTeraFormChangeStatChangeAbAttr", params);
|
||||
applyAbAttrs("ClearWeatherAbAttr", params);
|
||||
applyAbAttrs("ClearTerrainAbAttr", params);
|
||||
}
|
||||
|
||||
super.end();
|
||||
|
@ -1,10 +1,6 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type { BattlerIndex } from "#enums/battler-index";
|
||||
import {
|
||||
applyAbAttrs,
|
||||
applyPostStatStageChangeAbAttrs,
|
||||
applyPreStatStageChangeAbAttrs,
|
||||
} from "#app/data/abilities/apply-ab-attrs";
|
||||
import { applyAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||
import { MistTag } from "#app/data/arena-tag";
|
||||
import { ArenaTagSide } from "#enums/arena-tag-side";
|
||||
import type { ArenaTag } from "#app/data/arena-tag";
|
||||
@ -18,6 +14,10 @@ import { PokemonPhase } from "./pokemon-phase";
|
||||
import { Stat, type BattleStat, getStatKey, getStatStageChangeDescriptionKey } from "#enums/stat";
|
||||
import { OctolockTag } from "#app/data/battler-tags";
|
||||
import { ArenaTagType } from "#app/enums/arena-tag-type";
|
||||
import type {
|
||||
ConditionalUserFieldProtectStatAbAttrParams,
|
||||
PreStatStageChangeAbAttrParams,
|
||||
} from "#app/@types/ability-types";
|
||||
|
||||
export type StatStageChangeCallback = (
|
||||
target: Pokemon | null,
|
||||
@ -126,7 +126,7 @@ export class StatStageChangePhase extends PokemonPhase {
|
||||
const stages = new NumberHolder(this.stages);
|
||||
|
||||
if (!this.ignoreAbilities) {
|
||||
applyAbAttrs("StatStageChangeMultiplierAbAttr", pokemon, null, false, stages);
|
||||
applyAbAttrs("StatStageChangeMultiplierAbAttr", { pokemon, numStages: stages });
|
||||
}
|
||||
|
||||
let simulate = false;
|
||||
@ -146,42 +146,38 @@ export class StatStageChangePhase extends PokemonPhase {
|
||||
}
|
||||
|
||||
if (!cancelled.value && !this.selfTarget && stages.value < 0) {
|
||||
applyPreStatStageChangeAbAttrs("ProtectStatAbAttr", pokemon, stat, cancelled, simulate);
|
||||
applyPreStatStageChangeAbAttrs(
|
||||
"ConditionalUserFieldProtectStatAbAttr",
|
||||
const abAttrParams: PreStatStageChangeAbAttrParams & ConditionalUserFieldProtectStatAbAttrParams = {
|
||||
pokemon,
|
||||
stat,
|
||||
cancelled,
|
||||
simulate,
|
||||
pokemon,
|
||||
);
|
||||
simulated: simulate,
|
||||
target: pokemon,
|
||||
stages: this.stages,
|
||||
};
|
||||
applyAbAttrs("ProtectStatAbAttr", abAttrParams);
|
||||
applyAbAttrs("ConditionalUserFieldProtectStatAbAttr", abAttrParams);
|
||||
// TODO: Consider skipping this call if `cancelled` is false.
|
||||
const ally = pokemon.getAlly();
|
||||
if (!isNullOrUndefined(ally)) {
|
||||
applyPreStatStageChangeAbAttrs(
|
||||
"ConditionalUserFieldProtectStatAbAttr",
|
||||
ally,
|
||||
stat,
|
||||
cancelled,
|
||||
simulate,
|
||||
pokemon,
|
||||
);
|
||||
applyAbAttrs("ConditionalUserFieldProtectStatAbAttr", { ...abAttrParams, pokemon: ally });
|
||||
}
|
||||
|
||||
/** Potential stat reflection due to Mirror Armor, does not apply to Octolock end of turn effect */
|
||||
if (
|
||||
opponentPokemon !== undefined &&
|
||||
// TODO: investigate whether this is stoping mirror armor from applying to non-octolock
|
||||
// reasons for stat drops if the user has the Octolock tag
|
||||
!pokemon.findTag(t => t instanceof OctolockTag) &&
|
||||
!this.comingFromMirrorArmorUser
|
||||
) {
|
||||
applyPreStatStageChangeAbAttrs(
|
||||
"ReflectStatStageChangeAbAttr",
|
||||
applyAbAttrs("ReflectStatStageChangeAbAttr", {
|
||||
pokemon,
|
||||
stat,
|
||||
cancelled,
|
||||
simulate,
|
||||
opponentPokemon,
|
||||
this.stages,
|
||||
);
|
||||
simulated: simulate,
|
||||
source: opponentPokemon,
|
||||
stages: this.stages,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,17 +218,16 @@ export class StatStageChangePhase extends PokemonPhase {
|
||||
|
||||
if (stages.value > 0 && this.canBeCopied) {
|
||||
for (const opponent of pokemon.getOpponents()) {
|
||||
applyAbAttrs("StatStageChangeCopyAbAttr", opponent, null, false, this.stats, stages.value);
|
||||
applyAbAttrs("StatStageChangeCopyAbAttr", { pokemon: opponent, stats: this.stats, numStages: stages.value });
|
||||
}
|
||||
}
|
||||
|
||||
applyPostStatStageChangeAbAttrs(
|
||||
"PostStatStageChangeAbAttr",
|
||||
applyAbAttrs("PostStatStageChangeAbAttr", {
|
||||
pokemon,
|
||||
filteredStats,
|
||||
this.stages,
|
||||
this.selfTarget,
|
||||
);
|
||||
stats: filteredStats,
|
||||
stages: this.stages,
|
||||
selfTarget: this.selfTarget,
|
||||
});
|
||||
|
||||
// Look for any other stat change phases; if this is the last one, do White Herb check
|
||||
const existingPhase = globalScene.phaseManager.findPhase(
|
||||
|
Loading…
Reference in New Issue
Block a user