Update ability and move logic to use getMoveCategory instead of move.category

This commit is contained in:
PieonFire 2025-08-11 11:08:01 +02:00
parent 6743b1214a
commit 0d074d4b42

View File

@ -1982,11 +1982,11 @@ export class AllyMoveCategoryPowerBoostAbAttr extends FieldMovePowerBoostAbAttr
* @param powerMultiplier - The multiplier to apply to the move's power.
*/
constructor(boostedCategories: MoveCategory[], powerMultiplier: number) {
super((_pokemon, _defender, move) => {
super((pokemon, defender, move) => {
if (isNullOrUndefined(pokemon)) {
return false;
}
return boostedCategories.includes(_pokemon.getMoveCategory(_defender, move));
return boostedCategories.includes(pokemon.getMoveCategory(defender, move));
}, powerMultiplier);
}
}
@ -2119,12 +2119,12 @@ export abstract class PostAttackAbAttr extends AbAttr {
/** The default `attackCondition` requires that the selected move is a damaging move */
constructor(
attackCondition: PokemonAttackCondition = (_user, _target, move) => {
attackCondition: PokemonAttackCondition = (user, target, move) => {
if (isNullOrUndefined(user)) {
return false;
}
return _user.getMoveCategory(_target, move) !== MoveCategory.STATUS;
return user.getMoveCategory(target, move) !== MoveCategory.STATUS;
},
showAbility = true,
) {
@ -6944,11 +6944,11 @@ export function initAbilities() {
.attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.TRUANT, 1, false),
new Ability(AbilityId.HUSTLE, 3)
.attr(StatMultiplierAbAttr, Stat.ATK, 1.5)
.attr(StatMultiplierAbAttr, Stat.ACC, 0.8, (_user, _target, move) => {
if (_user === null) {
.attr(StatMultiplierAbAttr, Stat.ACC, 0.8, (user, target, move) => {
if (user === null) {
return false
}
return _user.getMoveCategory(_target, move) === MoveCategory.PHYSICAL
return user.getMoveCategory(target, move) === MoveCategory.PHYSICAL
}),
new Ability(AbilityId.CUTE_CHARM, 3)
.attr(PostDefendContactApplyTagChanceAbAttr, 30, BattlerTagType.INFATUATED),
@ -7181,8 +7181,8 @@ export function initAbilities() {
.attr(AlliedFieldDamageReductionAbAttr, 0.75)
.ignorable(),
new Ability(AbilityId.WEAK_ARMOR, 5)
.attr(PostDefendStatStageChangeAbAttr, (_target, _user, move) => _user.getMoveCategory(_target, move) === MoveCategory.PHYSICAL, Stat.DEF, -1)
.attr(PostDefendStatStageChangeAbAttr, (_target, _user, move) => _user.getMoveCategory(_target, move) === MoveCategory.PHYSICAL, Stat.SPD, 2),
.attr(PostDefendStatStageChangeAbAttr, (target, user, move) => user.getMoveCategory(target, move) === MoveCategory.PHYSICAL, Stat.DEF, -1)
.attr(PostDefendStatStageChangeAbAttr, (target, user, move) => user.getMoveCategory(target, move) === MoveCategory.PHYSICAL, Stat.SPD, 2),
new Ability(AbilityId.HEAVY_METAL, 5)
.attr(WeightMultiplierAbAttr, 2)
.ignorable(),
@ -7193,14 +7193,14 @@ export function initAbilities() {
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, _user, _move) => target.isFullHp(), 0.5)
.ignorable(),
new Ability(AbilityId.TOXIC_BOOST, 5)
.attr(MovePowerBoostAbAttr, (user, _target, move) => {
.attr(MovePowerBoostAbAttr, (user, target, move) => {
if (user===null) { return false; }
return user.getMoveCategory(_target, move) === MoveCategory.PHYSICAL && (user?.status?.effect === StatusEffect.POISON || user?.status?.effect === StatusEffect.TOXIC)
return user.getMoveCategory(target, move) === MoveCategory.PHYSICAL && (user?.status?.effect === StatusEffect.POISON || user?.status?.effect === StatusEffect.TOXIC)
}, 1.5),
new Ability(AbilityId.FLARE_BOOST, 5)
.attr(MovePowerBoostAbAttr, (user, _target, move) => {
.attr(MovePowerBoostAbAttr, (user, target, move) => {
if (user===null) { return false; }
return user.getMoveCategory(_target, move) === MoveCategory.SPECIAL && user?.status?.effect === StatusEffect.BURN
return user.getMoveCategory(target, move) === MoveCategory.SPECIAL && user?.status?.effect === StatusEffect.BURN
}, 1.5),
new Ability(AbilityId.HARVEST, 5)
.attr(
@ -7262,11 +7262,11 @@ export function initAbilities() {
new Ability(AbilityId.MOXIE, 5)
.attr(PostVictoryStatStageChangeAbAttr, Stat.ATK, 1),
new Ability(AbilityId.JUSTIFIED, 5)
.attr(PostDefendStatStageChangeAbAttr, (_target, user, move) => user.getMoveType(move) === PokemonType.DARK && user.getMoveCategory(_target, move) !== MoveCategory.STATUS, Stat.ATK, 1),
.attr(PostDefendStatStageChangeAbAttr, (target, user, move) => user.getMoveType(move) === PokemonType.DARK && user.getMoveCategory(target, move) !== MoveCategory.STATUS, Stat.ATK, 1),
new Ability(AbilityId.RATTLED, 5)
.attr(PostDefendStatStageChangeAbAttr, (_target, user, move) => {
.attr(PostDefendStatStageChangeAbAttr, (target, user, move) => {
const moveType = user.getMoveType(move);
return user.getMoveCategory(_target, move) !== MoveCategory.STATUS
return user.getMoveCategory(target, move) !== MoveCategory.STATUS
&& (moveType === PokemonType.DARK || moveType === PokemonType.BUG || moveType === PokemonType.GHOST);
}, Stat.SPD, 1)
.attr(PostIntimidateStatStageChangeAbAttr, [ Stat.SPD ], 1),
@ -7280,7 +7280,7 @@ export function initAbilities() {
.attr(TypeImmunityStatStageChangeAbAttr, PokemonType.GRASS, Stat.ATK, 1)
.ignorable(),
new Ability(AbilityId.PRANKSTER, 5)
.attr(ChangeMovePriorityAbAttr, (_pokemon, move: Move) => _pokemon.getMoveCategory(_pokemon, move) === MoveCategory.STATUS, 1),
.attr(ChangeMovePriorityAbAttr, (pokemon, move: Move) => pokemon.getMoveCategory(pokemon, move) === MoveCategory.STATUS, 1),
new Ability(AbilityId.SAND_FORCE, 5)
.attr(MoveTypePowerBoostAbAttr, PokemonType.ROCK, 1.3)
.attr(MoveTypePowerBoostAbAttr, PokemonType.GROUND, 1.3)
@ -7333,8 +7333,8 @@ export function initAbilities() {
// TODO: needs testing on interaction with weather blockage
.edgeCase(),
new Ability(AbilityId.FUR_COAT, 6)
.attr(ReceivedMoveDamageMultiplierAbAttr, (_target, _user, move) => {
const isPhysicalMove = _user.getMoveCategory(_target, move) === MoveCategory.PHYSICAL
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => {
const isPhysicalMove = user.getMoveCategory(target, move) === MoveCategory.PHYSICAL
// This is for a theoretical move where Fur Coat shouldn't apply, in case it's implemented later
const moveIsPhysicalAndActuallyHitsDef = isPhysicalMove && !move.hasAttr("VariableDefAttr")
const moveIsSpecialButHitsPhysicalInstead = move.hasAttr("DefDefAttr")
@ -7411,7 +7411,7 @@ export function initAbilities() {
.attr(PreLeaveFieldClearWeatherAbAttr)
.bypassFaint(),
new Ability(AbilityId.STAMINA, 7)
.attr(PostDefendStatStageChangeAbAttr, (_target, _user, move) => _user.getMoveCategory(_target, move) !== MoveCategory.STATUS, Stat.DEF, 1),
.attr(PostDefendStatStageChangeAbAttr, (target, user, move) => user.getMoveCategory(target, move) !== MoveCategory.STATUS, Stat.DEF, 1),
new Ability(AbilityId.WIMP_OUT, 7)
.attr(PostDamageForceSwitchAbAttr)
.edgeCase(), // Should not trigger when hurting itself in confusion, causes Fake Out to fail turn 1 and succeed turn 2 if pokemon is switched out before battle start via playing in Switch Mode
@ -7419,7 +7419,7 @@ export function initAbilities() {
.attr(PostDamageForceSwitchAbAttr)
.edgeCase(), // Should not trigger when hurting itself in confusion, causes Fake Out to fail turn 1 and succeed turn 2 if pokemon is switched out before battle start via playing in Switch Mode
new Ability(AbilityId.WATER_COMPACTION, 7)
.attr(PostDefendStatStageChangeAbAttr, (_target, user, move) => user.getMoveType(move) === PokemonType.WATER && user.getMoveCategory(_target, move) !== MoveCategory.STATUS, Stat.DEF, 2),
.attr(PostDefendStatStageChangeAbAttr, (target, user, move) => user.getMoveType(move) === PokemonType.WATER && user.getMoveCategory(target, move) !== MoveCategory.STATUS, Stat.DEF, 2),
new Ability(AbilityId.MERCILESS, 7)
.attr(ConditionalCritAbAttr, (_user, target, _move) => target?.status?.effect === StatusEffect.TOXIC || target?.status?.effect === StatusEffect.POISON),
new Ability(AbilityId.SHIELDS_DOWN, 7, -1)
@ -7448,7 +7448,7 @@ export function initAbilities() {
new Ability(AbilityId.STEELWORKER, 7)
.attr(MoveTypePowerBoostAbAttr, PokemonType.STEEL),
new Ability(AbilityId.BERSERK, 7)
.attr(PostDefendHpGatedStatStageChangeAbAttr, (_target, _user, move) => _user.getMoveCategory(_target, move) !== MoveCategory.STATUS, 0.5, [ Stat.SPATK ], 1)
.attr(PostDefendHpGatedStatStageChangeAbAttr, (target, user, move) => user.getMoveCategory(target, move) !== MoveCategory.STATUS, 0.5, [ Stat.SPATK ], 1)
.condition(getSheerForceHitDisableAbCondition()),
new Ability(AbilityId.SLUSH_RUSH, 7)
.attr(StatMultiplierAbAttr, Stat.SPD, 2)
@ -7602,7 +7602,7 @@ export function initAbilities() {
.attr(FetchBallAbAttr)
.condition(getOncePerBattleCondition(AbilityId.BALL_FETCH)),
new Ability(AbilityId.COTTON_DOWN, 8)
.attr(PostDefendStatStageChangeAbAttr, (_target, _user, move) => _user.getMoveCategory(_target, move) !== MoveCategory.STATUS, Stat.SPD, -1, false, true)
.attr(PostDefendStatStageChangeAbAttr, (target, user, move) => user.getMoveCategory(target, move) !== MoveCategory.STATUS, Stat.SPD, -1, false, true)
.bypassFaint(),
new Ability(AbilityId.PROPELLER_TAIL, 8)
.attr(BlockRedirectAbAttr),
@ -7625,9 +7625,9 @@ export function initAbilities() {
new Ability(AbilityId.STALWART, 8)
.attr(BlockRedirectAbAttr),
new Ability(AbilityId.STEAM_ENGINE, 8)
.attr(PostDefendStatStageChangeAbAttr, (_target, user, move) => {
.attr(PostDefendStatStageChangeAbAttr, (target, user, move) => {
const moveType = user.getMoveType(move);
return user.getMoveCategory(_target, move) !== MoveCategory.STATUS
return user.getMoveCategory(target, move) !== MoveCategory.STATUS
&& (moveType === PokemonType.FIRE || moveType === PokemonType.WATER);
}, Stat.SPD, 6),
new Ability(AbilityId.PUNK_ROCK, 8)
@ -7635,10 +7635,10 @@ export function initAbilities() {
.attr(ReceivedMoveDamageMultiplierAbAttr, (_target, _user, move) => move.hasFlag(MoveFlags.SOUND_BASED), 0.5)
.ignorable(),
new Ability(AbilityId.SAND_SPIT, 8)
.attr(PostDefendWeatherChangeAbAttr, WeatherType.SANDSTORM, (_target, _user, move) => _user.getMoveCategory(_target, move) !== MoveCategory.STATUS)
.attr(PostDefendWeatherChangeAbAttr, WeatherType.SANDSTORM, (target, user, move) => user.getMoveCategory(target, move) !== MoveCategory.STATUS)
.bypassFaint(),
new Ability(AbilityId.ICE_SCALES, 8)
.attr(ReceivedMoveDamageMultiplierAbAttr, (_target, _user, move) => _user.getMoveCategory(_target, move) === MoveCategory.SPECIAL, 0.5)
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => user.getMoveCategory(target, move) === MoveCategory.SPECIAL, 0.5)
.ignorable(),
new Ability(AbilityId.RIPEN, 8)
.attr(DoubleBerryEffectAbAttr),
@ -7652,7 +7652,7 @@ export function initAbilities() {
// When weather changes to HAIL or SNOW while pokemon is fielded, add BattlerTagType.ICE_FACE
.attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.ICE_FACE, 0, WeatherType.HAIL, WeatherType.SNOW)
.attr(FormBlockDamageAbAttr,
(target, _user, move) => _user.getMoveCategory(target, move) === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE), 0, BattlerTagType.ICE_FACE,
(target, user, move) => user.getMoveCategory(target, move) === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE), 0, BattlerTagType.ICE_FACE,
(pokemon, abilityName) => i18next.t("abilityTriggers:iceFaceAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName }))
.attr(PostBattleInitFormChangeAbAttr, () => 0)
.uncopiable()
@ -7732,13 +7732,13 @@ export function initAbilities() {
.attr(PostDefendTerrainChangeAbAttr, TerrainType.GRASSY)
.bypassFaint(),
new Ability(AbilityId.THERMAL_EXCHANGE, 9)
.attr(PostDefendStatStageChangeAbAttr, (_target, user, move) => user.getMoveType(move) === PokemonType.FIRE && user.getMoveCategory(_target, move) !== MoveCategory.STATUS, Stat.ATK, 1)
.attr(PostDefendStatStageChangeAbAttr, (target, user, move) => user.getMoveType(move) === PokemonType.FIRE && user.getMoveCategory(target, move) !== MoveCategory.STATUS, Stat.ATK, 1)
.attr(StatusEffectImmunityAbAttr, StatusEffect.BURN)
.attr(PostSummonHealStatusAbAttr, StatusEffect.BURN)
.ignorable(),
new Ability(AbilityId.ANGER_SHELL, 9)
.attr(PostDefendHpGatedStatStageChangeAbAttr, (_target, _user, move) => _user.getMoveCategory(_target, move) !== MoveCategory.STATUS, 0.5, [ Stat.ATK, Stat.SPATK, Stat.SPD ], 1)
.attr(PostDefendHpGatedStatStageChangeAbAttr, (_target, _user, move) => _user.getMoveCategory(_target, move) !== MoveCategory.STATUS, 0.5, [ Stat.DEF, Stat.SPDEF ], -1)
.attr(PostDefendHpGatedStatStageChangeAbAttr, (target, user, move) => user.getMoveCategory(target, move) !== MoveCategory.STATUS, 0.5, [ Stat.ATK, Stat.SPATK, Stat.SPD ], 1)
.attr(PostDefendHpGatedStatStageChangeAbAttr, (target, user, move) => user.getMoveCategory(target, move) !== MoveCategory.STATUS, 0.5, [ Stat.DEF, Stat.SPDEF ], -1)
.condition(getSheerForceHitDisableAbCondition()),
new Ability(AbilityId.PURIFYING_SALT, 9)
.attr(StatusEffectImmunityAbAttr)
@ -7775,7 +7775,7 @@ export function initAbilities() {
.unreplaceable()
.edgeCase(), // Encore, Frenzy, and other non-`TURN_END` tags don't lapse correctly on the commanding Pokemon.
new Ability(AbilityId.ELECTROMORPHOSIS, 9)
.attr(PostDefendApplyBattlerTagAbAttr, (_target, _user, move) => _user.getMoveCategory(_target, move) !== MoveCategory.STATUS, BattlerTagType.CHARGED),
.attr(PostDefendApplyBattlerTagAbAttr, (target, user, move) => user.getMoveCategory(target, move) !== MoveCategory.STATUS, BattlerTagType.CHARGED),
new Ability(AbilityId.PROTOSYNTHESIS, 9, -2)
.conditionalAttr(getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN), PostSummonAddBattlerTagAbAttr, BattlerTagType.PROTOSYNTHESIS, 0, true)
.attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.PROTOSYNTHESIS, 0, WeatherType.SUNNY, WeatherType.HARSH_SUN)
@ -7829,7 +7829,7 @@ export function initAbilities() {
new Ability(AbilityId.COSTAR, 9, -2)
.attr(PostSummonCopyAllyStatsAbAttr),
new Ability(AbilityId.TOXIC_DEBRIS, 9)
.attr(PostDefendApplyArenaTrapTagAbAttr, (_target, _user, move) => _user.getMoveCategory(_target, move) === MoveCategory.PHYSICAL, ArenaTagType.TOXIC_SPIKES)
.attr(PostDefendApplyArenaTrapTagAbAttr, (target, user, move) => user.getMoveCategory(target, move) === MoveCategory.PHYSICAL, ArenaTagType.TOXIC_SPIKES)
.bypassFaint(),
new Ability(AbilityId.ARMOR_TAIL, 9)
.attr(FieldPriorityMoveImmunityAbAttr)
@ -7838,9 +7838,9 @@ export function initAbilities() {
.attr(TypeImmunityHealAbAttr, PokemonType.GROUND)
.ignorable(),
new Ability(AbilityId.MYCELIUM_MIGHT, 9)
.attr(ChangeMovePriorityAbAttr, (_pokemon, move) => _pokemon.getMoveCategory(_pokemon, move) === MoveCategory.STATUS, -0.2)
.attr(PreventBypassSpeedChanceAbAttr, (_pokemon, move) => _pokemon.getMoveCategory(_pokemon, move) === MoveCategory.STATUS)
.attr(MoveAbilityBypassAbAttr, (_pokemon, move: Move) => _pokemon.getMoveCategory(_pokemon, move) === MoveCategory.STATUS),
.attr(ChangeMovePriorityAbAttr, (pokemon, move) => pokemon.getMoveCategory(pokemon, move) === MoveCategory.STATUS, -0.2)
.attr(PreventBypassSpeedChanceAbAttr, (pokemon, move) => pokemon.getMoveCategory(pokemon, move) === MoveCategory.STATUS)
.attr(MoveAbilityBypassAbAttr, (pokemon, move: Move) => pokemon.getMoveCategory(pokemon, move) === MoveCategory.STATUS),
new Ability(AbilityId.MINDS_EYE, 9)
.attr(IgnoreTypeImmunityAbAttr, PokemonType.GHOST, [ PokemonType.NORMAL, PokemonType.FIGHTING ])
.attr(ProtectStatAbAttr, Stat.ACC)