Update preAttack and fieldStat

This commit is contained in:
Dean 2025-02-01 16:40:54 -08:00
parent e2249a25a4
commit e958bb5fbd

View File

@ -1160,6 +1160,10 @@ export class PostStatStageChangeStatStageChangeAbAttr extends PostStatStageChang
} }
export class PreAttackAbAttr extends AbAttr { export class PreAttackAbAttr extends AbAttr {
willSucceedPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean {
return true;
}
applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean | Promise<boolean> { applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean | Promise<boolean> {
return false; return false;
} }
@ -1252,10 +1256,9 @@ export class FieldMultiplyStatAbAttr extends AbAttr {
this.canStack = canStack; this.canStack = canStack;
} }
willSucceed(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { willSucceedFieldStat(pokemon: Pokemon, passive: boolean, simulated: boolean, stat: Stat, statValue: Utils.NumberHolder, checkedPokemon: Pokemon, hasApplied: Utils.BooleanHolder, args: any[]): boolean {
if (!this.canStack && hasApplied.value) { return this.canStack || !hasApplied.value
return false; && this.stat === stat && checkedPokemon.getAbilityAttrs(FieldMultiplyStatAbAttr).every(attr => (attr as FieldMultiplyStatAbAttr).stat !== stat);
}
} }
/** /**
@ -1270,14 +1273,9 @@ export class FieldMultiplyStatAbAttr extends AbAttr {
* @returns true if this changed the checked stat, false otherwise. * @returns true if this changed the checked stat, false otherwise.
*/ */
applyFieldStat(pokemon: Pokemon, passive: boolean, simulated: boolean, stat: Stat, statValue: Utils.NumberHolder, checkedPokemon: Pokemon, hasApplied: Utils.BooleanHolder, args: any[]): boolean { applyFieldStat(pokemon: Pokemon, passive: boolean, simulated: boolean, stat: Stat, statValue: Utils.NumberHolder, checkedPokemon: Pokemon, hasApplied: Utils.BooleanHolder, args: any[]): boolean {
statValue.value *= this.multiplier;
hasApplied.value = true;
if (this.stat === stat && checkedPokemon.getAbilityAttrs(FieldMultiplyStatAbAttr).every(attr => (attr as FieldMultiplyStatAbAttr).stat !== stat)) { return true;
statValue.value *= this.multiplier;
hasApplied.value = true;
return true;
}
return false;
} }
} }
@ -1291,19 +1289,19 @@ export class MoveTypeChangeAbAttr extends PreAttackAbAttr {
super(true); super(true);
} }
willSucceedPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean {
return (this.condition && this.condition(pokemon, defender, move)) ?? false;
}
// TODO: Decouple this into two attributes (type change / power boost) // TODO: Decouple this into two attributes (type change / power boost)
applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
if (this.condition && this.condition(pokemon, defender, move)) { if (args[0] && args[0] instanceof Utils.NumberHolder) {
if (args[0] && args[0] instanceof Utils.NumberHolder) { args[0].value = this.newType;
args[0].value = this.newType;
}
if (args[1] && args[1] instanceof Utils.NumberHolder) {
args[1].value *= this.powerMultiplier;
}
return true;
} }
if (args[1] && args[1] instanceof Utils.NumberHolder) {
return false; args[1].value *= this.powerMultiplier;
}
return true;
} }
} }
@ -1315,37 +1313,38 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr {
super(true); super(true);
} }
applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { willSucceedPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean {
if ( if (!pokemon.isTerastallized() &&
!pokemon.isTerastallized() && move.id !== Moves.STRUGGLE &&
move.id !== Moves.STRUGGLE && /**
/** * Skip moves that call other moves because these moves generate a following move that will trigger this ability attribute
* Skip moves that call other moves because these moves generate a following move that will trigger this ability attribute * @see {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_call_other_moves}
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_call_other_moves} */
*/ !move.findAttr((attr) =>
!move.findAttr((attr) => attr instanceof RandomMovesetMoveAttr ||
attr instanceof RandomMovesetMoveAttr || attr instanceof RandomMoveAttr ||
attr instanceof RandomMoveAttr || attr instanceof NaturePowerAttr ||
attr instanceof NaturePowerAttr || attr instanceof CopyMoveAttr)) {
attr instanceof CopyMoveAttr
)
) {
const moveType = pokemon.getMoveType(move); const moveType = pokemon.getMoveType(move);
if (pokemon.getTypes().some((t) => t !== moveType)) { if (pokemon.getTypes().some((t) => t !== moveType)) {
if (!simulated) {
this.moveType = moveType;
pokemon.summonData.types = [ moveType ];
pokemon.updateInfo();
}
return true; return true;
} }
} }
return false; return false;
} }
applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
const moveType = pokemon.getMoveType(move);
if (!simulated) {
this.moveType = moveType;
pokemon.summonData.types = [ moveType ];
pokemon.updateInfo();
}
return true;
}
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
return i18next.t("abilityTriggers:pokemonTypeChange", { return i18next.t("abilityTriggers:pokemonTypeChange", {
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
@ -1367,6 +1366,10 @@ export class AddSecondStrikeAbAttr extends PreAttackAbAttr {
this.damageMultiplier = damageMultiplier; this.damageMultiplier = damageMultiplier;
} }
willSucceedPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean {
return move.canBeMultiStrikeEnhanced(pokemon, true);
}
/** /**
* If conditions are met, this doubles the move's hit count (via args[1]) * If conditions are met, this doubles the move's hit count (via args[1])
* or multiplies the damage of secondary strikes (via args[2]) * or multiplies the damage of secondary strikes (via args[2])
@ -1382,19 +1385,15 @@ export class AddSecondStrikeAbAttr extends PreAttackAbAttr {
applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
const hitCount = args[0] as Utils.NumberHolder; const hitCount = args[0] as Utils.NumberHolder;
const multiplier = args[1] as Utils.NumberHolder; const multiplier = args[1] as Utils.NumberHolder;
this.showAbility = !!hitCount?.value;
if (move.canBeMultiStrikeEnhanced(pokemon, true)) { if (hitCount?.value) {
this.showAbility = !!hitCount?.value; hitCount.value += 1;
if (hitCount?.value) {
hitCount.value += 1;
}
if (multiplier?.value && pokemon.turnData.hitsLeft === 1) {
multiplier.value = this.damageMultiplier;
}
return true;
} }
return false;
if (multiplier?.value && pokemon.turnData.hitsLeft === 1) {
multiplier.value = this.damageMultiplier;
}
return true;
} }
} }
@ -1414,6 +1413,10 @@ export class DamageBoostAbAttr extends PreAttackAbAttr {
this.condition = condition; this.condition = condition;
} }
willSucceedPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean {
return this.condition(pokemon, defender, move);
}
/** /**
* *
* @param pokemon the attacker pokemon * @param pokemon the attacker pokemon
@ -1424,13 +1427,9 @@ export class DamageBoostAbAttr extends PreAttackAbAttr {
* @returns true if the function succeeds * @returns true if the function succeeds
*/ */
applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
if (this.condition(pokemon, defender, move)) { const power = args[0] as Utils.NumberHolder;
const power = args[0] as Utils.NumberHolder; power.value = Math.floor(power.value * this.damageMultiplier);
power.value = Math.floor(power.value * this.damageMultiplier); return true;
return true;
}
return false;
} }
} }
@ -1444,14 +1443,13 @@ export class MovePowerBoostAbAttr extends VariableMovePowerAbAttr {
this.powerMultiplier = powerMultiplier; this.powerMultiplier = powerMultiplier;
} }
willSucceedPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean {
return this.condition(pokemon, defender, move);
}
applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
if (this.condition(pokemon, defender, move)) { (args[0] as Utils.NumberHolder).value *= this.powerMultiplier;
(args[0] as Utils.NumberHolder).value *= this.powerMultiplier; return true;
return true;
}
return false;
} }
} }
@ -1488,17 +1486,17 @@ export class VariableMovePowerBoostAbAttr extends VariableMovePowerAbAttr {
this.mult = mult; this.mult = mult;
} }
willSucceedPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
return this.mult(pokemon, defender, move) !== 1;
}
/** /**
* @override * @override
*/ */
applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move, args: any[]): boolean { applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move, args: any[]): boolean {
const multiplier = this.mult(pokemon, defender, move); const multiplier = this.mult(pokemon, defender, move);
if (multiplier !== 1) { (args[0] as Utils.NumberHolder).value *= multiplier;
(args[0] as Utils.NumberHolder).value *= multiplier; return true;
return true;
}
return false;
} }
} }
@ -5191,7 +5189,8 @@ export class PostDamageForceSwitchAbAttr extends PostDamageAbAttr {
export function applyAbAttrs(attrType: Constructor<AbAttr>, pokemon: Pokemon, cancelled: Utils.BooleanHolder | null, simulated: boolean = false, ...args: any[]): Promise<void> { export function applyAbAttrs(attrType: Constructor<AbAttr>, pokemon: Pokemon, cancelled: Utils.BooleanHolder | null, simulated: boolean = false, ...args: any[]): Promise<void> {
return applyAbAttrsInternal<AbAttr>(attrType, pokemon, (attr, passive) => attr.apply(pokemon, passive, simulated, cancelled, args), (attr, passive) => attr.willSucceed(pokemon, passive, simulated, args), args, false, simulated); return applyAbAttrsInternal<AbAttr>(attrType, pokemon, (attr, passive) => attr.apply(pokemon, passive, simulated, cancelled, args),
(attr, passive) => attr.willSucceed(pokemon, passive, simulated, args), args, false, simulated);
} }
export function applyPostBattleInitAbAttrs(attrType: Constructor<PostBattleInitAbAttr>, export function applyPostBattleInitAbAttrs(attrType: Constructor<PostBattleInitAbAttr>,
@ -5247,12 +5246,14 @@ export function applyPostDamageAbAttrs(attrType: Constructor<PostDamageAbAttr>,
*/ */
export function applyFieldStatMultiplierAbAttrs(attrType: Constructor<FieldMultiplyStatAbAttr>, export function applyFieldStatMultiplierAbAttrs(attrType: Constructor<FieldMultiplyStatAbAttr>,
pokemon: Pokemon, stat: Stat, statValue: Utils.NumberHolder, checkedPokemon: Pokemon, hasApplied: Utils.BooleanHolder, simulated: boolean = false, ...args: any[]): Promise<void> { pokemon: Pokemon, stat: Stat, statValue: Utils.NumberHolder, checkedPokemon: Pokemon, hasApplied: Utils.BooleanHolder, simulated: boolean = false, ...args: any[]): Promise<void> {
return applyAbAttrsInternal<FieldMultiplyStatAbAttr>(attrType, pokemon, (attr, passive) => attr.applyFieldStat(pokemon, passive, simulated, stat, statValue, checkedPokemon, hasApplied, args), args); return applyAbAttrsInternal<FieldMultiplyStatAbAttr>(attrType, pokemon, (attr, passive) => attr.applyFieldStat(pokemon, passive, simulated, stat, statValue, checkedPokemon, hasApplied, args),
(attr, passive) => attr.willSucceedFieldStat(pokemon, passive, simulated, stat, statValue, checkedPokemon, hasApplied, args), args);
} }
export function applyPreAttackAbAttrs(attrType: Constructor<PreAttackAbAttr>, export function applyPreAttackAbAttrs(attrType: Constructor<PreAttackAbAttr>,
pokemon: Pokemon, defender: Pokemon | null, move: Move, simulated: boolean = false, ...args: any[]): Promise<void> { pokemon: Pokemon, defender: Pokemon | null, move: Move, simulated: boolean = false, ...args: any[]): Promise<void> {
return applyAbAttrsInternal<PreAttackAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPreAttack(pokemon, passive, simulated, defender, move, args), args, false, simulated); return applyAbAttrsInternal<PreAttackAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPreAttack(pokemon, passive, simulated, defender, move, args),
(attr, passive) => attr.willSucceedPreAttack(pokemon, passive, simulated, defender, move, args), args, false, simulated);
} }
export function applyPostAttackAbAttrs(attrType: Constructor<PostAttackAbAttr>, export function applyPostAttackAbAttrs(attrType: Constructor<PostAttackAbAttr>,