mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-10 18:32:16 +02:00
Use BattlerTag for move-disabling effects
This commit is contained in:
parent
7ce209dd02
commit
7847d1c445
@ -971,22 +971,16 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr {
|
||||
}
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
if (!attacker.summonData.disabledMove) {
|
||||
if (attacker.getTag(BattlerTagType.DISABLED) === null) {
|
||||
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && !attacker.isMax()) {
|
||||
this.attacker = attacker;
|
||||
this.move = move;
|
||||
|
||||
attacker.summonData.disabledMove = move.id;
|
||||
attacker.summonData.disabledTurns = 4;
|
||||
this.attacker.addTag(BattlerTagType.DISABLED, 4, 0, pokemon.id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
return getPokemonMessage(this.attacker, `'s ${this.move.name}\nwas disabled!`);
|
||||
}
|
||||
}
|
||||
|
||||
export class PostStatChangeStatChangeAbAttr extends PostStatChangeAbAttr {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { CommonAnim, CommonBattleAnim } from "./battle-anims";
|
||||
import { CommonAnimPhase, MoveEffectPhase, MovePhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase } from "../phases";
|
||||
import { CommonAnimPhase, MessagePhase, MoveEffectPhase, MovePhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase } from "../phases";
|
||||
import { getPokemonMessage, getPokemonNameWithAffix } from "../messages";
|
||||
import Pokemon, { MoveResult, HitResult } from "../field/pokemon";
|
||||
import { Stat, getStatName } from "./pokemon-stat";
|
||||
@ -17,6 +17,7 @@ import { BattleStat } from "./battle-stat";
|
||||
import { allAbilities } from "./ability";
|
||||
import { SpeciesFormChangeManualTrigger } from "./pokemon-forms";
|
||||
import { Species } from "./enums/species";
|
||||
import i18next from "i18next";
|
||||
|
||||
export enum BattlerTagLapseType {
|
||||
FAINT,
|
||||
@ -91,6 +92,84 @@ export interface TerrainBattlerTag {
|
||||
terrainTypes: TerrainType[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for tags that disable moves. Descendants can override {@linkcode moveIsDisabled} to disable moves that match a condition.
|
||||
*/
|
||||
export abstract class DisablingBattlerTag extends BattlerTag {
|
||||
public abstract moveIsDisabled(move: Moves): boolean;
|
||||
|
||||
constructor(tagType: BattlerTagType, lapseType?: BattlerTagLapseType, turnCount?: integer, sourceMove?: Moves, sourceId?: integer) {
|
||||
super(tagType, lapseType ?? BattlerTagLapseType.TURN_END, turnCount ?? 3, sourceMove, sourceId);
|
||||
}
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||
if (!super.lapse(pokemon, lapseType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag representing the "disabling" effect performed by {@linkcode Moves.DISABLE} and {@linkcode Abilities.CURSED_BODY}.
|
||||
* When the tag is added, the last used move of the tag holder is set as the disabled move.
|
||||
*/
|
||||
export class DisabledTag extends DisablingBattlerTag {
|
||||
/** The move being disabled. Gets set when {@linkcode onAdd} is called for this tag. */
|
||||
private moveId: integer = 0;
|
||||
|
||||
public override moveIsDisabled(move: Moves): boolean {
|
||||
return move === this.moveId;
|
||||
}
|
||||
|
||||
constructor(turnCount: integer, sourceId: integer) {
|
||||
super(BattlerTagType.DISABLED, BattlerTagLapseType.TURN_END, turnCount, Moves.DISABLE, sourceId);
|
||||
}
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||
if (!super.lapse(pokemon, lapseType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.moveId === 0) {
|
||||
console.warn(`attempt to disable move ID 0 on ${pokemon}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
const history = pokemon.getLastXMoves();
|
||||
|
||||
if (history.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const move = history.find(m => m.move !== Moves.NONE);
|
||||
if (move === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.moveId = move.move;
|
||||
|
||||
pokemon.scene.queueMessage(this.generateAddMessage(pokemon));
|
||||
}
|
||||
|
||||
onRemove(pokemon: Pokemon): void {
|
||||
if (this.moveId === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
pokemon.scene.pushPhase(new MessagePhase(pokemon.scene, i18next.t("battle:notDisabled", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: allMoves[this.moveId].name })));
|
||||
}
|
||||
|
||||
private generateAddMessage(pokemon: Pokemon): string {
|
||||
return getPokemonMessage(pokemon, `'s ${allMoves[this.moveId].name}\nwas disabled!`);
|
||||
}
|
||||
}
|
||||
|
||||
export class RechargingTag extends BattlerTag {
|
||||
constructor(sourceMove: Moves) {
|
||||
super(BattlerTagType.RECHARGING, BattlerTagLapseType.PRE_MOVE, 1, sourceMove);
|
||||
@ -1522,6 +1601,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
|
||||
return new DestinyBondTag(sourceMove, sourceId);
|
||||
case BattlerTagType.ICE_FACE:
|
||||
return new IceFaceTag(sourceMove);
|
||||
case BattlerTagType.DISABLED:
|
||||
return new DisabledTag(turnCount, sourceId);
|
||||
case BattlerTagType.NONE:
|
||||
default:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
||||
|
@ -58,5 +58,6 @@ export enum BattlerTagType {
|
||||
MAGNET_RISEN = "MAGNET_RISEN",
|
||||
MINIMIZED = "MINIMIZED",
|
||||
DESTINY_BOND = "DESTINY_BOND",
|
||||
ICE_FACE = "ICE_FACE"
|
||||
ICE_FACE = "ICE_FACE",
|
||||
DISABLED = "DISABLED"
|
||||
}
|
||||
|
@ -3690,70 +3690,6 @@ export class TypelessAttr extends MoveAttr { }
|
||||
*/
|
||||
export class BypassRedirectAttr extends MoveAttr { }
|
||||
|
||||
export class DisableMoveAttr extends MoveEffectAttr {
|
||||
constructor() {
|
||||
super(false);
|
||||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (!super.apply(user, target, move, args)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const moveQueue = target.getLastXMoves();
|
||||
let turnMove: TurnMove;
|
||||
while (moveQueue.length) {
|
||||
turnMove = moveQueue.shift();
|
||||
if (turnMove.virtual) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const moveIndex = target.getMoveset().findIndex(m => m.moveId === turnMove.move);
|
||||
if (moveIndex === -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const disabledMove = target.getMoveset()[moveIndex];
|
||||
target.summonData.disabledMove = disabledMove.moveId;
|
||||
target.summonData.disabledTurns = 4;
|
||||
|
||||
user.scene.queueMessage(getPokemonMessage(target, `'s ${disabledMove.getName()}\nwas disabled!`));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
getCondition(): MoveConditionFunc {
|
||||
return (user, target, move) => {
|
||||
if (target.summonData.disabledMove || target.isMax()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const moveQueue = target.getLastXMoves();
|
||||
let turnMove: TurnMove;
|
||||
while (moveQueue.length) {
|
||||
turnMove = moveQueue.shift();
|
||||
if (turnMove.virtual) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const move = target.getMoveset().find(m => m.moveId === turnMove.move);
|
||||
if (!move) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
|
||||
return -5;
|
||||
}
|
||||
}
|
||||
|
||||
export class FrenzyAttr extends MoveEffectAttr {
|
||||
constructor() {
|
||||
super(true, MoveEffectTrigger.HIT);
|
||||
@ -3842,6 +3778,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
|
||||
case BattlerTagType.NIGHTMARE:
|
||||
case BattlerTagType.DROWSY:
|
||||
case BattlerTagType.NO_CRIT:
|
||||
case BattlerTagType.DISABLED:
|
||||
return -5;
|
||||
case BattlerTagType.SEEDED:
|
||||
case BattlerTagType.SALT_CURED:
|
||||
@ -5306,6 +5243,9 @@ export class hitsSameTypeAttr extends VariableMoveTypeMultiplierAttr {
|
||||
|
||||
const unknownTypeCondition: MoveConditionFunc = (user, target, move) => !user.getTypes().includes(Type.UNKNOWN);
|
||||
|
||||
/** Ensures that the target has at least one non-virtual, non-NONE move in its history. */
|
||||
const targetHasMoveHistoryCondition: MoveConditionFunc = (user, target, move) => target.getLastXMoves().filter(m => m.move !== Moves.NONE && !m.virtual).length >= 1;
|
||||
|
||||
export type MoveTargetSet = {
|
||||
targets: BattlerIndex[];
|
||||
multiple: boolean;
|
||||
@ -5506,7 +5446,8 @@ export function initMoves() {
|
||||
new AttackMove(Moves.SONIC_BOOM, Type.NORMAL, MoveCategory.SPECIAL, -1, 90, 20, -1, 0, 1)
|
||||
.attr(FixedDamageAttr, 20),
|
||||
new StatusMove(Moves.DISABLE, Type.NORMAL, 100, 20, -1, 0, 1)
|
||||
.attr(DisableMoveAttr)
|
||||
.attr(AddBattlerTagAttr, BattlerTagType.DISABLED, false, true, 4, 4)
|
||||
.condition(targetHasMoveHistoryCondition)
|
||||
.condition(failOnMaxCondition),
|
||||
new AttackMove(Moves.ACID, Type.POISON, MoveCategory.SPECIAL, 40, 100, 30, 10, 0, 1)
|
||||
.attr(StatChangeAttr, BattleStat.SPDEF, -1)
|
||||
|
@ -19,7 +19,7 @@ import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEv
|
||||
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "../data/tms";
|
||||
import { DamagePhase, FaintPhase, LearnMovePhase, ObtainStatusEffectPhase, StatChangePhase, SwitchSummonPhase, ToggleDoublePositionPhase } from "../phases";
|
||||
import { BattleStat } from "../data/battle-stat";
|
||||
import { BattlerTag, BattlerTagLapseType, EncoreTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, getBattlerTag } from "../data/battler-tags";
|
||||
import { BattlerTag, BattlerTagLapseType, DisablingBattlerTag, EncoreTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, getBattlerTag } from "../data/battler-tags";
|
||||
import { BattlerTagType } from "../data/enums/battler-tag-type";
|
||||
import { Species } from "../data/enums/species";
|
||||
import { WeatherType } from "../data/weather";
|
||||
@ -2139,6 +2139,18 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.updateInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether a move is currently disabled for this Pokemon.
|
||||
* @see {@linkcode DisablingBattlerTag}
|
||||
*/
|
||||
isMoveDisabled(moveId: Moves): boolean {
|
||||
for (const tag of this.findTags(t => t instanceof DisablingBattlerTag)) {
|
||||
if ((tag as DisablingBattlerTag).moveIsDisabled(moveId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getMoveHistory(): TurnMove[] {
|
||||
return this.battleSummonData.moveHistory;
|
||||
}
|
||||
@ -3749,8 +3761,6 @@ export interface AttackMoveResult {
|
||||
export class PokemonSummonData {
|
||||
public battleStats: integer[] = [ 0, 0, 0, 0, 0, 0, 0 ];
|
||||
public moveQueue: QueuedMove[] = [];
|
||||
public disabledMove: Moves = Moves.NONE;
|
||||
public disabledTurns: integer = 0;
|
||||
public tags: BattlerTag[] = [];
|
||||
public abilitySuppressed: boolean = false;
|
||||
|
||||
@ -3844,9 +3854,16 @@ export class PokemonMove {
|
||||
}
|
||||
|
||||
isUsable(pokemon: Pokemon, ignorePp?: boolean): boolean {
|
||||
if (this.moveId && pokemon.summonData?.disabledMove === this.moveId) {
|
||||
if (!this.moveId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const tag of pokemon.findTags(t => t instanceof DisablingBattlerTag)) {
|
||||
if ((tag as DisablingBattlerTag).moveIsDisabled(this.moveId)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (ignorePp || this.ppUsed < this.getMovePp() || this.getMove().pp === -1) && !this.getMove().name.endsWith(" (N)");
|
||||
}
|
||||
|
||||
|
@ -1916,7 +1916,7 @@ export class CommandPhase extends FieldPhase {
|
||||
|
||||
// Decides between a Disabled, Not Implemented, or No PP translation message
|
||||
const errorMessage =
|
||||
playerPokemon.summonData.disabledMove === move.moveId ? "battle:moveDisabled" :
|
||||
playerPokemon.isMoveDisabled(move.moveId) ? "battle:moveDisabled" :
|
||||
move.getName().endsWith(" (N)") ? "battle:moveNotImplemented" : "battle:moveNoPP";
|
||||
const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator
|
||||
|
||||
@ -2355,11 +2355,6 @@ export class TurnEndPhase extends FieldPhase {
|
||||
const handlePokemon = (pokemon: Pokemon) => {
|
||||
pokemon.lapseTags(BattlerTagLapseType.TURN_END);
|
||||
|
||||
if (pokemon.summonData.disabledMove && !--pokemon.summonData.disabledTurns) {
|
||||
this.scene.pushPhase(new MessagePhase(this.scene, i18next.t("battle:notDisabled", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: allMoves[pokemon.summonData.disabledMove].name })));
|
||||
pokemon.summonData.disabledMove = Moves.NONE;
|
||||
}
|
||||
|
||||
this.scene.applyModifiers(TurnHealModifier, pokemon.isPlayer(), pokemon);
|
||||
|
||||
if (this.scene.arena.terrain?.terrainType === TerrainType.GRASSY && pokemon.isGrounded()) {
|
||||
@ -2521,10 +2516,9 @@ export class MovePhase extends BattlePhase {
|
||||
console.log(Moves[this.move.moveId]);
|
||||
|
||||
if (!this.canMove()) {
|
||||
if (this.move.moveId && this.pokemon.summonData?.disabledMove === this.move.moveId) {
|
||||
this.scene.queueMessage(`${this.move.getName()} is disabled!`);
|
||||
}
|
||||
return this.end();
|
||||
this.fail();
|
||||
this.showMoveText();
|
||||
this.showFailedText();
|
||||
}
|
||||
|
||||
if (!this.followUp) {
|
||||
|
@ -118,8 +118,6 @@ export default class PokemonData {
|
||||
if (!forHistory && source.summonData) {
|
||||
this.summonData.battleStats = source.summonData.battleStats;
|
||||
this.summonData.moveQueue = source.summonData.moveQueue;
|
||||
this.summonData.disabledMove = source.summonData.disabledMove;
|
||||
this.summonData.disabledTurns = source.summonData.disabledTurns;
|
||||
this.summonData.abilitySuppressed = source.summonData.abilitySuppressed;
|
||||
|
||||
this.summonData.ability = source.summonData.ability;
|
||||
|
Loading…
Reference in New Issue
Block a user