Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Move] Use BattlerTag for move-disabling effects #2051

Merged
merged 62 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from 53 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
7847d1c
Use BattlerTag for move-disabling effects
zacharied Jun 10, 2024
2b3a365
Fix RUN command causing freeze
zacharied Jun 10, 2024
969fd86
Improve documentation
zacharied Jun 10, 2024
0f6d01e
Clean up and document PokemonMove.isUsable
zacharied Jun 10, 2024
91cb62a
Fix isMoveDisabled missing return
zacharied Jun 11, 2024
d7b2a35
Tags define the message shown when disabling interrupts a move
zacharied Jun 11, 2024
5a33a1b
Fix -1 duration on Disable effect
zacharied Jun 11, 2024
4a09003
Add tests for Disable
zacharied Jun 11, 2024
16a8f46
Merge branch 'main' into disable_battlertag
zacharied Jun 11, 2024
0ed7024
Merge branch 'beta' into disable2
zacharied Aug 3, 2024
a1ea656
En loc and fix message functions
zacharied Aug 3, 2024
77ba74d
Fix Disable test
zacharied Aug 3, 2024
80037e1
Merge branch 'beta' into disable_battlertag
zacharied Aug 8, 2024
837a19b
Fix broken imports
zacharied Aug 8, 2024
d67937e
Fix test
zacharied Aug 8, 2024
48f2e2e
All disable tests passing
zacharied Aug 8, 2024
4972322
Localize remaining strings
zacharied Aug 8, 2024
a628f77
Move cancellation logic out of lapse; use use TURN_END for lapse type
zacharied Aug 9, 2024
534ebce
Prevent disabling STRUGGLE
zacharied Aug 9, 2024
4d89b76
Inline struggle check function
zacharied Aug 9, 2024
00d3c76
Restore RechargingTag docs
zacharied Aug 9, 2024
b6a5f29
Merge branch 'beta' into disable_battlertag
zacharied Aug 9, 2024
f6b41e3
Move cancellation logic back to tag
zacharied Aug 9, 2024
94200ff
Fix hyper beam test
zacharied Aug 9, 2024
4d9fda7
Remove erroneous shit
zacharied Aug 10, 2024
f293e33
Fill movesets with SPLASH for disable test
zacharied Aug 10, 2024
777511c
More robust condition for disable checking
zacharied Aug 10, 2024
daf063b
Remove DisabledTag lapse
zacharied Aug 10, 2024
3fe58ac
Simplify DisablingBattlerTag lapse
zacharied Aug 10, 2024
14de49e
Cancel disable-interrupted moves instead of failing them
zacharied Aug 10, 2024
8923720
Avoid disabling virtual moves
zacharied Aug 10, 2024
ba50b4b
Consistent access modifiers across Disable tags
zacharied Aug 10, 2024
63d2447
Add abstract function for message when player tries to select the dis…
zacharied Aug 10, 2024
88d3054
Fix syntax mistake
zacharied Aug 10, 2024
570074c
Always disable last-used non-virtual move
zacharied Aug 10, 2024
c6757d0
Overhaul tests + add tests
zacharied Aug 10, 2024
ae667d7
Implement loadTag for DisabledTag
zacharied Aug 10, 2024
efd41af
Merge branch 'beta' into disable_battlertag
zacharied Aug 13, 2024
9970387
Update translations
zacharied Aug 13, 2024
e38cc6e
Update translations
zacharied Aug 13, 2024
d56d486
Merge branch 'beta' into disable_battlertag
zacharied Sep 2, 2024
3ebcd4c
Reimplement phase changes
zacharied Sep 2, 2024
4a5c363
fix battlertag strings
zacharied Sep 2, 2024
2e34349
Fix disable test not running
zacharied Sep 2, 2024
5f3183b
Update name of base class
zacharied Sep 2, 2024
e5d4b6a
Rename "disabling" to "restriction"
zacharied Sep 2, 2024
fbc7121
Fix sneaky string fuckup
zacharied Sep 2, 2024
7e90e9a
Merge branch 'beta' into disable_battlertag
zacharied Sep 4, 2024
84f6847
Fix test failure
zacharied Sep 4, 2024
82b90da
fix merge problems
zacharied Sep 4, 2024
2dbcf63
fix merge problems
zacharied Sep 4, 2024
ee471eb
Merge branch 'beta' into disable_battlertag
zacharied Sep 4, 2024
5577e71
Merge branch 'beta' into disable_battlertag
zacharied Sep 4, 2024
974e722
Update tests
zacharied Sep 5, 2024
c3b93c9
Merge branch 'disable_battlertag' of github.com:zacharied/pokerogue i…
zacharied Sep 5, 2024
a3d950a
rerun RNG test
zacharied Sep 5, 2024
6245bb4
Properly mock stats in test
zacharied Sep 5, 2024
a8ca139
Document everything in battlertag
zacharied Sep 5, 2024
2de1a26
More docs + typo fix
zacharied Sep 5, 2024
a9fdf10
Merge branch 'beta' into disable_battlertag
zacharied Sep 5, 2024
9b80526
Merge branch 'beta' into disable_battlertag
zacharied Sep 5, 2024
0488fc2
Update tests
DayKev Sep 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions src/data/ability.ts
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -1085,29 +1085,20 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr {
}

applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
if (!attacker.summonData.disabledMove) {
if (attacker.getTag(BattlerTagType.DISABLED) === null) {
zacharied marked this conversation as resolved.
Show resolved Hide resolved
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && !attacker.isMax()) {
if (simulated) {
return true;
}

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 i18next.t("abilityTriggers:postDefendMoveDisable", {
pokemonNameWithAffix: getPokemonNameWithAffix(this.attacker),
moveName: this.move.name,
});
}
}

export class PostStatStageChangeStatStageChangeAbAttr extends PostStatStageChangeAbAttr {
Expand Down
100 changes: 100 additions & 0 deletions src/data/battler-tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,104 @@ export interface TerrainBattlerTag {
terrainTypes: TerrainType[];
}

/**
* 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 MoveRestrictionBattlerTag extends BattlerTag {
constructor(tagType: BattlerTagType, turnCount: integer, sourceMove?: Moves, sourceId?: integer) {
super(tagType, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.TURN_END ], turnCount, sourceMove, sourceId);
zacharied marked this conversation as resolved.
Show resolved Hide resolved
}

override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
if (lapseType === BattlerTagLapseType.PRE_MOVE) {
// Cancel the affected pokemon's selected move
const phase = pokemon.scene.getCurrentPhase() as MovePhase;
const move = phase.move;

if (this.isMoveRestricted(move.moveId)) {
pokemon.scene.queueMessage(this.interruptedText(pokemon, move.moveId));
phase.cancel();
}

return true;
}

return super.lapse(pokemon, lapseType);
}

/** Determines whether to restrict a move. */
abstract isMoveRestricted(move: Moves): boolean;

/** 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 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.
*/
export class DisabledTag extends MoveRestrictionBattlerTag {
/** The move being disabled. Gets set when {@linkcode onAdd} is called for this tag. */
public moveId: Moves = Moves.NONE;
zacharied marked this conversation as resolved.
Show resolved Hide resolved

public override isMoveRestricted(move: Moves): boolean {
return move === this.moveId;
}

constructor(sourceId: number) {
super(BattlerTagType.DISABLED, 4, Moves.DISABLE, sourceId);
}

/**
* Ensures that move history exists and has a valid move. If so, sets the {@link moveId} and shows a message.
* Otherwise, something has gone wrong, so the move ID will not get assigned and this tag will get removed next turn.
*/
override onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);

const move = pokemon.getLastXMoves()
.find(m => m.move !== Moves.NONE && m.move !== Moves.STRUGGLE && !m.virtual);
if (move === undefined) {
return;
}

this.moveId = move.move;

pokemon.scene.queueMessage(i18next.t("battlerTags:disabledOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[this.moveId].name }));
}

override onRemove(pokemon: Pokemon): void {
super.onRemove(pokemon);

pokemon.scene.queueMessage(i18next.t("battlerTags:disabledLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[this.moveId].name }));
}

override selectionDeniedText(pokemon: Pokemon, move: Moves): string {
return i18next.t("battle:moveDisabled", { moveName: allMoves[move].name });
}

override interruptedText(pokemon: Pokemon, move: Moves): string {
return i18next.t("battle:disableInterruptedMove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
}

override loadTag(source: BattlerTag | any): void {
super.loadTag(source);
this.moveId = source.moveId;
}
}

/**
* BattlerTag that represents the "recharge" effects of moves like Hyper Beam.
*/
Expand Down Expand Up @@ -1995,6 +2093,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
return new StockpilingTag(sourceMove);
case BattlerTagType.OCTOLOCK:
return new OctolockTag(sourceId);
case BattlerTagType.DISABLED:
return new DisabledTag(sourceId);
case BattlerTagType.IGNORE_GHOST:
return new ExposedTag(tagType, sourceMove, Type.GHOST, [Type.NORMAL, Type.FIGHTING]);
case BattlerTagType.IGNORE_DARK:
Expand Down
70 changes: 3 additions & 67 deletions src/data/move.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4332,72 +4332,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 | undefined;
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!; // TODO: is this bang correct?
target.summonData.disabledTurns = 4;

user.scene.queueMessage(i18next.t("abilityTriggers:postDefendMoveDisable", { pokemonNameWithAffix: getPokemonNameWithAffix(target), moveName: disabledMove?.getName()}));

return true;
}

return false;
}

getCondition(): MoveConditionFunc {
return (user, target, move): boolean => { // TODO: Not sure what to do here
if (target.summonData.disabledMove || target.isMax()) {
return false;
}

const moveQueue = target.getLastXMoves();
let turnMove: TurnMove | undefined;
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;
}

return false;
};
}

getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
return -5;
}
}

export class FrenzyAttr extends MoveEffectAttr {
constructor() {
super(true, MoveEffectTrigger.HIT, false, true);
Expand Down Expand Up @@ -4488,6 +4422,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
case BattlerTagType.INFATUATED:
case BattlerTagType.NIGHTMARE:
case BattlerTagType.DROWSY:
case BattlerTagType.DISABLED:
return -5;
case BattlerTagType.SEEDED:
case BattlerTagType.SALT_CURED:
Expand Down Expand Up @@ -6673,7 +6608,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)
.condition((user, target, move) => target.getMoveHistory().reverse().find(m => m.move !== Moves.NONE && m.move !== Moves.STRUGGLE && !m.virtual) !== undefined)
.condition(failOnMaxCondition),
new AttackMove(Moves.ACID, Type.POISON, MoveCategory.SPECIAL, 40, 100, 30, 10, 0, 1)
.attr(StatStageChangeAttr, [ Stat.SPDEF ], -1)
Expand Down
1 change: 1 addition & 0 deletions src/enums/battler-tag-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export enum BattlerTagType {
STOCKPILING = "STOCKPILING",
RECEIVE_DOUBLE_DAMAGE = "RECEIVE_DOUBLE_DAMAGE",
ALWAYS_GET_HIT = "ALWAYS_GET_HIT",
DISABLED = "DISABLED",
IGNORE_GHOST = "IGNORE_GHOST",
IGNORE_DARK = "IGNORE_DARK",
GULP_MISSILE_ARROKUDA = "GULP_MISSILE_ARROKUDA",
Expand Down
46 changes: 39 additions & 7 deletions src/field/pokemon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { initMoveAnim, loadMoveAnimAssets } from "../data/battle-anims";
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 { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, 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 { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "../data/arena-tag";
import { Ability, AbAttr, StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr } from "../data/ability";
Expand Down Expand Up @@ -2670,6 +2670,27 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.updateInfo();
}

/**
* Gets whether the given move move is currently disabled for this Pokemon.
zacharied marked this conversation as resolved.
Show resolved Hide resolved
* @param moveId {@linkcode Moves} The ID of the move to check
* @see {@linkcode MoveRestrictionBattlerTag}
*/
isMoveRestricted(moveId: Moves): boolean {
return this.getRestrictingTag(moveId) !== null;
}

/**
* Gets the {@link MoveRestrictionBattlerTag} that is restricting the given move, or null if that move is not restricted.
*/
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;
}

getMoveHistory(): TurnMove[] {
return this.battleSummonData.moveHistory;
}
Expand Down Expand Up @@ -4458,8 +4479,6 @@ export interface AttackMoveResult {
export class PokemonSummonData {
public statStages: number[] = [ 0, 0, 0, 0, 0, 0, 0 ];
public moveQueue: QueuedMove[] = [];
public disabledMove: Moves = Moves.NONE;
public disabledTurns: number = 0;
public tags: BattlerTag[] = [];
public abilitySuppressed: boolean = false;
public abilitiesApplied: Abilities[] = [];
Expand Down Expand Up @@ -4540,7 +4559,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.
Expand All @@ -4560,11 +4579,24 @@ export class PokemonMove {
this.virtual = !!virtual;
}

isUsable(pokemon: Pokemon, ignorePp?: boolean): boolean {
if (this.moveId && pokemon.summonData?.disabledMove === this.moveId) {
/**
* 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, 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 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, ignoreRestrictionTags?: boolean): boolean {
if (this.moveId && !ignoreRestrictionTags && pokemon.isMoveRestricted(this.moveId)) {
return false;
}

if (this.getMove().name.endsWith(" (N)")) {
zacharied marked this conversation as resolved.
Show resolved Hide resolved
return false;
}
return (ignorePp || this.ppUsed < this.getMovePp() || this.getMove().pp === -1) && !this.getMove().name.endsWith(" (N)");

return (ignorePp || this.ppUsed < this.getMovePp() || this.getMove().pp === -1);
}

getMove(): Move {
Expand Down
1 change: 1 addition & 0 deletions src/locales/en/battle.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.",
"moveNoPP": "There's no PP left for\nthis move!",
"moveDisabled": "{{moveName}} is disabled!",
"disableInterruptedMove": "{{pokemonNameWithAffix}}'s {{moveName}}\nis disabled!",
"noPokeballForce": "An unseen force\nprevents using Poké Balls.",
"noPokeballTrainer": "You can't catch\nanother trainer's Pokémon!",
"noPokeballMulti": "You can only throw a Poké Ball\nwhen there is one Pokémon remaining!",
Expand Down
6 changes: 4 additions & 2 deletions src/locales/en/battler-tags.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,7 @@
"saltCuredLapse": "{{pokemonNameWithAffix}} is hurt by {{moveName}}!",
"cursedOnAdd": "{{pokemonNameWithAffix}} cut its own HP and put a curse on the {{pokemonName}}!",
"cursedLapse": "{{pokemonNameWithAffix}} is afflicted by the Curse!",
"stockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!"
}
"stockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!",
"disabledOnAdd": "{{pokemonNameWithAffix}}'s {{moveName}}\nwas disabled!",
"disabledLapse": "{{pokemonNameWithAffix}}'s {{moveName}}\nis no longer disabled."
}
5 changes: 3 additions & 2 deletions src/phases/command-phase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ 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" :
move.getName().endsWith(" (N)") ? "battle:moveNotImplemented" : "battle:moveNoPP";
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

this.scene.ui.showText(i18next.t(errorMessage, { moveName: moveName }), null, () => {
Expand Down
9 changes: 3 additions & 6 deletions src/phases/move-phase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ export class MovePhase extends BattlePhase {
this.cancelled = false;
}

canMove(): boolean {
return this.pokemon.isActive(true) && this.move.isUsable(this.pokemon, this.ignorePp) && !!this.targets.length;
canMove(ignoreDisableTags?: boolean): boolean {
return this.pokemon.isActive(true) && this.move.isUsable(this.pokemon, this.ignorePp, ignoreDisableTags) && !!this.targets.length;
}

/**Signifies the current move should fail but still use PP */
Expand All @@ -63,10 +63,7 @@ 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(i18next.t("battle:moveDisabled", { moveName: this.move.getName() }));
}
if (!this.canMove(true)) {
if (this.pokemon.isActive(true) && this.move.ppUsed >= this.move.getMovePp()) { // if the move PP was reduced from Spite or otherwise, the move fails
this.fail();
this.showMoveText();
Expand Down
Loading
Loading