mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-06 08:22:16 +02:00
Compare commits
4 Commits
4a5c3638c6
...
fbc71216e7
Author | SHA1 | Date | |
---|---|---|---|
|
fbc71216e7 | ||
|
e5d4b6a0a6 | ||
|
5f3183bc8a | ||
|
2e3434910e |
@ -98,11 +98,14 @@ export interface TerrainBattlerTag {
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for tags that disable moves. Descendants can override {@linkcode moveIsDisabled} to disable moves that
|
||||
* match a condition. A disabled move gets cancelled before it is used. Players and enemies should not be allowed
|
||||
* to select disabled moves.
|
||||
* Base class for tags that restrict the usage of moves. This effect is generally referred to as "disabling" a move
|
||||
* in-game. This is not to be confused with {@linkcode Moves.DISABLE}.
|
||||
*
|
||||
* Descendants can override {@linkcode isMoveRestricted} to restrict moves that
|
||||
* match a condition. A restricted move gets cancelled before it is used. Players and enemies should not be allowed
|
||||
* to select restricted moves.
|
||||
*/
|
||||
export abstract class DisablingBattlerTag extends BattlerTag {
|
||||
export abstract class MoveRestrictionBattlerTag extends BattlerTag {
|
||||
constructor(tagType: BattlerTagType, turnCount: integer, sourceMove?: Moves, sourceId?: integer) {
|
||||
super(tagType, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.TURN_END ], turnCount, sourceMove, sourceId);
|
||||
}
|
||||
@ -113,7 +116,7 @@ export abstract class DisablingBattlerTag extends BattlerTag {
|
||||
const phase = pokemon.scene.getCurrentPhase() as MovePhase;
|
||||
const move = phase.move;
|
||||
|
||||
if (this.moveIsDisabled(move.moveId)) {
|
||||
if (this.isMoveRestricted(move.moveId)) {
|
||||
pokemon.scene.queueMessage(this.interruptedText(pokemon, move.moveId));
|
||||
phase.cancel();
|
||||
}
|
||||
@ -124,29 +127,29 @@ export abstract class DisablingBattlerTag extends BattlerTag {
|
||||
return super.lapse(pokemon, lapseType);
|
||||
}
|
||||
|
||||
/** Determines whether to disable a move. */
|
||||
abstract moveIsDisabled(move: Moves): boolean;
|
||||
/** Determines whether to restrict a move. */
|
||||
abstract isMoveRestricted(move: Moves): boolean;
|
||||
|
||||
/** The text to display when the player attempts to select a move disabled by this tag. */
|
||||
/** The text to display when the player attempts to select a move that is restricted by this tag. */
|
||||
abstract selectionDeniedText(pokemon: Pokemon, move: Moves): string;
|
||||
|
||||
/**
|
||||
* The text to display when a move's execution is prevented as a result of the disable.
|
||||
* Because disabling effects also prevent selection of the move, this situation can only arise if a
|
||||
* pokemon first selects a move, then gets outsped by a pokemon using a move that disables the selected move.
|
||||
* The text to display when a move's execution is prevented as a result of the restriction.
|
||||
* Because restriction effects also prevent selection of the move, this situation can only arise if a
|
||||
* pokemon first selects a move, then gets outsped by a pokemon using a move that restricts the selected move.
|
||||
*/
|
||||
abstract interruptedText(pokemon: Pokemon, move: Moves): string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* When the tag is added, the last-used move of the tag holder is set as the disabled move.
|
||||
*/
|
||||
export class DisabledTag extends DisablingBattlerTag {
|
||||
export class DisabledTag extends MoveRestrictionBattlerTag {
|
||||
/** The move being disabled. Gets set when {@linkcode onAdd} is called for this tag. */
|
||||
public moveId: Moves = Moves.NONE;
|
||||
|
||||
public override moveIsDisabled(move: Moves): boolean {
|
||||
public override isMoveRestricted(move: Moves): boolean {
|
||||
return move === this.moveId;
|
||||
}
|
||||
|
||||
@ -640,7 +643,7 @@ export class SeedTag extends BattlerTag {
|
||||
const reverseDrain = pokemon.hasAbilityWithAttr(ReverseDrainAbAttr, false);
|
||||
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, source.getBattlerIndex(),
|
||||
!reverseDrain ? damage : damage * -1,
|
||||
!reverseDrain ? i18next.t("battlerTags:seededLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }) : i18next.t("battle:battlerTagsSeededLapseShed", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }),
|
||||
!reverseDrain ? i18next.t("battlerTags:seededLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }) : i18next.t("battlerTags:seededLapseShed", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }),
|
||||
false, true));
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import { Status, StatusEffect, getRandomStatus } from "../data/status-effect";
|
||||
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "../data/pokemon-evolutions";
|
||||
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "../data/tms";
|
||||
import { BattleStat } from "../data/battle-stat";
|
||||
import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, DisablingBattlerTag, ExposedTag, DragonCheerTag, CritBoostTag, TrappedTag } from "../data/battler-tags";
|
||||
import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, MoveRestrictionBattlerTag, ExposedTag, DragonCheerTag, CritBoostTag, TrappedTag } from "../data/battler-tags";
|
||||
import { WeatherType } from "../data/weather";
|
||||
import { TempBattleStat } from "../data/temp-battle-stat";
|
||||
import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "../data/arena-tag";
|
||||
@ -2549,20 +2549,21 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether a move is currently disabled for this Pokemon.
|
||||
* @see {@linkcode DisablingBattlerTag}
|
||||
* Gets whether the given move move is currently disabled for this Pokemon.
|
||||
* @param moveId {@linkcode Moves} The ID of the move to check
|
||||
* @see {@linkcode MoveRestrictionBattlerTag}
|
||||
*/
|
||||
isMoveDisabled(moveId: Moves): boolean {
|
||||
return this.getDisablingTag(moveId) !== null;
|
||||
isMoveRestricted(moveId: Moves): boolean {
|
||||
return this.getRestrictingTag(moveId) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link DisablingBattlerTag} that is disabling the given move, or null if that move is not disabled.
|
||||
* Gets the {@link MoveRestrictionBattlerTag} that is restricting the given move, or null if that move is not restricted.
|
||||
*/
|
||||
getDisablingTag(moveId: Moves): DisablingBattlerTag | null {
|
||||
for (const tag of this.findTags(t => t instanceof DisablingBattlerTag)) {
|
||||
if ((tag as DisablingBattlerTag).moveIsDisabled(moveId)) {
|
||||
return tag as DisablingBattlerTag;
|
||||
getRestrictingTag(moveId: Moves): MoveRestrictionBattlerTag | null {
|
||||
for (const tag of this.findTags(t => t instanceof MoveRestrictionBattlerTag)) {
|
||||
if ((tag as MoveRestrictionBattlerTag).isMoveRestricted(moveId)) {
|
||||
return tag as MoveRestrictionBattlerTag;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -4433,7 +4434,7 @@ export type DamageResult = HitResult.EFFECTIVE | HitResult.SUPER_EFFECTIVE | Hit
|
||||
* It links to {@linkcode Move} class via the move ID.
|
||||
* Compared to {@linkcode Move}, this class also tracks if a move has received.
|
||||
* PP Ups, amount of PP used, and things like that.
|
||||
* @see {@linkcode isUsable} - checks if move is disabled, out of PP, or not implemented.
|
||||
* @see {@linkcode isUsable} - checks if move is restricted, out of PP, or not implemented.
|
||||
* @see {@linkcode getMove} - returns {@linkcode Move} object by looking it up via ID.
|
||||
* @see {@linkcode usePp} - removes a point of PP from the move.
|
||||
* @see {@linkcode getMovePp} - returns amount of PP a move currently has.
|
||||
@ -4455,14 +4456,14 @@ export class PokemonMove {
|
||||
|
||||
/**
|
||||
* Checks whether the move can be selected or performed by a Pokemon, without consideration for the move's targets.
|
||||
* The move is unusable if it is out of PP, disabled by an effect, or unimplemented.
|
||||
* @param {Pokemon} pokemon The Pokemon that would be using this move
|
||||
* The move is unusable if it is out of PP, restricted by an effect, or unimplemented.
|
||||
* @param pokemon {@linkcode Pokemon} The Pokemon that would be using this move
|
||||
* @param ignorePp If true, skips the PP check
|
||||
* @param ignoreDisableTags If true, skips the check for move-disabling tags
|
||||
* @param ignoreRestrictionTags If true, skips the check for move restriction tags
|
||||
* @returns True if the move can be selected and used by the Pokemon, otherwise false.
|
||||
*/
|
||||
isUsable(pokemon: Pokemon, ignorePp?: boolean, ignoreDisableTags?: boolean): boolean {
|
||||
if (this.moveId && !ignoreDisableTags && pokemon.isMoveDisabled(this.moveId)) {
|
||||
isUsable(pokemon: Pokemon, ignorePp?: boolean, ignoreRestrictionTags?: boolean): boolean {
|
||||
if (this.moveId && !ignoreRestrictionTags && pokemon.isMoveRestricted(this.moveId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -107,8 +107,8 @@ export class CommandPhase extends FieldPhase {
|
||||
|
||||
// Decides between a Disabled, Not Implemented, or No PP translation message
|
||||
const errorMessage =
|
||||
playerPokemon.isMoveDisabled(move.moveId)
|
||||
? playerPokemon.getDisablingTag(move.moveId)!.selectionDeniedText(playerPokemon, move.moveId)
|
||||
playerPokemon.isMoveRestricted(move.moveId)
|
||||
? playerPokemon.getRestrictingTag(move.moveId)!.selectionDeniedText(playerPokemon, move.moveId)
|
||||
: move.getName().endsWith(" (N)") ? "battle:moveNotImplemented" : "battle:moveNoPP";
|
||||
const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator
|
||||
|
||||
|
@ -3,13 +3,15 @@ import GameManager from "../utils/gameManager";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { CommandPhase, EnemyCommandPhase, TurnInitPhase } from "#app/phases.js";
|
||||
import { Mode } from "#app/ui/ui.js";
|
||||
import { getMovePosition } from "../utils/gameManagerUtils";
|
||||
import { Command } from "#app/ui/command-ui-handler";
|
||||
import { MoveResult } from "#app/field/pokemon.js";
|
||||
import { Stat } from "#app/data/pokemon-stat.js";
|
||||
import { SPLASH_ONLY } from "../utils/testUtils";
|
||||
import { CommandPhase } from "#app/phases/command-phase.js";
|
||||
import { EnemyCommandPhase } from "#app/phases/enemy-command-phase.js";
|
||||
import { TurnInitPhase } from "#app/phases/turn-init-phase.js";
|
||||
|
||||
describe("Moves - Disable", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
@ -62,7 +64,7 @@ describe("Moves - Disable", () => {
|
||||
expect(playerMon.getMoveHistory()).toHaveLength(1);
|
||||
expect(enemyMon.getMoveHistory()).toHaveLength(1);
|
||||
expect(playerMon.getMoveHistory()[0]).toMatchObject({ move: Moves.DISABLE, result: MoveResult.SUCCESS });
|
||||
expect(enemyMon.isMoveDisabled(Moves.SPLASH)).toBe(true);
|
||||
expect(enemyMon.isMoveRestricted(Moves.SPLASH)).toBe(true);
|
||||
});
|
||||
|
||||
it("fails if enemy has no move history", async() => {
|
||||
@ -116,7 +118,7 @@ describe("Moves - Disable", () => {
|
||||
|
||||
expect(playerMon.getLastXMoves()[0].result).toBe(MoveResult.FAIL);
|
||||
expect(enemyMon.getLastXMoves()[0].move).toBe(Moves.STRUGGLE);
|
||||
expect(enemyMon.isMoveDisabled(Moves.STRUGGLE)).toBe(false);
|
||||
expect(enemyMon.isMoveRestricted(Moves.STRUGGLE)).toBe(false);
|
||||
}, 20000);
|
||||
|
||||
it("interrupts target's move when target moves after", async() => {
|
||||
@ -155,7 +157,7 @@ describe("Moves - Disable", () => {
|
||||
_useMove(Moves.DISABLE);
|
||||
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(CommandPhase);
|
||||
|
||||
expect(enemyMon.isMoveDisabled(Moves.NATURE_POWER)).toBe(true);
|
||||
expect(enemyMon.isMoveDisabled(enemyMon.getLastXMoves(2)[1].move)).toBe(false);
|
||||
expect(enemyMon.isMoveRestricted(Moves.NATURE_POWER)).toBe(true);
|
||||
expect(enemyMon.isMoveRestricted(enemyMon.getLastXMoves(2)[1].move)).toBe(false);
|
||||
}, 20000);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user