mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-05-05 16:05:01 +01:00
* Grabbed reverted changes from stuff * Added version migrator for rage fist data + deepMergeSpriteData tests * fixed formattign * Fied a few * Fixed constructor (maybe), moved deepCopy and deepMergeSpriteData to own file `common.ts` is hella bloated so seems legit * Moved empty moveset verification mapping thing to upgrade script bc i wanted to * Fixed tests * test added * Fixed summondata being cleared inside summonPhase, removed `summonDataPrimer` like seriously how come no-one checked this * Fixed test I forgot that we outsped and oneshot * Fixed test * huhjjjjjb * Hopefully fixed bug my sanity and homework are paying the price for this lol * added commented out console.log statement uncomment to see new berry data * Fixed migrate script, re-added deprecated attributes out of necessity * Fixed failing test by not trying to mock rng * Fixed test * Fixed tests * Update ability.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update ability.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update overrides.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update berry-phase.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update encounter-phase.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update game-data.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update move-phase.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Added utility function `randSeedFloat` basically just `Phaser.math.RND.realInRange(0, 1)` * Applied review comments, cleaned up code a bit * Removed unnecessary null checks for turnData and co. I explicitly made them initialized by default for this very reason * Added tests for Last Resort regarding moveHistory * Update pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update battle-scene.ts Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> * Update the-winstrate-challenge-encounter.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update ability.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update move.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update move.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update move.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update battle-anims.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update pokemon.ts comments * Fixed a few outstanding issues with documentation * Updated switch summon phase comment * Re-added BattleSummonData as TempSummonData * Hppefully fixed -1 sprite scale glitch * Fixed comment * Reveted `pokemon-forms.ts` * Fuxed constructor * fixed -1 bug * Revert "Added utility function `randSeedFloat`" This reverts commit 4c3447c851731c989fc591feea0094b6bbde7fd2. --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com>
170 lines
7.9 KiB
TypeScript
170 lines
7.9 KiB
TypeScript
import type { BattlerIndex } from "#app/battle";
|
|
import { Button } from "#app/enums/buttons";
|
|
import type Pokemon from "#app/field/pokemon";
|
|
import { PokemonMove } from "#app/field/pokemon";
|
|
import Overrides from "#app/overrides";
|
|
import type { CommandPhase } from "#app/phases/command-phase";
|
|
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
|
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
|
import { Command } from "#app/ui/command-ui-handler";
|
|
import { UiMode } from "#enums/ui-mode";
|
|
import { Moves } from "#enums/moves";
|
|
import { getMovePosition } from "#test/testUtils/gameManagerUtils";
|
|
import { GameManagerHelper } from "#test/testUtils/helpers/gameManagerHelper";
|
|
import { vi } from "vitest";
|
|
|
|
/**
|
|
* Helper to handle a Pokemon's move
|
|
*/
|
|
export class MoveHelper extends GameManagerHelper {
|
|
/**
|
|
* Intercepts {@linkcode MoveEffectPhase} and mocks the phase's move's
|
|
* accuracy to -1, guaranteeing a hit.
|
|
*/
|
|
public async forceHit(): Promise<void> {
|
|
await this.game.phaseInterceptor.to(MoveEffectPhase, false);
|
|
const moveEffectPhase = this.game.scene.getCurrentPhase() as MoveEffectPhase;
|
|
vi.spyOn(moveEffectPhase.move, "calculateBattleAccuracy").mockReturnValue(-1);
|
|
}
|
|
|
|
/**
|
|
* Intercepts {@linkcode MoveEffectPhase} and mocks the phase's move's accuracy
|
|
* to 0, guaranteeing a miss.
|
|
* @param firstTargetOnly - Whether the move should force miss on the first target only, in the case of multi-target moves.
|
|
*/
|
|
public async forceMiss(firstTargetOnly = false): Promise<void> {
|
|
await this.game.phaseInterceptor.to(MoveEffectPhase, false);
|
|
const moveEffectPhase = this.game.scene.getCurrentPhase() as MoveEffectPhase;
|
|
const accuracy = vi.spyOn(moveEffectPhase.move, "calculateBattleAccuracy");
|
|
|
|
if (firstTargetOnly) {
|
|
accuracy.mockReturnValueOnce(0);
|
|
} else {
|
|
accuracy.mockReturnValue(0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Select the move to be used by the given Pokemon(-index). Triggers during the next {@linkcode CommandPhase}
|
|
* @param move - the move to use
|
|
* @param pkmIndex - the pokemon index. Relevant for double-battles only (defaults to 0)
|
|
* @param targetIndex - The {@linkcode BattlerIndex} of the Pokemon to target for single-target moves, or `null` if a manual call to `selectTarget()` is required
|
|
*/
|
|
public select(move: Moves, pkmIndex: 0 | 1 = 0, targetIndex?: BattlerIndex | null) {
|
|
const movePosition = getMovePosition(this.game.scene, pkmIndex, move);
|
|
|
|
this.game.onNextPrompt("CommandPhase", UiMode.COMMAND, () => {
|
|
this.game.scene.ui.setMode(UiMode.FIGHT, (this.game.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
|
|
});
|
|
this.game.onNextPrompt("CommandPhase", UiMode.FIGHT, () => {
|
|
(this.game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
|
|
});
|
|
|
|
if (targetIndex !== null) {
|
|
this.game.selectTarget(movePosition, targetIndex);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Select the move to be used by the given Pokemon(-index), **which will also terastallize on this turn**.
|
|
* Triggers during the next {@linkcode CommandPhase}
|
|
* @param move - the move to use
|
|
* @param pkmIndex - the pokemon index. Relevant for double-battles only (defaults to 0)
|
|
* @param targetIndex - The {@linkcode BattlerIndex} of the Pokemon to target for single-target moves, or `null` if a manual call to `selectTarget()` is required
|
|
*/
|
|
public selectWithTera(move: Moves, pkmIndex: 0 | 1 = 0, targetIndex?: BattlerIndex | null) {
|
|
const movePosition = getMovePosition(this.game.scene, pkmIndex, move);
|
|
this.game.scene.getPlayerParty()[pkmIndex].isTerastallized = false;
|
|
|
|
this.game.onNextPrompt("CommandPhase", UiMode.COMMAND, () => {
|
|
this.game.scene.ui.setMode(
|
|
UiMode.FIGHT,
|
|
(this.game.scene.getCurrentPhase() as CommandPhase).getFieldIndex(),
|
|
Command.TERA,
|
|
);
|
|
});
|
|
this.game.onNextPrompt("CommandPhase", UiMode.FIGHT, () => {
|
|
(this.game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.TERA, movePosition, false);
|
|
});
|
|
|
|
if (targetIndex !== null) {
|
|
this.game.selectTarget(movePosition, targetIndex);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Forces the Paralysis or Freeze status to activate on the next move by temporarily mocking {@linkcode Overrides.STATUS_ACTIVATION_OVERRIDE},
|
|
* advancing to the next `MovePhase`, and then resetting the override to `null`
|
|
* @param activated - `true` to force the status to activate, `false` to force the status to not activate (will cause Freeze to heal)
|
|
*/
|
|
public async forceStatusActivation(activated: boolean): Promise<void> {
|
|
vi.spyOn(Overrides, "STATUS_ACTIVATION_OVERRIDE", "get").mockReturnValue(activated);
|
|
await this.game.phaseInterceptor.to("MovePhase");
|
|
vi.spyOn(Overrides, "STATUS_ACTIVATION_OVERRIDE", "get").mockReturnValue(null);
|
|
}
|
|
|
|
/**
|
|
* Forces the Confusion status to activate on the next move by temporarily mocking {@linkcode Overrides.CONFUSION_ACTIVATION_OVERRIDE},
|
|
* advancing to the next `MovePhase`, and then resetting the override to `null`
|
|
* @param activated - `true` to force the Pokemon to hit themself, `false` to forcibly disable it
|
|
*/
|
|
public async forceConfusionActivation(activated: boolean): Promise<void> {
|
|
vi.spyOn(Overrides, "CONFUSION_ACTIVATION_OVERRIDE", "get").mockReturnValue(activated);
|
|
await this.game.phaseInterceptor.to("MovePhase");
|
|
vi.spyOn(Overrides, "CONFUSION_ACTIVATION_OVERRIDE", "get").mockReturnValue(null);
|
|
}
|
|
|
|
/**
|
|
* Changes a pokemon's moveset to the given move(s).
|
|
* Used when the normal moveset override can't be used (such as when it's necessary to check or update properties of the moveset).
|
|
* @param pokemon - The {@linkcode Pokemon} being modified
|
|
* @param moveset - The {@linkcode Moves} (single or array) to change the Pokemon's moveset to
|
|
*/
|
|
public changeMoveset(pokemon: Pokemon, moveset: Moves | Moves[]): void {
|
|
if (!Array.isArray(moveset)) {
|
|
moveset = [moveset];
|
|
}
|
|
pokemon.moveset = [];
|
|
moveset.forEach(move => {
|
|
pokemon.moveset.push(new PokemonMove(move));
|
|
});
|
|
const movesetStr = moveset.map(moveId => Moves[moveId]).join(", ");
|
|
console.log(`Pokemon ${pokemon.species.name}'s moveset manually set to ${movesetStr} (=[${moveset.join(", ")}])!`);
|
|
}
|
|
|
|
/**
|
|
* Simulates learning a move for a player pokemon.
|
|
* @param move The {@linkcode Moves} being learnt
|
|
* @param partyIndex The party position of the {@linkcode PlayerPokemon} learning the move (defaults to 0)
|
|
* @param moveSlotIndex The INDEX (0-4) of the move slot to replace if existent move slots are full;
|
|
* defaults to 0 (first slot) and 4 aborts the procedure
|
|
* @returns a promise that resolves once the move has been successfully learnt
|
|
*/
|
|
public async learnMove(move: Moves | number, partyIndex = 0, moveSlotIndex = 0) {
|
|
return new Promise<void>(async (resolve, reject) => {
|
|
this.game.scene.pushPhase(new LearnMovePhase(partyIndex, move));
|
|
|
|
// if slots are full, queue up inputs to replace existing moves
|
|
if (this.game.scene.getPlayerParty()[partyIndex].moveset.filter(m => m).length === 4) {
|
|
this.game.onNextPrompt("LearnMovePhase", UiMode.CONFIRM, () => {
|
|
this.game.scene.ui.processInput(Button.ACTION); // "Should a move be forgotten and replaced with XXX?"
|
|
});
|
|
this.game.onNextPrompt("LearnMovePhase", UiMode.SUMMARY, () => {
|
|
for (let x = 0; x < (moveSlotIndex ?? 0); x++) {
|
|
this.game.scene.ui.processInput(Button.DOWN); // Scrolling in summary pane to move position
|
|
}
|
|
this.game.scene.ui.processInput(Button.ACTION);
|
|
if (moveSlotIndex === 4) {
|
|
this.game.onNextPrompt("LearnMovePhase", UiMode.CONFIRM, () => {
|
|
this.game.scene.ui.processInput(Button.ACTION); // "Give up on learning XXX?"
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
await this.game.phaseInterceptor.to(LearnMovePhase).catch(e => reject(e));
|
|
resolve();
|
|
});
|
|
}
|
|
}
|