mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-20 16:42:45 +02:00
[WIP] Refactor ability attribute apply args
This commit is contained in:
parent
6873a89296
commit
804809bb17
1
src/@types/ab-attr-types.ts
Normal file
1
src/@types/ab-attr-types.ts
Normal file
@ -0,0 +1 @@
|
||||
export type * from "#app/data/abilities/ability";
|
@ -4,6 +4,9 @@ import type Pokemon from "#app/field/pokemon";
|
||||
import type { BattleStat } from "#enums/stat";
|
||||
import type { AbAttrConstructorMap } from "#app/data/abilities/ability";
|
||||
|
||||
// biome-ignore lint/correctness/noUnusedImports: Used in a tsdoc comment
|
||||
import type { applyAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||
|
||||
// Intentionally re-export all types from the ability attributes module
|
||||
export type * from "#app/data/abilities/ability";
|
||||
|
||||
@ -25,3 +28,16 @@ export type AbAttrString = keyof AbAttrConstructorMap;
|
||||
export type AbAttrMap = {
|
||||
[K in keyof AbAttrConstructorMap]: InstanceType<AbAttrConstructorMap[K]>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Subset of ability attribute classes that may be passed to {@linkcode applyAbAttrs } method
|
||||
*
|
||||
* @remarks
|
||||
* Our AbAttr classes violate Liskov Substitution Principal.
|
||||
*
|
||||
* AbAttrs that are not in this have subclasses with apply methods requiring different parameters than
|
||||
* the base apply method.
|
||||
*
|
||||
* Such attributes may not be passed to the {@linkcode applyAbAttrs} method
|
||||
*/
|
||||
export type CallableAbAttrString = Exclude<AbAttrString, "PreDefendAbAttr" | "PreAttackAbAttr">;
|
||||
|
34
src/@types/type-helpers.ts
Normal file
34
src/@types/type-helpers.ts
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* A collection of custom utility types that aid in type checking and ensuring strict type conformity
|
||||
*/
|
||||
|
||||
// biome-ignore lint/correctness/noUnusedImports: Used in a tsdoc comment
|
||||
import type { AbAttr } from "./ability-types";
|
||||
|
||||
/** Exactly matches the type of the argument, preventing adding additional properties.
|
||||
* ⚠️ Should never be used with `extends`, as this will nullify the exactness of the type.
|
||||
* As an example, used to ensure that the parameters of {@linkcode AbAttr#canApply} and {@linkcode AbAttr#getTriggerMessage} are compatible with
|
||||
* the type of the apply method
|
||||
*
|
||||
* @typeParam T - The type to match exactly
|
||||
*/
|
||||
export type Exact<T> = {
|
||||
[K in keyof T]: T[K];
|
||||
};
|
||||
|
||||
/**
|
||||
* Type hint that indicates that the type is intended to be closed to a specific shape.
|
||||
*
|
||||
* @remarks
|
||||
* Can be used to ensure that a particular parameter does not change when subclassed, **But will only do so for one level of inheritance**
|
||||
* ```ts
|
||||
* type foo = { } // whatever
|
||||
* class Foo {
|
||||
* method<T>(param: Closed<T, foo>)
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @typeParam T - The type to check
|
||||
* @typeParam Shape - The shape to match against
|
||||
*/
|
||||
export type Closed<X, Shape> = X extends Shape ? (Shape extends X ? X : never) : never;
|
File diff suppressed because it is too large
Load Diff
@ -1,63 +1,13 @@
|
||||
import type { AbAttrApplyFunc, AbAttrMap, AbAttrString, AbAttrSuccessFunc } from "#app/@types/ability-types";
|
||||
import type Pokemon from "#app/field/pokemon";
|
||||
import type { AbAttrBaseParams, AbAttrMap, CallableAbAttrString } from "#app/@types/ability-types";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type { BooleanHolder, NumberHolder } from "#app/utils/common";
|
||||
import type { BattlerIndex } from "#enums/battler-index";
|
||||
import type { HitResult } from "#enums/hit-result";
|
||||
import type { BattleStat, Stat } from "#enums/stat";
|
||||
import type { StatusEffect } from "#enums/status-effect";
|
||||
import type { WeatherType } from "#enums/weather-type";
|
||||
import type { BattlerTag } from "../battler-tags";
|
||||
import type Move from "../moves/move";
|
||||
import type { PokemonMove } from "../moves/pokemon-move";
|
||||
import type { TerrainType } from "../terrain";
|
||||
import type { Weather } from "../weather";
|
||||
import type {
|
||||
PostBattleInitAbAttr,
|
||||
PreDefendAbAttr,
|
||||
PostDefendAbAttr,
|
||||
PostMoveUsedAbAttr,
|
||||
StatMultiplierAbAttr,
|
||||
AllyStatMultiplierAbAttr,
|
||||
PostSetStatusAbAttr,
|
||||
PostDamageAbAttr,
|
||||
FieldMultiplyStatAbAttr,
|
||||
PreAttackAbAttr,
|
||||
ExecutedMoveAbAttr,
|
||||
PostAttackAbAttr,
|
||||
PostKnockOutAbAttr,
|
||||
PostVictoryAbAttr,
|
||||
PostSummonAbAttr,
|
||||
PreSummonAbAttr,
|
||||
PreSwitchOutAbAttr,
|
||||
PreLeaveFieldAbAttr,
|
||||
PreStatStageChangeAbAttr,
|
||||
PostStatStageChangeAbAttr,
|
||||
PreSetStatusAbAttr,
|
||||
PreApplyBattlerTagAbAttr,
|
||||
PreWeatherEffectAbAttr,
|
||||
PreWeatherDamageAbAttr,
|
||||
PostTurnAbAttr,
|
||||
PostWeatherChangeAbAttr,
|
||||
PostWeatherLapseAbAttr,
|
||||
PostTerrainChangeAbAttr,
|
||||
CheckTrappedAbAttr,
|
||||
PostBattleAbAttr,
|
||||
PostFaintAbAttr,
|
||||
PostItemLostAbAttr,
|
||||
} from "./ability";
|
||||
|
||||
function applySingleAbAttrs<T extends AbAttrString>(
|
||||
pokemon: Pokemon,
|
||||
passive: boolean,
|
||||
function applySingleAbAttrs<T extends CallableAbAttrString>(
|
||||
attrType: T,
|
||||
applyFunc: AbAttrApplyFunc<AbAttrMap[T]>,
|
||||
successFunc: AbAttrSuccessFunc<AbAttrMap[T]>,
|
||||
args: any[],
|
||||
params: Parameters<AbAttrMap[T]["apply"]>[0],
|
||||
gainedMidTurn = false,
|
||||
simulated = false,
|
||||
messages: string[] = [],
|
||||
) {
|
||||
const { simulated = false, passive = false, pokemon } = params;
|
||||
if (!pokemon?.canApplyAbility(passive) || (passive && pokemon.getPassiveAbility().id === pokemon.getAbility().id)) {
|
||||
return;
|
||||
}
|
||||
@ -73,9 +23,10 @@ function applySingleAbAttrs<T extends AbAttrString>(
|
||||
}
|
||||
|
||||
for (const attr of ability.getAttrs(attrType)) {
|
||||
declare const attr: AbAttrMap[T];
|
||||
const condition = attr.getCondition();
|
||||
let abShown = false;
|
||||
if ((condition && !condition(pokemon)) || !successFunc(attr, passive)) {
|
||||
if ((condition && !condition(pokemon)) || !attr.canApply(params)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -85,7 +36,7 @@ function applySingleAbAttrs<T extends AbAttrString>(
|
||||
globalScene.phaseManager.queueAbilityDisplay(pokemon, passive, true);
|
||||
abShown = true;
|
||||
}
|
||||
const message = attr.getTriggerMessage(pokemon, ability.name, args);
|
||||
const message = attr.getTriggerMessage(pokemon, ability.name, params);
|
||||
if (message) {
|
||||
if (!simulated) {
|
||||
globalScene.phaseManager.queueMessage(message);
|
||||
@ -93,7 +44,7 @@ function applySingleAbAttrs<T extends AbAttrString>(
|
||||
messages.push(message);
|
||||
}
|
||||
|
||||
applyFunc(attr, passive);
|
||||
attr.apply(params);
|
||||
|
||||
if (abShown) {
|
||||
globalScene.phaseManager.queueAbilityDisplay(pokemon, passive, false);
|
||||
@ -107,717 +58,49 @@ function applySingleAbAttrs<T extends AbAttrString>(
|
||||
}
|
||||
}
|
||||
|
||||
function applyAbAttrsInternal<T extends AbAttrString>(
|
||||
function applyAbAttrsInternal<T extends CallableAbAttrString>(
|
||||
attrType: T,
|
||||
pokemon: Pokemon | null,
|
||||
applyFunc: AbAttrApplyFunc<AbAttrMap[T]>,
|
||||
successFunc: AbAttrSuccessFunc<AbAttrMap[T]>,
|
||||
args: any[],
|
||||
simulated = false,
|
||||
params: Parameters<AbAttrMap[T]["apply"]>[0],
|
||||
messages: string[] = [],
|
||||
gainedMidTurn = false,
|
||||
) {
|
||||
const { pokemon } = params;
|
||||
for (const passive of [false, true]) {
|
||||
if (pokemon) {
|
||||
applySingleAbAttrs(pokemon, passive, attrType, applyFunc, successFunc, args, gainedMidTurn, simulated, messages);
|
||||
applySingleAbAttrs(attrType, { ...params, passive }, gainedMidTurn, messages);
|
||||
globalScene.phaseManager.clearPhaseQueueSplice();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function applyAbAttrs<T extends AbAttrString>(
|
||||
/**
|
||||
* @param attrType - The type of the ability attribute to apply
|
||||
* @param params - The parameters to pass to the ability attribute's apply method
|
||||
*/
|
||||
export function applyAbAttrs<T extends CallableAbAttrString>(
|
||||
attrType: T,
|
||||
pokemon: Pokemon,
|
||||
cancelled: BooleanHolder | null,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
params: Parameters<AbAttrMap[T]["apply"]>[0],
|
||||
): void {
|
||||
applyAbAttrsInternal<T>(
|
||||
attrType,
|
||||
pokemon,
|
||||
// @ts-expect-error: TODO: fix the error on `cancelled`
|
||||
(attr, passive) => attr.apply(pokemon, passive, simulated, cancelled, args),
|
||||
(attr, passive) => attr.canApply(pokemon, passive, simulated, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
applyAbAttrsInternal(attrType, params);
|
||||
}
|
||||
|
||||
|
||||
// TODO: Improve the type signatures of the following methods / refactor the apply methods
|
||||
|
||||
export function applyPostBattleInitAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostBattleInitAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) => (attr as PostBattleInitAbAttr).applyPostBattleInit(pokemon, passive, simulated, args),
|
||||
(attr, passive) => (attr as PostBattleInitAbAttr).canApplyPostBattleInit(pokemon, passive, simulated, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPreDefendAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PreDefendAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
attacker: Pokemon,
|
||||
move: Move | null,
|
||||
cancelled: BooleanHolder | null,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as PreDefendAbAttr).applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args),
|
||||
(attr, passive) =>
|
||||
(attr as PreDefendAbAttr).canApplyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostDefendAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostDefendAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
attacker: Pokemon,
|
||||
move: Move,
|
||||
hitResult: HitResult | null,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as PostDefendAbAttr).applyPostDefend(pokemon, passive, simulated, attacker, move, hitResult, args),
|
||||
(attr, passive) =>
|
||||
(attr as PostDefendAbAttr).canApplyPostDefend(pokemon, passive, simulated, attacker, move, hitResult, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostMoveUsedAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostMoveUsedAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
move: PokemonMove,
|
||||
source: Pokemon,
|
||||
targets: BattlerIndex[],
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, _passive) => (attr as PostMoveUsedAbAttr).applyPostMoveUsed(pokemon, move, source, targets, simulated, args),
|
||||
(attr, _passive) =>
|
||||
(attr as PostMoveUsedAbAttr).canApplyPostMoveUsed(pokemon, move, source, targets, simulated, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyStatMultiplierAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends StatMultiplierAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
stat: BattleStat,
|
||||
statValue: NumberHolder,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as StatMultiplierAbAttr).applyStatStage(pokemon, passive, simulated, stat, statValue, args),
|
||||
(attr, passive) =>
|
||||
(attr as StatMultiplierAbAttr).canApplyStatStage(pokemon, passive, simulated, stat, statValue, args),
|
||||
args,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies an ally's Stat multiplier attribute
|
||||
* @param attrType - {@linkcode AllyStatMultiplierAbAttr} should always be AllyStatMultiplierAbAttr for the time being
|
||||
* @param pokemon - The {@linkcode Pokemon} with the ability
|
||||
* @param stat - The type of the checked {@linkcode Stat}
|
||||
* @param statValue - {@linkcode NumberHolder} containing the value of the checked stat
|
||||
* @param checkedPokemon - The {@linkcode Pokemon} with the checked stat
|
||||
* @param ignoreAbility - Whether or not the ability should be ignored by the pokemon or its move.
|
||||
* @param args - unused
|
||||
*/
|
||||
export function applyAllyStatMultiplierAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends AllyStatMultiplierAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
stat: BattleStat,
|
||||
statValue: NumberHolder,
|
||||
simulated = false,
|
||||
checkedPokemon: Pokemon,
|
||||
ignoreAbility: boolean,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as AllyStatMultiplierAbAttr).applyAllyStat(
|
||||
pokemon,
|
||||
passive,
|
||||
simulated,
|
||||
stat,
|
||||
statValue,
|
||||
checkedPokemon,
|
||||
ignoreAbility,
|
||||
args,
|
||||
),
|
||||
(attr, passive) =>
|
||||
(attr as AllyStatMultiplierAbAttr).canApplyAllyStat(
|
||||
pokemon,
|
||||
passive,
|
||||
simulated,
|
||||
stat,
|
||||
statValue,
|
||||
checkedPokemon,
|
||||
ignoreAbility,
|
||||
args,
|
||||
),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostSetStatusAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostSetStatusAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
effect: StatusEffect,
|
||||
sourcePokemon?: Pokemon | null,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as PostSetStatusAbAttr).applyPostSetStatus(pokemon, sourcePokemon, passive, effect, simulated, args),
|
||||
(attr, passive) =>
|
||||
(attr as PostSetStatusAbAttr).canApplyPostSetStatus(pokemon, sourcePokemon, passive, effect, simulated, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostDamageAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostDamageAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
damage: number,
|
||||
_passive: boolean,
|
||||
simulated = false,
|
||||
args: any[],
|
||||
source?: Pokemon,
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) => (attr as PostDamageAbAttr).applyPostDamage(pokemon, damage, passive, simulated, args, source),
|
||||
(attr, passive) => (attr as PostDamageAbAttr).canApplyPostDamage(pokemon, damage, passive, simulated, args, source),
|
||||
args,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Applies a field Stat multiplier attribute
|
||||
* @param attrType {@linkcode FieldMultiplyStatAbAttr} should always be FieldMultiplyBattleStatAbAttr for the time being
|
||||
* @param pokemon {@linkcode Pokemon} the Pokemon applying this ability
|
||||
* @param stat {@linkcode Stat} the type of the checked stat
|
||||
* @param statValue {@linkcode NumberHolder} the value of the checked stat
|
||||
* @param checkedPokemon {@linkcode Pokemon} the Pokemon with the checked stat
|
||||
* @param hasApplied {@linkcode BooleanHolder} whether or not a FieldMultiplyBattleStatAbAttr has already affected this stat
|
||||
* @param args unused
|
||||
*/
|
||||
|
||||
export function applyFieldStatMultiplierAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends FieldMultiplyStatAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
stat: Stat,
|
||||
statValue: NumberHolder,
|
||||
checkedPokemon: Pokemon,
|
||||
hasApplied: BooleanHolder,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as FieldMultiplyStatAbAttr).applyFieldStat(
|
||||
pokemon,
|
||||
passive,
|
||||
simulated,
|
||||
stat,
|
||||
statValue,
|
||||
checkedPokemon,
|
||||
hasApplied,
|
||||
args,
|
||||
),
|
||||
(attr, passive) =>
|
||||
(attr as FieldMultiplyStatAbAttr).canApplyFieldStat(
|
||||
pokemon,
|
||||
passive,
|
||||
simulated,
|
||||
stat,
|
||||
statValue,
|
||||
checkedPokemon,
|
||||
hasApplied,
|
||||
args,
|
||||
),
|
||||
args,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPreAttackAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PreAttackAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
defender: Pokemon | null,
|
||||
move: Move,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) => (attr as PreAttackAbAttr).applyPreAttack(pokemon, passive, simulated, defender, move, args),
|
||||
(attr, passive) => (attr as PreAttackAbAttr).canApplyPreAttack(pokemon, passive, simulated, defender, move, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyExecutedMoveAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends ExecutedMoveAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
attr => (attr as ExecutedMoveAbAttr).applyExecutedMove(pokemon, simulated),
|
||||
attr => (attr as ExecutedMoveAbAttr).canApplyExecutedMove(pokemon, simulated),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostAttackAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostAttackAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
defender: Pokemon,
|
||||
move: Move,
|
||||
hitResult: HitResult | null,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as PostAttackAbAttr).applyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args),
|
||||
(attr, passive) =>
|
||||
(attr as PostAttackAbAttr).canApplyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostKnockOutAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostKnockOutAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
knockedOut: Pokemon,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) => (attr as PostKnockOutAbAttr).applyPostKnockOut(pokemon, passive, simulated, knockedOut, args),
|
||||
(attr, passive) => (attr as PostKnockOutAbAttr).canApplyPostKnockOut(pokemon, passive, simulated, knockedOut, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostVictoryAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostVictoryAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) => (attr as PostVictoryAbAttr).applyPostVictory(pokemon, passive, simulated, args),
|
||||
(attr, passive) => (attr as PostVictoryAbAttr).canApplyPostVictory(pokemon, passive, simulated, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostSummonAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostSummonAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
passive = false,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applySingleAbAttrs(
|
||||
pokemon,
|
||||
passive,
|
||||
attrType,
|
||||
(attr, passive) => (attr as PostSummonAbAttr).applyPostSummon(pokemon, passive, simulated, args),
|
||||
(attr, passive) => (attr as PostSummonAbAttr).canApplyPostSummon(pokemon, passive, simulated, args),
|
||||
args,
|
||||
false,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPreSummonAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PreSummonAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) => (attr as PreSummonAbAttr).applyPreSummon(pokemon, passive, args),
|
||||
(attr, passive) => (attr as PreSummonAbAttr).canApplyPreSummon(pokemon, passive, args),
|
||||
args,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPreSwitchOutAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PreSwitchOutAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) => (attr as PreSwitchOutAbAttr).applyPreSwitchOut(pokemon, passive, simulated, args),
|
||||
(attr, passive) => (attr as PreSwitchOutAbAttr).canApplyPreSwitchOut(pokemon, passive, simulated, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPreLeaveFieldAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PreLeaveFieldAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) => (attr as PreLeaveFieldAbAttr).applyPreLeaveField(pokemon, passive, simulated, args),
|
||||
(attr, passive) => (attr as PreLeaveFieldAbAttr).canApplyPreLeaveField(pokemon, passive, simulated, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPreStatStageChangeAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PreStatStageChangeAbAttr ? K : never,
|
||||
pokemon: Pokemon | null,
|
||||
stat: BattleStat,
|
||||
cancelled: BooleanHolder,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as PreStatStageChangeAbAttr).applyPreStatStageChange(pokemon, passive, simulated, stat, cancelled, args),
|
||||
(attr, passive) =>
|
||||
(attr as PreStatStageChangeAbAttr).canApplyPreStatStageChange(pokemon, passive, simulated, stat, cancelled, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostStatStageChangeAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostStatStageChangeAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
stats: BattleStat[],
|
||||
stages: number,
|
||||
selfTarget: boolean,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, _passive) =>
|
||||
(attr as PostStatStageChangeAbAttr).applyPostStatStageChange(pokemon, simulated, stats, stages, selfTarget, args),
|
||||
(attr, _passive) =>
|
||||
(attr as PostStatStageChangeAbAttr).canApplyPostStatStageChange(
|
||||
pokemon,
|
||||
simulated,
|
||||
stats,
|
||||
stages,
|
||||
selfTarget,
|
||||
args,
|
||||
),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPreSetStatusAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PreSetStatusAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
effect: StatusEffect | undefined,
|
||||
cancelled: BooleanHolder,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as PreSetStatusAbAttr).applyPreSetStatus(pokemon, passive, simulated, effect, cancelled, args),
|
||||
(attr, passive) =>
|
||||
(attr as PreSetStatusAbAttr).canApplyPreSetStatus(pokemon, passive, simulated, effect, cancelled, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPreApplyBattlerTagAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PreApplyBattlerTagAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
tag: BattlerTag,
|
||||
cancelled: BooleanHolder,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as PreApplyBattlerTagAbAttr).applyPreApplyBattlerTag(pokemon, passive, simulated, tag, cancelled, args),
|
||||
(attr, passive) =>
|
||||
(attr as PreApplyBattlerTagAbAttr).canApplyPreApplyBattlerTag(pokemon, passive, simulated, tag, cancelled, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPreWeatherEffectAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PreWeatherEffectAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
weather: Weather | null,
|
||||
cancelled: BooleanHolder,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as PreWeatherDamageAbAttr).applyPreWeatherEffect(pokemon, passive, simulated, weather, cancelled, args),
|
||||
(attr, passive) =>
|
||||
(attr as PreWeatherDamageAbAttr).canApplyPreWeatherEffect(pokemon, passive, simulated, weather, cancelled, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostTurnAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostTurnAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) => (attr as PostTurnAbAttr).applyPostTurn(pokemon, passive, simulated, args),
|
||||
(attr, passive) => (attr as PostTurnAbAttr).canApplyPostTurn(pokemon, passive, simulated, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostWeatherChangeAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostWeatherChangeAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
weather: WeatherType,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as PostWeatherChangeAbAttr).applyPostWeatherChange(pokemon, passive, simulated, weather, args),
|
||||
(attr, passive) =>
|
||||
(attr as PostWeatherChangeAbAttr).canApplyPostWeatherChange(pokemon, passive, simulated, weather, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostWeatherLapseAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostWeatherLapseAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
weather: Weather | null,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as PostWeatherLapseAbAttr).applyPostWeatherLapse(pokemon, passive, simulated, weather, args),
|
||||
(attr, passive) =>
|
||||
(attr as PostWeatherLapseAbAttr).canApplyPostWeatherLapse(pokemon, passive, simulated, weather, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostTerrainChangeAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostTerrainChangeAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
terrain: TerrainType,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as PostTerrainChangeAbAttr).applyPostTerrainChange(pokemon, passive, simulated, terrain, args),
|
||||
(attr, passive) =>
|
||||
(attr as PostTerrainChangeAbAttr).canApplyPostTerrainChange(pokemon, passive, simulated, terrain, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyCheckTrappedAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends CheckTrappedAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
trapped: BooleanHolder,
|
||||
otherPokemon: Pokemon,
|
||||
messages: string[],
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as CheckTrappedAbAttr).applyCheckTrapped(pokemon, passive, simulated, trapped, otherPokemon, args),
|
||||
(attr, passive) =>
|
||||
(attr as CheckTrappedAbAttr).canApplyCheckTrapped(pokemon, passive, simulated, trapped, otherPokemon, args),
|
||||
args,
|
||||
simulated,
|
||||
messages,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostBattleAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostBattleAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) => (attr as PostBattleAbAttr).applyPostBattle(pokemon, passive, simulated, args),
|
||||
(attr, passive) => (attr as PostBattleAbAttr).canApplyPostBattle(pokemon, passive, simulated, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostFaintAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostFaintAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
attacker?: Pokemon,
|
||||
move?: Move,
|
||||
hitResult?: HitResult,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, passive) =>
|
||||
(attr as PostFaintAbAttr).applyPostFaint(pokemon, passive, simulated, attacker, move, hitResult, args),
|
||||
(attr, passive) =>
|
||||
(attr as PostFaintAbAttr).canApplyPostFaint(pokemon, passive, simulated, attacker, move, hitResult, args),
|
||||
args,
|
||||
simulated,
|
||||
);
|
||||
}
|
||||
|
||||
export function applyPostItemLostAbAttrs<K extends AbAttrString>(
|
||||
attrType: AbAttrMap[K] extends PostItemLostAbAttr ? K : never,
|
||||
pokemon: Pokemon,
|
||||
simulated = false,
|
||||
...args: any[]
|
||||
): void {
|
||||
applyAbAttrsInternal(
|
||||
attrType,
|
||||
pokemon,
|
||||
(attr, _passive) => (attr as PostItemLostAbAttr).applyPostItemLost(pokemon, simulated, args),
|
||||
(attr, _passive) => (attr as PostItemLostAbAttr).canApplyPostItemLost(pokemon, simulated, args),
|
||||
args,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies abilities when they become active mid-turn (ability switch)
|
||||
*
|
||||
* Ignores passives as they don't change and shouldn't be reapplied when main abilities change
|
||||
*/
|
||||
export function applyOnGainAbAttrs(pokemon: Pokemon, passive = false, simulated = false, ...args: any[]): void {
|
||||
applySingleAbAttrs(
|
||||
pokemon,
|
||||
passive,
|
||||
"PostSummonAbAttr",
|
||||
(attr, passive) => attr.applyPostSummon(pokemon, passive, simulated, args),
|
||||
(attr, passive) => attr.canApplyPostSummon(pokemon, passive, simulated, args),
|
||||
args,
|
||||
true,
|
||||
simulated,
|
||||
);
|
||||
export function applyOnGainAbAttrs(params: AbAttrBaseParams): void {
|
||||
applySingleAbAttrs("PostSummonAbAttr", params, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies ability attributes which activate when the ability is lost or suppressed (i.e. primal weather)
|
||||
*/
|
||||
export function applyOnLoseAbAttrs(pokemon: Pokemon, passive = false, simulated = false, ...args: any[]): void {
|
||||
applySingleAbAttrs(
|
||||
pokemon,
|
||||
passive,
|
||||
"PreLeaveFieldAbAttr",
|
||||
(attr, passive) => attr.applyPreLeaveField(pokemon, passive, simulated, [...args, true]),
|
||||
(attr, passive) => attr.canApplyPreLeaveField(pokemon, passive, simulated, [...args, true]),
|
||||
args,
|
||||
true,
|
||||
simulated,
|
||||
);
|
||||
export function applyOnLoseAbAttrs(params): void {
|
||||
applySingleAbAttrs("PreLeaveFieldAbAttr");
|
||||
|
||||
applySingleAbAttrs(
|
||||
pokemon,
|
||||
|
@ -38,7 +38,7 @@ export function getBerryPredicate(berryType: BerryType): BerryPredicate {
|
||||
const threshold = new NumberHolder(0.25);
|
||||
// Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth
|
||||
const stat: BattleStat = berryType - BerryType.ENIGMA;
|
||||
applyAbAttrs("ReduceBerryUseThresholdAbAttr", pokemon, null, false, threshold);
|
||||
applyAbAttrs("ReduceBerryUseThresholdAbAttr", { pokemon, stat});
|
||||
return pokemon.getHpRatio() < threshold.value && pokemon.getStatStage(stat) < 6;
|
||||
};
|
||||
case BerryType.LANSAT:
|
||||
@ -72,7 +72,7 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
|
||||
case BerryType.ENIGMA:
|
||||
{
|
||||
const hpHealed = new NumberHolder(toDmgValue(consumer.getMaxHp() / 4));
|
||||
applyAbAttrs("DoubleBerryEffectAbAttr", consumer, null, false, hpHealed);
|
||||
applyAbAttrs("DoubleBerryEffectAbAttr", { pokemon: consumer, effectValue: hpHealed, cancelled: null});
|
||||
globalScene.phaseManager.unshiftNew(
|
||||
"PokemonHealPhase",
|
||||
consumer.getBattlerIndex(),
|
||||
|
@ -20,11 +20,7 @@ import { ArenaTrapTag, getArenaTag } from "#app/data/arena-tag";
|
||||
import { ArenaTagSide } from "#enums/arena-tag-side";
|
||||
import type { BattlerIndex } from "#enums/battler-index";
|
||||
import { Terrain, TerrainType } from "#app/data/terrain";
|
||||
import {
|
||||
applyAbAttrs,
|
||||
applyPostTerrainChangeAbAttrs,
|
||||
applyPostWeatherChangeAbAttrs,
|
||||
} from "#app/data/abilities/apply-ab-attrs";
|
||||
import { applyAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||
import type Pokemon from "#app/field/pokemon";
|
||||
import Overrides from "#app/overrides";
|
||||
import { TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena";
|
||||
@ -372,7 +368,7 @@ export class Arena {
|
||||
pokemon.findAndRemoveTags(
|
||||
t => "weatherTypes" in t && !(t.weatherTypes as WeatherType[]).find(t => t === weather),
|
||||
);
|
||||
applyPostWeatherChangeAbAttrs("PostWeatherChangeAbAttr", pokemon, weather);
|
||||
applyAbAttrs("PostWeatherChangeAbAttr", {pokemon, weather});
|
||||
});
|
||||
|
||||
return true;
|
||||
|
@ -4046,7 +4046,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
const stubTag = new BattlerTag(tagType, 0, 0);
|
||||
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyPreApplyBattlerTagAbAttrs("BattlerTagImmunityAbAttr", this, stubTag, cancelled, true);
|
||||
applyAbAttrs("BattlerTagImmunityAbAttr", this, stubTag, cancelled, true, this);
|
||||
|
||||
const userField = this.getAlliedField();
|
||||
userField.forEach(pokemon =>
|
||||
|
@ -20,7 +20,7 @@ export class BerryPhase extends FieldPhase {
|
||||
|
||||
this.executeForAll(pokemon => {
|
||||
this.eatBerries(pokemon);
|
||||
applyAbAttrs("RepeatBerryNextTurnAbAttr", pokemon, null);
|
||||
applyAbAttrs("CudChewConsumeBerryAbAttr", { pokemon });
|
||||
});
|
||||
|
||||
this.end();
|
||||
|
Loading…
Reference in New Issue
Block a user