Cleaned up flying press/etc moves; removed VariableMoveTypeMultiplierAttr

This commit is contained in:
Bertie690 2025-08-08 19:19:00 -04:00
parent 8a66cfe40b
commit 1f50ebdae0
3 changed files with 63 additions and 73 deletions

View File

@ -730,9 +730,7 @@ export class AttackTypeImmunityAbAttr extends TypeImmunityAbAttr {
override canApply(params: TypeMultiplierAbAttrParams): boolean { override canApply(params: TypeMultiplierAbAttrParams): boolean {
const { move } = params; const { move } = params;
return ( return (
move.category !== MoveCategory.STATUS && move.category !== MoveCategory.STATUS && !move.hasAttr("VariableMoveTypeChartAttr") && super.canApply(params)
!move.hasAttr("NeutralDamageAgainstFlyingTypeMultiplierAttr") &&
super.canApply(params)
); );
} }
} }

View File

@ -67,7 +67,7 @@ import { StatusEffect } from "#enums/status-effect";
import { SwitchType } from "#enums/switch-type"; import { SwitchType } from "#enums/switch-type";
import { WeatherType } from "#enums/weather-type"; import { WeatherType } from "#enums/weather-type";
import { MoveUsedEvent } from "#events/battle-scene"; import { MoveUsedEvent } from "#events/battle-scene";
import type { EnemyPokemon, Pokemon } from "#field/pokemon"; import { EnemyPokemon, Pokemon } from "#field/pokemon";
import { import {
AttackTypeBoosterModifier, AttackTypeBoosterModifier,
BerryModifier, BerryModifier,
@ -5349,48 +5349,60 @@ export class CombinedPledgeTypeAttr extends VariableMoveTypeAttr {
} }
} }
export class VariableMoveTypeMultiplierAttr extends MoveAttr { /**
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { * Attribute for moves which have a custom type chart interaction.
return false; */
} export class VariableMoveTypeChartAttr extends MoveAttr {
}
export class NeutralDamageAgainstFlyingTypeMultiplierAttr extends VariableMoveTypeMultiplierAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if (!target.getTag(BattlerTagType.IGNORE_FLYING)) {
const multiplier = args[0] as NumberHolder;
//When a flying type is hit, the first hit is always 1x multiplier.
if (target.isOfType(PokemonType.FLYING)) {
multiplier.value = 1;
}
return true;
}
return false;
}
}
export class IceNoEffectTypeAttr extends VariableMoveTypeMultiplierAttr {
/** /**
* Checks to see if the Target is Ice-Type or not. If so, the move will have no effect. * @param user - The {@linkcode Pokemon} using the move
* @param user n/a * @param target - The {@linkcode Pokemon} targeted by the move
* @param target The {@linkcode Pokemon} targeted by the move * @param move - The {@linkcode Move} with this attribute
* @param move n/a * @param args -
* @param args `[0]` a {@linkcode NumberHolder | NumberHolder} containing a type effectiveness multiplier * `[0]`: A {@linkcode NumberHolder} holding the type effectiveness
* @returns `true` if this Ice-type immunity applies; `false` otherwise * `[1]`: The target's entire defensive type profile.
* @returns `true` if application of the attribute succeeds
*/ */
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: [multiplier: NumberHolder, types: PokemonType[]]): boolean {
const multiplier = args[0] as NumberHolder; return false;
if (target.isOfType(PokemonType.ICE)) { }
multiplier.value = 0; }
/**
* Attribute to implement {@linkcode MoveId.FREEZE_DRY}'s guaranteed water type super effectiveness.
*/
export class FreezeDryAttr extends VariableMoveTypeChartAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: [NumberHolder, PokemonType[]]): boolean {
const [multiplier, types] = args;
if (types.includes(PokemonType.WATER)) {
multiplier.value = Math.max(multiplier.value, 2);
return true; return true;
} }
return false; return false;
} }
} }
export class FlyingTypeMultiplierAttr extends VariableMoveTypeMultiplierAttr { /**
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { * Attribute used by {@linkcode MoveId.THOUSAND_ARROWS} to cause it to deal a fixed 1x damage
* against all ungrounded flying types.
*/
export class NeutralDamageAgainstFlyingTypeAttr extends VariableMoveTypeChartAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: [multiplier: NumberHolder, types: PokemonType[]]): boolean {
const [multiplier, types] = args;
if (target.isGrounded() || !types.includes(PokemonType.FLYING)) {
return false;
}
multiplier.value = 1;
return true;
}
}
/**
* Attribute used by {@linkcode MoveId.FLYING_PRESS} to add the Flying Type to its type effectiveness.
*/
export class FlyingTypeMultiplierAttr extends VariableMoveTypeChartAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: [multiplier: NumberHolder, types: PokemonType[]]): boolean {
const multiplier = args[0] as NumberHolder; const multiplier = args[0] as NumberHolder;
multiplier.value *= target.getAttackTypeEffectiveness(PokemonType.FLYING, user); multiplier.value *= target.getAttackTypeEffectiveness(PokemonType.FLYING, user);
return true; return true;
@ -5398,39 +5410,19 @@ export class FlyingTypeMultiplierAttr extends VariableMoveTypeMultiplierAttr {
} }
/** /**
* Attribute for moves which have a custom type chart interaction. * Attribute used by {@linkcode MoveId.SHEER_COLD} to implement its Gen VII+ ice ineffectiveness.
*/ */
export class VariableMoveTypeChartAttr extends MoveAttr { export class IceNoEffectTypeAttr extends VariableMoveTypeChartAttr {
/** apply(user: Pokemon, target: Pokemon, move: Move, args: [multiplier: NumberHolder, types: PokemonType[]]): boolean {
* @param user {@linkcode Pokemon} using the move const [multiplier, types] = args;
* @param target {@linkcode Pokemon} target of the move if (types.includes(PokemonType.ICE)) {
* @param move {@linkcode Move} with this attribute multiplier.value = 0;
* @param args [0] {@linkcode NumberHolder} holding the type effectiveness return true;
* @param args [1] A single defensive type of the target }
*
* @returns true if application of the attribute succeeds
*/
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
return false; return false;
} }
} }
/**
* This class forces Freeze-Dry to be super effective against Water Type.
*/
export class FreezeDryAttr extends VariableMoveTypeChartAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const multiplier = args[0] as NumberHolder;
const defType = args[1] as PokemonType;
if (defType === PokemonType.WATER) {
multiplier.value = 2;
return true;
} else {
return false;
}
}
}
export class OneHitKOAccuracyAttr extends VariableAccuracyAttr { export class OneHitKOAccuracyAttr extends VariableAccuracyAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
@ -5916,8 +5908,8 @@ export class ProtectAttr extends AddBattlerTagAttr {
for (const turnMove of user.getLastXMoves(-1).slice()) { for (const turnMove of user.getLastXMoves(-1).slice()) {
if ( if (
// Quick & Wide guard increment the Protect counter without using it for fail chance // Quick & Wide guard increment the Protect counter without using it for fail chance
!(allMoves[turnMove.move].hasAttr("ProtectAttr") || !(allMoves[turnMove.move].hasAttr("ProtectAttr") ||
[MoveId.QUICK_GUARD, MoveId.WIDE_GUARD].includes(turnMove.move)) || [MoveId.QUICK_GUARD, MoveId.WIDE_GUARD].includes(turnMove.move)) ||
turnMove.result !== MoveResult.SUCCESS turnMove.result !== MoveResult.SUCCESS
) { ) {
break; break;
@ -8146,7 +8138,9 @@ export class UpperHandCondition extends MoveCondition {
} }
} }
export class HitsSameTypeAttr extends VariableMoveTypeMultiplierAttr { // TODO: Does this need to extend from this?
// The only reason it might is to show ineffectiveness text but w/e
export class HitsSameTypeAttr extends VariableMoveTypeChartAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const multiplier = args[0] as NumberHolder; const multiplier = args[0] as NumberHolder;
if (!user.getTypes(true).some(type => target.getTypes(true).includes(type))) { if (!user.getTypes(true).some(type => target.getTypes(true).includes(type))) {
@ -8417,8 +8411,7 @@ const MoveAttrs = Object.freeze({
TeraStarstormTypeAttr, TeraStarstormTypeAttr,
MatchUserTypeAttr, MatchUserTypeAttr,
CombinedPledgeTypeAttr, CombinedPledgeTypeAttr,
VariableMoveTypeMultiplierAttr, NeutralDamageAgainstFlyingTypeAttr,
NeutralDamageAgainstFlyingTypeMultiplierAttr,
IceNoEffectTypeAttr, IceNoEffectTypeAttr,
FlyingTypeMultiplierAttr, FlyingTypeMultiplierAttr,
VariableMoveTypeChartAttr, VariableMoveTypeChartAttr,
@ -10454,7 +10447,7 @@ export function initMoves() {
.attr(HitHealAttr, 0.75) .attr(HitHealAttr, 0.75)
.triageMove(), .triageMove(),
new AttackMove(MoveId.THOUSAND_ARROWS, PokemonType.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6) new AttackMove(MoveId.THOUSAND_ARROWS, PokemonType.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6)
.attr(NeutralDamageAgainstFlyingTypeMultiplierAttr) .attr(NeutralDamageAgainstFlyingTypeAttr)
.attr(FallDownAttr) .attr(FallDownAttr)
.attr(HitsTagAttr, BattlerTagType.FLYING) .attr(HitsTagAttr, BattlerTagType.FLYING)
.attr(HitsTagAttr, BattlerTagType.FLOATING) .attr(HitsTagAttr, BattlerTagType.FLOATING)

View File

@ -2400,7 +2400,6 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
: 1, : 1,
); );
applyMoveAttrs("VariableMoveTypeMultiplierAttr", source, this, move, typeMultiplier);
if (this.getTypes(true, true).find(t => move.isTypeImmune(source, this, t))) { if (this.getTypes(true, true).find(t => move.isTypeImmune(source, this, t))) {
typeMultiplier.value = 0; typeMultiplier.value = 0;
} }