mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-02-19 10:47:41 +00:00
* Replace various `scene` pass-arounds with global scene variable * Modify tests * Add scene back to `fade[in|out]()` calls Co-authored-by: Moka <54149968+MokaStitcher@users.noreply.github.com> * Fix Bug Superfan ME test Co-authored-by: Moka <54149968+MokaStitcher@users.noreply.github.com> * Re-enable fixed test Co-authored-by: Moka <54149968+MokaStitcher@users.noreply.github.com> * Rename `gScene` to `globalScene` * Move `globalScene` to its own file to fix import/async issues * Fix `SelectModifierPhase` tests * Fix ME tests by removing `scene` from `expect()`s * Resolve merge issues * Remove tsdocs referencing `scene` params Remove missed instances of `.scene` * Remove unnecessary `globalScene` usage in `loading-scene.ts` * Fix merge conflicts * Attempt to fix circular import issue * Found the source of the import issue * Fix merge issues --------- Co-authored-by: Moka <54149968+MokaStitcher@users.noreply.github.com>
187 lines
8.2 KiB
TypeScript
187 lines
8.2 KiB
TypeScript
import { globalScene } from "#app/global-scene";
|
|
import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims";
|
|
import type Move from "#app/data/move";
|
|
import { allMoves } from "#app/data/move";
|
|
import { SpeciesFormChangeMoveLearnedTrigger } from "#app/data/pokemon-forms";
|
|
import { Moves } from "#enums/moves";
|
|
import { getPokemonNameWithAffix } from "#app/messages";
|
|
import Overrides from "#app/overrides";
|
|
import EvolutionSceneHandler from "#app/ui/evolution-scene-handler";
|
|
import { SummaryUiMode } from "#app/ui/summary-ui-handler";
|
|
import { Mode } from "#app/ui/ui";
|
|
import i18next from "i18next";
|
|
import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase";
|
|
import type Pokemon from "#app/field/pokemon";
|
|
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
|
|
|
export enum LearnMoveType {
|
|
/** For learning a move via level-up, evolution, or other non-item-based event */
|
|
LEARN_MOVE,
|
|
/** For learning a move via Memory Mushroom */
|
|
MEMORY,
|
|
/** For learning a move via TM */
|
|
TM
|
|
}
|
|
|
|
export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
|
private moveId: Moves;
|
|
private messageMode: Mode;
|
|
private learnMoveType;
|
|
private cost: number;
|
|
|
|
constructor(partyMemberIndex: integer, moveId: Moves, learnMoveType: LearnMoveType = LearnMoveType.LEARN_MOVE, cost: number = -1) {
|
|
super(partyMemberIndex);
|
|
this.moveId = moveId;
|
|
this.learnMoveType = learnMoveType;
|
|
this.cost = cost;
|
|
}
|
|
|
|
start() {
|
|
super.start();
|
|
|
|
const pokemon = this.getPokemon();
|
|
const move = allMoves[this.moveId];
|
|
const currentMoveset = pokemon.getMoveset();
|
|
|
|
// The game first checks if the Pokemon already has the move and ends the phase if it does.
|
|
const hasMoveAlready = currentMoveset.some(m => m?.moveId === move.id) && this.moveId !== Moves.SKETCH;
|
|
if (hasMoveAlready) {
|
|
return this.end();
|
|
}
|
|
|
|
this.messageMode = globalScene.ui.getHandler() instanceof EvolutionSceneHandler ? Mode.EVOLUTION_SCENE : Mode.MESSAGE;
|
|
globalScene.ui.setMode(this.messageMode);
|
|
// If the Pokemon has less than 4 moves, the new move is added to the largest empty moveset index
|
|
// If it has 4 moves, the phase then checks if the player wants to replace the move itself.
|
|
if (currentMoveset.length < 4) {
|
|
this.learnMove(currentMoveset.length, move, pokemon);
|
|
} else {
|
|
this.replaceMoveCheck(move, pokemon);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This displays a chain of messages (listed below) and asks if the user wishes to forget a move.
|
|
*
|
|
* > [Pokemon] wants to learn the move [MoveName]
|
|
* > However, [Pokemon] already knows four moves.
|
|
* > Should a move be forgotten and replaced with [MoveName]? --> `Mode.CONFIRM` -> Yes: Go to `this.forgetMoveProcess()`, No: Go to `this.rejectMoveAndEnd()`
|
|
* @param move The Move to be learned
|
|
* @param Pokemon The Pokemon learning the move
|
|
*/
|
|
async replaceMoveCheck(move: Move, pokemon: Pokemon) {
|
|
const learnMovePrompt = i18next.t("battle:learnMovePrompt", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name });
|
|
const moveLimitReached = i18next.t("battle:learnMoveLimitReached", { pokemonName: getPokemonNameWithAffix(pokemon) });
|
|
const shouldReplaceQ = i18next.t("battle:learnMoveReplaceQuestion", { moveName: move.name });
|
|
const preQText = [ learnMovePrompt, moveLimitReached ].join("$");
|
|
await globalScene.ui.showTextPromise(preQText);
|
|
await globalScene.ui.showTextPromise(shouldReplaceQ, undefined, false);
|
|
await globalScene.ui.setModeWithoutClear(Mode.CONFIRM,
|
|
() => this.forgetMoveProcess(move, pokemon), // Yes
|
|
() => { // No
|
|
globalScene.ui.setMode(this.messageMode);
|
|
this.rejectMoveAndEnd(move, pokemon);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* This facilitates the process in which an old move is chosen to be forgotten.
|
|
*
|
|
* > Which move should be forgotten?
|
|
*
|
|
* The game then goes `Mode.SUMMARY` to select a move to be forgotten.
|
|
* If a player does not select a move or chooses the new move (`moveIndex === 4`), the game goes to `this.rejectMoveAndEnd()`.
|
|
* If an old move is selected, the function then passes the `moveIndex` to `this.learnMove()`
|
|
* @param move The Move to be learned
|
|
* @param Pokemon The Pokemon learning the move
|
|
*/
|
|
async forgetMoveProcess(move: Move, pokemon: Pokemon) {
|
|
globalScene.ui.setMode(this.messageMode);
|
|
await globalScene.ui.showTextPromise(i18next.t("battle:learnMoveForgetQuestion"), undefined, true);
|
|
await globalScene.ui.setModeWithoutClear(Mode.SUMMARY, pokemon, SummaryUiMode.LEARN_MOVE, move, (moveIndex: integer) => {
|
|
if (moveIndex === 4) {
|
|
globalScene.ui.setMode(this.messageMode).then(() => this.rejectMoveAndEnd(move, pokemon));
|
|
return;
|
|
}
|
|
const forgetSuccessText = i18next.t("battle:learnMoveForgetSuccess", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: pokemon.moveset[moveIndex]!.getName() });
|
|
const fullText = [ i18next.t("battle:countdownPoof"), forgetSuccessText, i18next.t("battle:learnMoveAnd") ].join("$");
|
|
globalScene.ui.setMode(this.messageMode).then(() => this.learnMove(moveIndex, move, pokemon, fullText));
|
|
});
|
|
}
|
|
|
|
/**
|
|
* This asks the player if they wish to end the current move learning process.
|
|
*
|
|
* > Stop trying to teach [MoveName]? --> `Mode.CONFIRM` --> Yes: > [Pokemon] did not learn the move [MoveName], No: `this.replaceMoveCheck()`
|
|
*
|
|
* If the player wishes to not teach the Pokemon the move, it displays a message and ends the phase.
|
|
* If the player reconsiders, it repeats the process for a Pokemon with a full moveset once again.
|
|
* @param move The Move to be learned
|
|
* @param Pokemon The Pokemon learning the move
|
|
*/
|
|
async rejectMoveAndEnd(move: Move, pokemon: Pokemon) {
|
|
await globalScene.ui.showTextPromise(i18next.t("battle:learnMoveStopTeaching", { moveName: move.name }), undefined, false);
|
|
globalScene.ui.setModeWithoutClear(Mode.CONFIRM,
|
|
() => {
|
|
globalScene.ui.setMode(this.messageMode);
|
|
globalScene.ui.showTextPromise(i18next.t("battle:learnMoveNotLearned", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }), undefined, true).then(() => this.end());
|
|
},
|
|
() => {
|
|
globalScene.ui.setMode(this.messageMode);
|
|
this.replaceMoveCheck(move, pokemon);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* This teaches the Pokemon the new move and ends the phase.
|
|
* When a Pokemon forgets a move and learns a new one, its 'Learn Move' message is significantly longer.
|
|
*
|
|
* Pokemon with a `moveset.length < 4`
|
|
* > [Pokemon] learned [MoveName]
|
|
*
|
|
* Pokemon with a `moveset.length > 4`
|
|
* > 1... 2... and 3... and Poof!
|
|
* > [Pokemon] forgot how to use [MoveName]
|
|
* > And...
|
|
* > [Pokemon] learned [MoveName]!
|
|
* @param move The Move to be learned
|
|
* @param Pokemon The Pokemon learning the move
|
|
*/
|
|
async learnMove(index: number, move: Move, pokemon: Pokemon, textMessage?: string) {
|
|
if (this.learnMoveType === LearnMoveType.TM) {
|
|
if (!pokemon.usedTMs) {
|
|
pokemon.usedTMs = [];
|
|
}
|
|
pokemon.usedTMs.push(this.moveId);
|
|
globalScene.tryRemovePhase((phase) => phase instanceof SelectModifierPhase);
|
|
} else if (this.learnMoveType === LearnMoveType.MEMORY) {
|
|
if (this.cost !== -1) {
|
|
if (!Overrides.WAIVE_ROLL_FEE_OVERRIDE) {
|
|
globalScene.money -= this.cost;
|
|
globalScene.updateMoneyText();
|
|
globalScene.animateMoneyChanged(false);
|
|
}
|
|
globalScene.playSound("se/buy");
|
|
} else {
|
|
globalScene.tryRemovePhase((phase) => phase instanceof SelectModifierPhase);
|
|
}
|
|
}
|
|
pokemon.setMove(index, this.moveId);
|
|
initMoveAnim(this.moveId).then(() => {
|
|
loadMoveAnimAssets([ this.moveId ], true);
|
|
});
|
|
globalScene.ui.setMode(this.messageMode);
|
|
const learnMoveText = i18next.t("battle:learnMove", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name });
|
|
if (textMessage) {
|
|
await globalScene.ui.showTextPromise(textMessage);
|
|
}
|
|
globalScene.playSound("level_up_fanfare"); // Sound loaded into game as is
|
|
globalScene.ui.showText(learnMoveText, null, () => {
|
|
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true);
|
|
this.end();
|
|
}, this.messageMode === Mode.EVOLUTION_SCENE ? 1000 : undefined, true);
|
|
}
|
|
}
|