mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-21 09:02:47 +02:00
Merge remote-tracking branch 'upstream/beta' into modifier-fixes
This commit is contained in:
commit
cd2c710937
@ -31,7 +31,6 @@
|
|||||||
"src/overrides.ts",
|
"src/overrides.ts",
|
||||||
// TODO: these files are too big and complex, ignore them until their respective refactors
|
// TODO: these files are too big and complex, ignore them until their respective refactors
|
||||||
"src/data/moves/move.ts",
|
"src/data/moves/move.ts",
|
||||||
"src/data/abilities/ability.ts",
|
|
||||||
|
|
||||||
// this file is just too big:
|
// this file is just too big:
|
||||||
"src/data/balance/tms.ts"
|
"src/data/balance/tms.ts"
|
||||||
@ -42,9 +41,6 @@
|
|||||||
// TODO: Remove if we ever get down to 0 circular imports
|
// TODO: Remove if we ever get down to 0 circular imports
|
||||||
"organizeImports": { "enabled": false },
|
"organizeImports": { "enabled": false },
|
||||||
"linter": {
|
"linter": {
|
||||||
"ignore": [
|
|
||||||
"src/phases/move-effect-phase.ts" // TODO: unignore after move-effect-phase refactor
|
|
||||||
],
|
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"rules": {
|
"rules": {
|
||||||
"recommended": true,
|
"recommended": true,
|
||||||
|
@ -145,6 +145,5 @@
|
|||||||
</div>
|
</div>
|
||||||
<script type="module" src="./src/main.ts"></script>
|
<script type="module" src="./src/main.ts"></script>
|
||||||
<script src="./src/touch-controls.ts" type="module"></script>
|
<script src="./src/touch-controls.ts" type="module"></script>
|
||||||
<script src="./src/debug.js" type="module"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -9,6 +9,11 @@ pre-commit:
|
|||||||
- rebase
|
- rebase
|
||||||
|
|
||||||
post-merge:
|
post-merge:
|
||||||
|
commands:
|
||||||
|
update-submodules:
|
||||||
|
run: git submodule update --init --recursive
|
||||||
|
|
||||||
|
post-checkout:
|
||||||
commands:
|
commands:
|
||||||
update-submodules:
|
update-submodules:
|
||||||
run: git submodule update --init --recursive
|
run: git submodule update --init --recursive
|
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 3.7 KiB |
@ -1,6 +1,7 @@
|
|||||||
/**
|
export interface DexData {
|
||||||
* Dex entry for a single Pokemon Species
|
[key: number]: DexEntry;
|
||||||
*/
|
}
|
||||||
|
|
||||||
export interface DexEntry {
|
export interface DexEntry {
|
||||||
seenAttr: bigint;
|
seenAttr: bigint;
|
||||||
caughtAttr: bigint;
|
caughtAttr: bigint;
|
||||||
@ -10,7 +11,3 @@ export interface DexEntry {
|
|||||||
hatchedCount: number;
|
hatchedCount: number;
|
||||||
ivs: number[];
|
ivs: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DexData {
|
|
||||||
[key: number]: DexEntry;
|
|
||||||
}
|
|
@ -2,9 +2,6 @@ export interface Localizable {
|
|||||||
localize(): void;
|
localize(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TranslationEntries {
|
|
||||||
[key: string]: string | { [key: string]: string };
|
|
||||||
}
|
|
||||||
export interface SimpleTranslationEntries {
|
export interface SimpleTranslationEntries {
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
}
|
}
|
25
src/@types/phase-types.ts
Normal file
25
src/@types/phase-types.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import type { PhaseConstructorMap } from "#app/phase-manager";
|
||||||
|
|
||||||
|
// Intentionally export the types of everything in phase-manager, as this file is meant to be
|
||||||
|
// the centralized place for type definitions for the phase system.
|
||||||
|
export type * from "#app/phase-manager";
|
||||||
|
|
||||||
|
// This file includes helpful types for the phase system.
|
||||||
|
// It intentionally imports the phase constructor map from the phase manager (and re-exports it)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of phase names to constructors for said phase
|
||||||
|
*/
|
||||||
|
export type PhaseMap = {
|
||||||
|
[K in keyof PhaseConstructorMap]: InstanceType<PhaseConstructorMap[K]>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Union type of all phase constructors.
|
||||||
|
*/
|
||||||
|
export type PhaseClass = PhaseConstructorMap[keyof PhaseConstructorMap];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Union type of all phase names as strings.
|
||||||
|
*/
|
||||||
|
export type PhaseString = keyof PhaseMap;
|
@ -2,8 +2,8 @@ import type { EnemyPokemon } from "#app/field/pokemon";
|
|||||||
import type { PersistentModifier } from "#app/modifier/modifier";
|
import type { PersistentModifier } from "#app/modifier/modifier";
|
||||||
import type { PartyMemberStrength } from "#enums/party-member-strength";
|
import type { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
import type { SpeciesId } from "#enums/species-id";
|
import type { SpeciesId } from "#enums/species-id";
|
||||||
import type { TrainerConfig } from "./trainer-config";
|
import type { TrainerConfig } from "../data/trainers/trainer-config";
|
||||||
import type { TrainerPartyTemplate } from "./TrainerPartyTemplate";
|
import type { TrainerPartyTemplate } from "../data/trainers/TrainerPartyTemplate";
|
||||||
|
|
||||||
export type PartyTemplateFunc = () => TrainerPartyTemplate;
|
export type PartyTemplateFunc = () => TrainerPartyTemplate;
|
||||||
export type PartyMemberFunc = (level: number, strength: PartyMemberStrength) => EnemyPokemon;
|
export type PartyMemberFunc = (level: number, strength: PartyMemberStrength) => EnemyPokemon;
|
@ -108,7 +108,6 @@ import {
|
|||||||
SpeciesFormChangeManualTrigger,
|
SpeciesFormChangeManualTrigger,
|
||||||
SpeciesFormChangeTimeOfDayTrigger,
|
SpeciesFormChangeTimeOfDayTrigger,
|
||||||
} from "#app/data/pokemon-forms";
|
} from "#app/data/pokemon-forms";
|
||||||
import { FormChangePhase } from "#app/phases/form-change-phase";
|
|
||||||
import { getTypeRgb } from "#app/data/type";
|
import { getTypeRgb } from "#app/data/type";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import PokemonSpriteSparkleHandler from "#app/field/pokemon-sprite-sparkle-handler";
|
import PokemonSpriteSparkleHandler from "#app/field/pokemon-sprite-sparkle-handler";
|
||||||
@ -120,7 +119,7 @@ import { SceneBase } from "#app/scene-base";
|
|||||||
import CandyBar from "#app/ui/candy-bar";
|
import CandyBar from "#app/ui/candy-bar";
|
||||||
import type { Variant } from "#app/sprites/variant";
|
import type { Variant } from "#app/sprites/variant";
|
||||||
import { variantData, clearVariantData } from "#app/sprites/variant";
|
import { variantData, clearVariantData } from "#app/sprites/variant";
|
||||||
import type { Localizable } from "#app/interfaces/locales";
|
import type { Localizable } from "#app/@types/locales";
|
||||||
import Overrides from "#app/overrides";
|
import Overrides from "#app/overrides";
|
||||||
import { InputsController } from "#app/inputs-controller";
|
import { InputsController } from "#app/inputs-controller";
|
||||||
import { UiInputs } from "#app/ui-inputs";
|
import { UiInputs } from "#app/ui-inputs";
|
||||||
@ -142,21 +141,7 @@ import i18next from "i18next";
|
|||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { battleSpecDialogue } from "#app/data/dialogue";
|
import { battleSpecDialogue } from "#app/data/dialogue";
|
||||||
import { LoadingScene } from "#app/loading-scene";
|
import { LoadingScene } from "#app/loading-scene";
|
||||||
import { LevelCapPhase } from "#app/phases/level-cap-phase";
|
import type { MovePhase } from "#app/phases/move-phase";
|
||||||
import { LoginPhase } from "#app/phases/login-phase";
|
|
||||||
import { MessagePhase } from "#app/phases/message-phase";
|
|
||||||
import { MovePhase } from "#app/phases/move-phase";
|
|
||||||
import { NewBiomeEncounterPhase } from "#app/phases/new-biome-encounter-phase";
|
|
||||||
import { NextEncounterPhase } from "#app/phases/next-encounter-phase";
|
|
||||||
import { PokemonAnimPhase } from "#app/phases/pokemon-anim-phase";
|
|
||||||
import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase";
|
|
||||||
import { ReturnPhase } from "#app/phases/return-phase";
|
|
||||||
import { ShowTrainerPhase } from "#app/phases/show-trainer-phase";
|
|
||||||
import { SummonPhase } from "#app/phases/summon-phase";
|
|
||||||
import { SwitchPhase } from "#app/phases/switch-phase";
|
|
||||||
import { TitlePhase } from "#app/phases/title-phase";
|
|
||||||
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
|
|
||||||
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
|
||||||
import { ShopCursorTarget } from "#app/enums/shop-cursor-target";
|
import { ShopCursorTarget } from "#app/enums/shop-cursor-target";
|
||||||
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import {
|
import {
|
||||||
@ -170,22 +155,19 @@ import {
|
|||||||
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||||
import { ExpPhase } from "#app/phases/exp-phase";
|
|
||||||
import { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase";
|
|
||||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
import { ExpGainsSpeed } from "#enums/exp-gains-speed";
|
import { ExpGainsSpeed } from "#enums/exp-gains-speed";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { FRIENDSHIP_GAIN_FROM_BATTLE } from "#app/data/balance/starters";
|
import { FRIENDSHIP_GAIN_FROM_BATTLE } from "#app/data/balance/starters";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import { initGlobalScene } from "#app/global-scene";
|
import { initGlobalScene } from "#app/global-scene";
|
||||||
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
|
||||||
import { HideAbilityPhase } from "#app/phases/hide-ability-phase";
|
|
||||||
import { expSpriteKeys } from "./sprites/sprite-keys";
|
import { expSpriteKeys } from "./sprites/sprite-keys";
|
||||||
import { hasExpSprite } from "./sprites/sprite-utils";
|
import { hasExpSprite } from "./sprites/sprite-utils";
|
||||||
import { timedEventManager } from "./global-event-manager";
|
import { timedEventManager } from "./global-event-manager";
|
||||||
import { starterColors } from "./global-vars/starter-colors";
|
import { starterColors } from "./global-vars/starter-colors";
|
||||||
import { startingWave } from "./starting-wave";
|
import { startingWave } from "./starting-wave";
|
||||||
|
import { PhaseManager } from "./phase-manager";
|
||||||
|
|
||||||
const DEBUG_RNG = false;
|
const DEBUG_RNG = false;
|
||||||
|
|
||||||
@ -298,18 +280,8 @@ export default class BattleScene extends SceneBase {
|
|||||||
public gameData: GameData;
|
public gameData: GameData;
|
||||||
public sessionSlotId: number;
|
public sessionSlotId: number;
|
||||||
|
|
||||||
/** PhaseQueue: dequeue/remove the first element to get the next phase */
|
/** Manager for the phases active in the battle scene */
|
||||||
public phaseQueue: Phase[];
|
public readonly phaseManager: PhaseManager;
|
||||||
public conditionalQueue: Array<[() => boolean, Phase]>;
|
|
||||||
/** PhaseQueuePrepend: is a temp storage of what will be added to PhaseQueue */
|
|
||||||
private phaseQueuePrepend: Phase[];
|
|
||||||
|
|
||||||
/** overrides default of inserting phases to end of phaseQueuePrepend array, useful or inserting Phases "out of order" */
|
|
||||||
private phaseQueuePrependSpliceIndex: number;
|
|
||||||
private nextCommandPhaseQueue: Phase[];
|
|
||||||
|
|
||||||
private currentPhase: Phase | null;
|
|
||||||
private standbyPhase: Phase | null;
|
|
||||||
public field: Phaser.GameObjects.Container;
|
public field: Phaser.GameObjects.Container;
|
||||||
public fieldUI: Phaser.GameObjects.Container;
|
public fieldUI: Phaser.GameObjects.Container;
|
||||||
public charSprite: CharSprite;
|
public charSprite: CharSprite;
|
||||||
@ -397,11 +369,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super("battle");
|
super("battle");
|
||||||
this.phaseQueue = [];
|
this.phaseManager = new PhaseManager();
|
||||||
this.phaseQueuePrepend = [];
|
|
||||||
this.conditionalQueue = [];
|
|
||||||
this.phaseQueuePrependSpliceIndex = -1;
|
|
||||||
this.nextCommandPhaseQueue = [];
|
|
||||||
this.eventManager = new TimedEventManager();
|
this.eventManager = new TimedEventManager();
|
||||||
this.updateGameInfo();
|
this.updateGameInfo();
|
||||||
initGlobalScene(this);
|
initGlobalScene(this);
|
||||||
@ -717,10 +685,10 @@ export default class BattleScene extends SceneBase {
|
|||||||
).then(() => loadMoveAnimAssets(defaultMoves, true)),
|
).then(() => loadMoveAnimAssets(defaultMoves, true)),
|
||||||
this.initStarterColors(),
|
this.initStarterColors(),
|
||||||
]).then(() => {
|
]).then(() => {
|
||||||
this.pushPhase(new LoginPhase());
|
this.phaseManager.pushNew("LoginPhase");
|
||||||
this.pushPhase(new TitlePhase());
|
this.phaseManager.pushNew("TitlePhase");
|
||||||
|
|
||||||
this.shiftPhase();
|
this.phaseManager.shiftPhase();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -812,6 +780,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add a `getPartyOnSide` function for getting the party of a pokemon
|
||||||
public getPlayerParty(): PlayerPokemon[] {
|
public getPlayerParty(): PlayerPokemon[] {
|
||||||
return this.party;
|
return this.party;
|
||||||
}
|
}
|
||||||
@ -899,9 +868,9 @@ export default class BattleScene extends SceneBase {
|
|||||||
if (allyPokemon?.isActive(true)) {
|
if (allyPokemon?.isActive(true)) {
|
||||||
let targetingMovePhase: MovePhase;
|
let targetingMovePhase: MovePhase;
|
||||||
do {
|
do {
|
||||||
targetingMovePhase = this.findPhase(
|
targetingMovePhase = this.phaseManager.findPhase(
|
||||||
mp =>
|
mp =>
|
||||||
mp instanceof MovePhase &&
|
mp.is("MovePhase") &&
|
||||||
mp.targets.length === 1 &&
|
mp.targets.length === 1 &&
|
||||||
mp.targets[0] === removedPokemon.getBattlerIndex() &&
|
mp.targets[0] === removedPokemon.getBattlerIndex() &&
|
||||||
mp.pokemon.isPlayer() !== allyPokemon.isPlayer(),
|
mp.pokemon.isPlayer() !== allyPokemon.isPlayer(),
|
||||||
@ -1287,7 +1256,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
duration: 250,
|
duration: 250,
|
||||||
ease: "Sine.easeInOut",
|
ease: "Sine.easeInOut",
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
this.clearPhaseQueue();
|
this.phaseManager.clearPhaseQueue();
|
||||||
|
|
||||||
this.ui.freeUIData();
|
this.ui.freeUIData();
|
||||||
this.uiContainer.remove(this.ui, true);
|
this.uiContainer.remove(this.ui, true);
|
||||||
@ -1460,7 +1429,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lastBattle?.double && !newDouble) {
|
if (lastBattle?.double && !newDouble) {
|
||||||
this.tryRemovePhase(p => p instanceof SwitchPhase);
|
this.phaseManager.tryRemovePhase((p: Phase) => p.is("SwitchPhase"));
|
||||||
for (const p of this.getPlayerField()) {
|
for (const p of this.getPlayerField()) {
|
||||||
p.lapseTag(BattlerTagType.COMMANDED);
|
p.lapseTag(BattlerTagType.COMMANDED);
|
||||||
}
|
}
|
||||||
@ -1502,7 +1471,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
playerField.forEach((pokemon, p) => {
|
playerField.forEach((pokemon, p) => {
|
||||||
if (pokemon.isOnField()) {
|
if (pokemon.isOnField()) {
|
||||||
this.pushPhase(new ReturnPhase(p));
|
this.phaseManager.pushNew("ReturnPhase", p);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1519,7 +1488,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.trainer.visible) {
|
if (!this.trainer.visible) {
|
||||||
this.pushPhase(new ShowTrainerPhase());
|
this.phaseManager.pushNew("ShowTrainerPhase");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1528,13 +1497,13 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.gameMode.hasRandomBiomes && !isNewBiome) {
|
if (!this.gameMode.hasRandomBiomes && !isNewBiome) {
|
||||||
this.pushPhase(new NextEncounterPhase());
|
this.phaseManager.pushNew("NextEncounterPhase");
|
||||||
} else {
|
} else {
|
||||||
this.pushPhase(new NewBiomeEncounterPhase());
|
this.phaseManager.pushNew("NewBiomeEncounterPhase");
|
||||||
|
|
||||||
const newMaxExpLevel = this.getMaxExpLevel();
|
const newMaxExpLevel = this.getMaxExpLevel();
|
||||||
if (newMaxExpLevel > maxExpLevel) {
|
if (newMaxExpLevel > maxExpLevel) {
|
||||||
this.pushPhase(new LevelCapPhase());
|
this.phaseManager.pushNew("LevelCapPhase");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1599,7 +1568,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isEggPhase: boolean = ["EggLapsePhase", "EggHatchPhase"].includes(
|
const isEggPhase: boolean = ["EggLapsePhase", "EggHatchPhase"].includes(
|
||||||
this.getCurrentPhase()?.constructor.name ?? "",
|
this.phaseManager.getCurrentPhase()?.phaseName ?? "",
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -2627,286 +2596,6 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Phase Functions */
|
|
||||||
getCurrentPhase(): Phase | null {
|
|
||||||
return this.currentPhase;
|
|
||||||
}
|
|
||||||
|
|
||||||
getStandbyPhase(): Phase | null {
|
|
||||||
return this.standbyPhase;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a phase to the conditional queue and ensures it is executed only when the specified condition is met.
|
|
||||||
*
|
|
||||||
* This method allows deferring the execution of a phase until certain conditions are met, which is useful for handling
|
|
||||||
* situations like abilities and entry hazards that depend on specific game states.
|
|
||||||
*
|
|
||||||
* @param {Phase} phase - The phase to be added to the conditional queue.
|
|
||||||
* @param {() => boolean} condition - A function that returns a boolean indicating whether the phase should be executed.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
pushConditionalPhase(phase: Phase, condition: () => boolean): void {
|
|
||||||
this.conditionalQueue.push([condition, phase]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a phase to nextCommandPhaseQueue, as long as boolean passed in is false
|
|
||||||
* @param phase {@linkcode Phase} the phase to add
|
|
||||||
* @param defer boolean on which queue to add to, defaults to false, and adds to phaseQueue
|
|
||||||
*/
|
|
||||||
pushPhase(phase: Phase, defer = false): void {
|
|
||||||
(!defer ? this.phaseQueue : this.nextCommandPhaseQueue).push(phase);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds Phase(s) to the end of phaseQueuePrepend, or at phaseQueuePrependSpliceIndex
|
|
||||||
* @param phases {@linkcode Phase} the phase(s) to add
|
|
||||||
*/
|
|
||||||
unshiftPhase(...phases: Phase[]): void {
|
|
||||||
if (this.phaseQueuePrependSpliceIndex === -1) {
|
|
||||||
this.phaseQueuePrepend.push(...phases);
|
|
||||||
} else {
|
|
||||||
this.phaseQueuePrepend.splice(this.phaseQueuePrependSpliceIndex, 0, ...phases);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the phaseQueue
|
|
||||||
*/
|
|
||||||
clearPhaseQueue(): void {
|
|
||||||
this.phaseQueue.splice(0, this.phaseQueue.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears all phase-related stuff, including all phase queues, the current and standby phases, and a splice index
|
|
||||||
*/
|
|
||||||
clearAllPhases(): void {
|
|
||||||
for (const queue of [this.phaseQueue, this.phaseQueuePrepend, this.conditionalQueue, this.nextCommandPhaseQueue]) {
|
|
||||||
queue.splice(0, queue.length);
|
|
||||||
}
|
|
||||||
this.currentPhase = null;
|
|
||||||
this.standbyPhase = null;
|
|
||||||
this.clearPhaseQueueSplice();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by function unshiftPhase(), sets index to start inserting at current length instead of the end of the array, useful if phaseQueuePrepend gets longer with Phases
|
|
||||||
*/
|
|
||||||
setPhaseQueueSplice(): void {
|
|
||||||
this.phaseQueuePrependSpliceIndex = this.phaseQueuePrepend.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets phaseQueuePrependSpliceIndex to -1, implies that calls to unshiftPhase will insert at end of phaseQueuePrepend
|
|
||||||
*/
|
|
||||||
clearPhaseQueueSplice(): void {
|
|
||||||
this.phaseQueuePrependSpliceIndex = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is called by each Phase implementations "end()" by default
|
|
||||||
* We dump everything from phaseQueuePrepend to the start of of phaseQueue
|
|
||||||
* then removes first Phase and starts it
|
|
||||||
*/
|
|
||||||
shiftPhase(): void {
|
|
||||||
if (this.standbyPhase) {
|
|
||||||
this.currentPhase = this.standbyPhase;
|
|
||||||
this.standbyPhase = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.phaseQueuePrependSpliceIndex > -1) {
|
|
||||||
this.clearPhaseQueueSplice();
|
|
||||||
}
|
|
||||||
if (this.phaseQueuePrepend.length) {
|
|
||||||
while (this.phaseQueuePrepend.length) {
|
|
||||||
const poppedPhase = this.phaseQueuePrepend.pop();
|
|
||||||
if (poppedPhase) {
|
|
||||||
this.phaseQueue.unshift(poppedPhase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!this.phaseQueue.length) {
|
|
||||||
this.populatePhaseQueue();
|
|
||||||
// Clear the conditionalQueue if there are no phases left in the phaseQueue
|
|
||||||
this.conditionalQueue = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currentPhase = this.phaseQueue.shift() ?? null;
|
|
||||||
|
|
||||||
// Check if there are any conditional phases queued
|
|
||||||
if (this.conditionalQueue?.length) {
|
|
||||||
// Retrieve the first conditional phase from the queue
|
|
||||||
const conditionalPhase = this.conditionalQueue.shift();
|
|
||||||
// Evaluate the condition associated with the phase
|
|
||||||
if (conditionalPhase?.[0]()) {
|
|
||||||
// If the condition is met, add the phase to the phase queue
|
|
||||||
this.pushPhase(conditionalPhase[1]);
|
|
||||||
} else if (conditionalPhase) {
|
|
||||||
// If the condition is not met, re-add the phase back to the front of the conditional queue
|
|
||||||
this.conditionalQueue.unshift(conditionalPhase);
|
|
||||||
} else {
|
|
||||||
console.warn("condition phase is undefined/null!", conditionalPhase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.currentPhase) {
|
|
||||||
console.log(`%cStart Phase ${this.currentPhase.constructor.name}`, "color:green;");
|
|
||||||
this.currentPhase.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
overridePhase(phase: Phase): boolean {
|
|
||||||
if (this.standbyPhase) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.standbyPhase = this.currentPhase;
|
|
||||||
this.currentPhase = phase;
|
|
||||||
console.log(`%cStart Phase ${phase.constructor.name}`, "color:green;");
|
|
||||||
phase.start();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a specific {@linkcode Phase} in the phase queue.
|
|
||||||
*
|
|
||||||
* @param phaseFilter filter function to use to find the wanted phase
|
|
||||||
* @returns the found phase or undefined if none found
|
|
||||||
*/
|
|
||||||
findPhase<P extends Phase = Phase>(phaseFilter: (phase: P) => boolean): P | undefined {
|
|
||||||
return this.phaseQueue.find(phaseFilter) as P;
|
|
||||||
}
|
|
||||||
|
|
||||||
tryReplacePhase(phaseFilter: (phase: Phase) => boolean, phase: Phase): boolean {
|
|
||||||
const phaseIndex = this.phaseQueue.findIndex(phaseFilter);
|
|
||||||
if (phaseIndex > -1) {
|
|
||||||
this.phaseQueue[phaseIndex] = phase;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
tryRemovePhase(phaseFilter: (phase: Phase) => boolean): boolean {
|
|
||||||
const phaseIndex = this.phaseQueue.findIndex(phaseFilter);
|
|
||||||
if (phaseIndex > -1) {
|
|
||||||
this.phaseQueue.splice(phaseIndex, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Will search for a specific phase in {@linkcode phaseQueuePrepend} via filter, and remove the first result if a match is found.
|
|
||||||
* @param phaseFilter filter function
|
|
||||||
*/
|
|
||||||
tryRemoveUnshiftedPhase(phaseFilter: (phase: Phase) => boolean): boolean {
|
|
||||||
const phaseIndex = this.phaseQueuePrepend.findIndex(phaseFilter);
|
|
||||||
if (phaseIndex > -1) {
|
|
||||||
this.phaseQueuePrepend.splice(phaseIndex, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to add the input phase to index before target phase in the phaseQueue, else simply calls unshiftPhase()
|
|
||||||
* @param phase {@linkcode Phase} the phase to be added
|
|
||||||
* @param targetPhase {@linkcode Phase} the type of phase to search for in phaseQueue
|
|
||||||
* @returns boolean if a targetPhase was found and added
|
|
||||||
*/
|
|
||||||
prependToPhase(phase: Phase | Phase[], targetPhase: Constructor<Phase>): boolean {
|
|
||||||
if (!Array.isArray(phase)) {
|
|
||||||
phase = [phase];
|
|
||||||
}
|
|
||||||
const targetIndex = this.phaseQueue.findIndex(ph => ph instanceof targetPhase);
|
|
||||||
|
|
||||||
if (targetIndex !== -1) {
|
|
||||||
this.phaseQueue.splice(targetIndex, 0, ...phase);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
this.unshiftPhase(...phase);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to add the input phase(s) to index after target phase in the {@linkcode phaseQueue}, else simply calls {@linkcode unshiftPhase()}
|
|
||||||
* @param phase {@linkcode Phase} the phase(s) to be added
|
|
||||||
* @param targetPhase {@linkcode Phase} the type of phase to search for in {@linkcode phaseQueue}
|
|
||||||
* @returns `true` if a `targetPhase` was found to append to
|
|
||||||
*/
|
|
||||||
appendToPhase(phase: Phase | Phase[], targetPhase: Constructor<Phase>): boolean {
|
|
||||||
if (!Array.isArray(phase)) {
|
|
||||||
phase = [phase];
|
|
||||||
}
|
|
||||||
const targetIndex = this.phaseQueue.findIndex(ph => ph instanceof targetPhase);
|
|
||||||
|
|
||||||
if (targetIndex !== -1 && this.phaseQueue.length > targetIndex) {
|
|
||||||
this.phaseQueue.splice(targetIndex + 1, 0, ...phase);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
this.unshiftPhase(...phase);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a MessagePhase, either to PhaseQueuePrepend or nextCommandPhaseQueue
|
|
||||||
* @param message string for MessagePhase
|
|
||||||
* @param callbackDelay optional param for MessagePhase constructor
|
|
||||||
* @param prompt optional param for MessagePhase constructor
|
|
||||||
* @param promptDelay optional param for MessagePhase constructor
|
|
||||||
* @param defer boolean for which queue to add it to, false -> add to PhaseQueuePrepend, true -> nextCommandPhaseQueue
|
|
||||||
*/
|
|
||||||
queueMessage(
|
|
||||||
message: string,
|
|
||||||
callbackDelay?: number | null,
|
|
||||||
prompt?: boolean | null,
|
|
||||||
promptDelay?: number | null,
|
|
||||||
defer?: boolean | null,
|
|
||||||
) {
|
|
||||||
const phase = new MessagePhase(message, callbackDelay, prompt, promptDelay);
|
|
||||||
if (!defer) {
|
|
||||||
// adds to the end of PhaseQueuePrepend
|
|
||||||
this.unshiftPhase(phase);
|
|
||||||
} else {
|
|
||||||
//remember that pushPhase adds it to nextCommandPhaseQueue
|
|
||||||
this.pushPhase(phase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Queues an ability bar flyout phase
|
|
||||||
* @param pokemon The pokemon who has the ability
|
|
||||||
* @param passive Whether the ability is a passive
|
|
||||||
* @param show Whether to show or hide the bar
|
|
||||||
*/
|
|
||||||
public queueAbilityDisplay(pokemon: Pokemon, passive: boolean, show: boolean): void {
|
|
||||||
this.unshiftPhase(show ? new ShowAbilityPhase(pokemon.getBattlerIndex(), passive) : new HideAbilityPhase());
|
|
||||||
this.clearPhaseQueueSplice();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hides the ability bar if it is currently visible
|
|
||||||
*/
|
|
||||||
public hideAbilityBar(): void {
|
|
||||||
if (this.abilityBar.isVisible()) {
|
|
||||||
this.unshiftPhase(new HideAbilityPhase());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves everything from nextCommandPhaseQueue to phaseQueue (keeping order)
|
|
||||||
*/
|
|
||||||
populatePhaseQueue(): void {
|
|
||||||
if (this.nextCommandPhaseQueue.length) {
|
|
||||||
this.phaseQueue.push(...this.nextCommandPhaseQueue);
|
|
||||||
this.nextCommandPhaseQueue.splice(0, this.nextCommandPhaseQueue.length);
|
|
||||||
}
|
|
||||||
this.phaseQueue.push(new TurnInitPhase());
|
|
||||||
}
|
|
||||||
|
|
||||||
addMoney(amount: number): void {
|
addMoney(amount: number): void {
|
||||||
this.money = Math.min(this.money + amount, Number.MAX_SAFE_INTEGER);
|
this.money = Math.min(this.money + amount, Number.MAX_SAFE_INTEGER);
|
||||||
this.updateMoneyText();
|
this.updateMoneyText();
|
||||||
@ -2954,7 +2643,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
} else if (!virtual) {
|
} else if (!virtual) {
|
||||||
const defaultModifierType = getDefaultModifierTypeForTier(modifier.type.tier);
|
const defaultModifierType = getDefaultModifierTypeForTier(modifier.type.tier);
|
||||||
this.queueMessage(
|
this.phaseManager.queueMessage(
|
||||||
i18next.t("battle:itemStackFull", {
|
i18next.t("battle:itemStackFull", {
|
||||||
fullItemName: modifier.type.name,
|
fullItemName: modifier.type.name,
|
||||||
itemName: defaultModifierType.name,
|
itemName: defaultModifierType.name,
|
||||||
@ -3545,17 +3234,17 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
if (matchingFormChange) {
|
if (matchingFormChange) {
|
||||||
let phase: Phase;
|
let phase: Phase;
|
||||||
if (pokemon instanceof PlayerPokemon && !matchingFormChange.quiet) {
|
if (pokemon.isPlayer() && !matchingFormChange.quiet) {
|
||||||
phase = new FormChangePhase(pokemon, matchingFormChange, modal);
|
phase = this.phaseManager.create("FormChangePhase", pokemon, matchingFormChange, modal);
|
||||||
} else {
|
} else {
|
||||||
phase = new QuietFormChangePhase(pokemon, matchingFormChange);
|
phase = this.phaseManager.create("QuietFormChangePhase", pokemon, matchingFormChange);
|
||||||
}
|
}
|
||||||
if (pokemon instanceof PlayerPokemon && !matchingFormChange.quiet && modal) {
|
if (pokemon.isPlayer() && !matchingFormChange.quiet && modal) {
|
||||||
this.overridePhase(phase);
|
this.phaseManager.overridePhase(phase);
|
||||||
} else if (delayed) {
|
} else if (delayed) {
|
||||||
this.pushPhase(phase);
|
this.phaseManager.pushPhase(phase);
|
||||||
} else {
|
} else {
|
||||||
this.unshiftPhase(phase);
|
this.phaseManager.unshiftPhase(phase);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3570,11 +3259,12 @@ export default class BattleScene extends SceneBase {
|
|||||||
fieldAssets?: Phaser.GameObjects.Sprite[],
|
fieldAssets?: Phaser.GameObjects.Sprite[],
|
||||||
delayed = false,
|
delayed = false,
|
||||||
): boolean {
|
): boolean {
|
||||||
const phase: Phase = new PokemonAnimPhase(battleAnimType, pokemon, fieldAssets);
|
const phaseManager = this.phaseManager;
|
||||||
|
const phase: Phase = phaseManager.create("PokemonAnimPhase", battleAnimType, pokemon, fieldAssets);
|
||||||
if (delayed) {
|
if (delayed) {
|
||||||
this.pushPhase(phase);
|
phaseManager.pushPhase(phase);
|
||||||
} else {
|
} else {
|
||||||
this.unshiftPhase(phase);
|
phaseManager.unshiftPhase(phase);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3619,21 +3309,18 @@ export default class BattleScene extends SceneBase {
|
|||||||
gameMode: this.currentBattle ? this.gameMode.getName() : "Title",
|
gameMode: this.currentBattle ? this.gameMode.getName() : "Title",
|
||||||
biome: this.currentBattle ? getBiomeName(this.arena.biomeType) : "",
|
biome: this.currentBattle ? getBiomeName(this.arena.biomeType) : "",
|
||||||
wave: this.currentBattle?.waveIndex ?? 0,
|
wave: this.currentBattle?.waveIndex ?? 0,
|
||||||
party: this.party
|
party:
|
||||||
? this.party.map(p => {
|
this.party?.map(p => ({
|
||||||
return {
|
name: p.name,
|
||||||
name: p.name,
|
form: p.getFormKey(),
|
||||||
form: p.getFormKey(),
|
types: p.getTypes().map(type => PokemonType[type]),
|
||||||
types: p.getTypes().map(type => PokemonType[type]),
|
teraType: PokemonType[p.getTeraType()],
|
||||||
teraType: PokemonType[p.getTeraType()],
|
isTerastallized: p.isTerastallized,
|
||||||
isTerastallized: p.isTerastallized,
|
level: p.level,
|
||||||
level: p.level,
|
currentHP: p.hp,
|
||||||
currentHP: p.hp,
|
maxHP: p.getMaxHp(),
|
||||||
maxHP: p.getMaxHp(),
|
status: p.status?.effect ? StatusEffect[p.status.effect] : "",
|
||||||
status: p.status?.effect ? StatusEffect[p.status.effect] : "",
|
})) ?? [], // TODO: review if this can be nullish
|
||||||
};
|
|
||||||
})
|
|
||||||
: [],
|
|
||||||
modeChain: this.ui?.getModeChain() ?? [],
|
modeChain: this.ui?.getModeChain() ?? [],
|
||||||
};
|
};
|
||||||
(window as any).gameInfo = gameInfo;
|
(window as any).gameInfo = gameInfo;
|
||||||
@ -3651,7 +3338,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
activePokemon = activePokemon.concat(this.getEnemyParty());
|
activePokemon = activePokemon.concat(this.getEnemyParty());
|
||||||
for (const p of activePokemon) {
|
for (const p of activePokemon) {
|
||||||
keys.push(p.getSpriteKey(true));
|
keys.push(p.getSpriteKey(true));
|
||||||
if (p instanceof PlayerPokemon) {
|
if (p.isPlayer()) {
|
||||||
keys.push(p.getBattleSpriteKey(true, true));
|
keys.push(p.getBattleSpriteKey(true, true));
|
||||||
}
|
}
|
||||||
keys.push(p.species.getCryKey(p.formIndex));
|
keys.push(p.species.getCryKey(p.formIndex));
|
||||||
@ -3667,7 +3354,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
* @param pokemon The (enemy) pokemon
|
* @param pokemon The (enemy) pokemon
|
||||||
*/
|
*/
|
||||||
initFinalBossPhaseTwo(pokemon: Pokemon): void {
|
initFinalBossPhaseTwo(pokemon: Pokemon): void {
|
||||||
if (pokemon instanceof EnemyPokemon && pokemon.isBoss() && !pokemon.formIndex && pokemon.bossSegmentIndex < 1) {
|
if (pokemon.isEnemy() && pokemon.isBoss() && !pokemon.formIndex && pokemon.bossSegmentIndex < 1) {
|
||||||
this.fadeOutBgm(fixedInt(2000), false);
|
this.fadeOutBgm(fixedInt(2000), false);
|
||||||
this.ui.showDialogue(
|
this.ui.showDialogue(
|
||||||
battleSpecDialogue[BattleSpec.FINAL_BOSS].firstStageWin,
|
battleSpecDialogue[BattleSpec.FINAL_BOSS].firstStageWin,
|
||||||
@ -3685,19 +3372,19 @@ export default class BattleScene extends SceneBase {
|
|||||||
this.currentBattle.double = true;
|
this.currentBattle.double = true;
|
||||||
const availablePartyMembers = this.getPlayerParty().filter(p => p.isAllowedInBattle());
|
const availablePartyMembers = this.getPlayerParty().filter(p => p.isAllowedInBattle());
|
||||||
if (availablePartyMembers.length > 1) {
|
if (availablePartyMembers.length > 1) {
|
||||||
this.pushPhase(new ToggleDoublePositionPhase(true));
|
this.phaseManager.pushNew("ToggleDoublePositionPhase", true);
|
||||||
if (!availablePartyMembers[1].isOnField()) {
|
if (!availablePartyMembers[1].isOnField()) {
|
||||||
this.pushPhase(new SummonPhase(1));
|
this.phaseManager.pushNew("SummonPhase", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.shiftPhase();
|
this.phaseManager.shiftPhase();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.shiftPhase();
|
this.phaseManager.shiftPhase();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3809,10 +3496,10 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
if (exp) {
|
if (exp) {
|
||||||
const partyMemberIndex = party.indexOf(expPartyMembers[pm]);
|
const partyMemberIndex = party.indexOf(expPartyMembers[pm]);
|
||||||
this.unshiftPhase(
|
this.phaseManager.unshiftPhase(
|
||||||
expPartyMembers[pm].isOnField()
|
expPartyMembers[pm].isOnField()
|
||||||
? new ExpPhase(partyMemberIndex, exp)
|
? this.phaseManager.create("ExpPhase", partyMemberIndex, exp)
|
||||||
: new ShowPartyExpBarPhase(partyMemberIndex, exp),
|
: this.phaseManager.create("ShowPartyExpBarPhase", partyMemberIndex, exp),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4016,16 +3703,13 @@ export default class BattleScene extends SceneBase {
|
|||||||
if (previousEncounter !== null && encounterType === previousEncounter) {
|
if (previousEncounter !== null && encounterType === previousEncounter) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (
|
return !(
|
||||||
this.mysteryEncounterSaveData.encounteredEvents.length > 0 &&
|
this.mysteryEncounterSaveData.encounteredEvents.length > 0 &&
|
||||||
encounterCandidate.maxAllowedEncounters &&
|
encounterCandidate.maxAllowedEncounters &&
|
||||||
encounterCandidate.maxAllowedEncounters > 0 &&
|
encounterCandidate.maxAllowedEncounters > 0 &&
|
||||||
this.mysteryEncounterSaveData.encounteredEvents.filter(e => e.type === encounterType).length >=
|
this.mysteryEncounterSaveData.encounteredEvents.filter(e => e.type === encounterType).length >=
|
||||||
encounterCandidate.maxAllowedEncounters
|
encounterCandidate.maxAllowedEncounters
|
||||||
) {
|
);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
})
|
})
|
||||||
.map(m => allMysteryEncounters[m]);
|
.map(m => allMysteryEncounters[m]);
|
||||||
// Decrement tier
|
// Decrement tier
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
shiftCharCodes,
|
shiftCharCodes,
|
||||||
randSeedItem,
|
randSeedItem,
|
||||||
randInt,
|
randInt,
|
||||||
|
randSeedFloat,
|
||||||
} from "#app/utils/common";
|
} from "#app/utils/common";
|
||||||
import Trainer, { TrainerVariant } from "./field/trainer";
|
import Trainer, { TrainerVariant } from "./field/trainer";
|
||||||
import type { GameMode } from "./game-mode";
|
import type { GameMode } from "./game-mode";
|
||||||
@ -150,7 +151,7 @@ export default class Battle {
|
|||||||
randSeedGaussForLevel(value: number): number {
|
randSeedGaussForLevel(value: number): number {
|
||||||
let rand = 0;
|
let rand = 0;
|
||||||
for (let i = value; i > 0; i--) {
|
for (let i = value; i > 0; i--) {
|
||||||
rand += Phaser.Math.RND.realInRange(0, 1);
|
rand += randSeedFloat();
|
||||||
}
|
}
|
||||||
return rand / value;
|
return rand / value;
|
||||||
}
|
}
|
||||||
@ -199,7 +200,7 @@ export default class Battle {
|
|||||||
const message = i18next.t("battle:moneyPickedUp", {
|
const message = i18next.t("battle:moneyPickedUp", {
|
||||||
moneyAmount: formattedMoneyAmount,
|
moneyAmount: formattedMoneyAmount,
|
||||||
});
|
});
|
||||||
globalScene.queueMessage(message, undefined, true);
|
globalScene.phaseManager.queueMessage(message, undefined, true);
|
||||||
|
|
||||||
globalScene.currentBattle.moneyScattered = 0;
|
globalScene.currentBattle.moneyScattered = 0;
|
||||||
}
|
}
|
||||||
|
@ -197,10 +197,7 @@ export function canIAssignThisKey(config, key) {
|
|||||||
export function canIOverrideThisSetting(config, settingName) {
|
export function canIOverrideThisSetting(config, settingName) {
|
||||||
const key = getKeyWithSettingName(config, settingName);
|
const key = getKeyWithSettingName(config, settingName);
|
||||||
// || isTheLatestBind(config, settingName) no longer needed since action and cancel are protected
|
// || isTheLatestBind(config, settingName) no longer needed since action and cancel are protected
|
||||||
if (config.blacklist?.includes(key)) {
|
return !config.blacklist?.includes(key);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function canIDeleteThisKey(config, key) {
|
export function canIDeleteThisKey(config, key) {
|
||||||
|
@ -2,7 +2,7 @@ import { AbilityId } from "#enums/ability-id";
|
|||||||
import type { AbAttrCondition } from "#app/@types/ability-types";
|
import type { AbAttrCondition } from "#app/@types/ability-types";
|
||||||
import type { AbAttr } from "#app/data/abilities/ab-attrs/ab-attr";
|
import type { AbAttr } from "#app/data/abilities/ab-attrs/ab-attr";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import type { Localizable } from "#app/interfaces/locales";
|
import type { Localizable } from "#app/@types/locales";
|
||||||
import type { Constructor } from "#app/utils/common";
|
import type { Constructor } from "#app/utils/common";
|
||||||
|
|
||||||
export class Ability implements Localizable {
|
export class Ability implements Localizable {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -26,10 +26,6 @@ import { AbilityId } from "#enums/ability-id";
|
|||||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
|
||||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { CommonAnimPhase } from "#app/phases/common-anim-phase";
|
|
||||||
|
|
||||||
export enum ArenaTagSide {
|
export enum ArenaTagSide {
|
||||||
BOTH,
|
BOTH,
|
||||||
@ -54,7 +50,7 @@ export abstract class ArenaTag {
|
|||||||
|
|
||||||
onRemove(_arena: Arena, quiet = false): void {
|
onRemove(_arena: Arena, quiet = false): void {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:arenaOnRemove${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:arenaOnRemove${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
{ moveName: this.getMoveName() },
|
{ moveName: this.getMoveName() },
|
||||||
@ -134,7 +130,7 @@ export class MistTag extends ArenaTag {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:mistOnAdd", {
|
i18next.t("arenaTag:mistOnAdd", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
||||||
}),
|
}),
|
||||||
@ -165,7 +161,7 @@ export class MistTag extends ArenaTag {
|
|||||||
cancelled.value = true;
|
cancelled.value = true;
|
||||||
|
|
||||||
if (!simulated) {
|
if (!simulated) {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:mistApply"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:mistApply"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -243,7 +239,7 @@ class ReflectTag extends WeakenMoveScreenTag {
|
|||||||
|
|
||||||
onAdd(_arena: Arena, quiet = false): void {
|
onAdd(_arena: Arena, quiet = false): void {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:reflectOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:reflectOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -263,7 +259,7 @@ class LightScreenTag extends WeakenMoveScreenTag {
|
|||||||
|
|
||||||
onAdd(_arena: Arena, quiet = false): void {
|
onAdd(_arena: Arena, quiet = false): void {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:lightScreenOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:lightScreenOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -286,7 +282,7 @@ class AuroraVeilTag extends WeakenMoveScreenTag {
|
|||||||
|
|
||||||
onAdd(_arena: Arena, quiet = false): void {
|
onAdd(_arena: Arena, quiet = false): void {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:auroraVeilOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:auroraVeilOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -322,7 +318,7 @@ export class ConditionalProtectTag extends ArenaTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:conditionalProtectOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:conditionalProtectOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
{ moveName: super.getMoveName() },
|
{ moveName: super.getMoveName() },
|
||||||
@ -359,7 +355,7 @@ export class ConditionalProtectTag extends ArenaTag {
|
|||||||
isProtected.value = true;
|
isProtected.value = true;
|
||||||
if (!simulated) {
|
if (!simulated) {
|
||||||
new CommonBattleAnim(CommonAnim.PROTECT, defender).play();
|
new CommonBattleAnim(CommonAnim.PROTECT, defender).play();
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:conditionalProtectApply", {
|
i18next.t("arenaTag:conditionalProtectApply", {
|
||||||
moveName: super.getMoveName(),
|
moveName: super.getMoveName(),
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(defender),
|
pokemonNameWithAffix: getPokemonNameWithAffix(defender),
|
||||||
@ -385,9 +381,9 @@ export class ConditionalProtectTag extends ArenaTag {
|
|||||||
*/
|
*/
|
||||||
const QuickGuardConditionFunc: ProtectConditionFunc = (_arena, moveId) => {
|
const QuickGuardConditionFunc: ProtectConditionFunc = (_arena, moveId) => {
|
||||||
const move = allMoves[moveId];
|
const move = allMoves[moveId];
|
||||||
const effectPhase = globalScene.getCurrentPhase();
|
const effectPhase = globalScene.phaseManager.getCurrentPhase();
|
||||||
|
|
||||||
if (effectPhase instanceof MoveEffectPhase) {
|
if (effectPhase?.is("MoveEffectPhase")) {
|
||||||
const attacker = effectPhase.getUserPokemon();
|
const attacker = effectPhase.getUserPokemon();
|
||||||
if (attacker) {
|
if (attacker) {
|
||||||
return move.getPriority(attacker) > 0;
|
return move.getPriority(attacker) > 0;
|
||||||
@ -466,7 +462,7 @@ class MatBlockTag extends ConditionalProtectTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
super.onAdd(_arena);
|
super.onAdd(_arena);
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:matBlockOnAdd", {
|
i18next.t("arenaTag:matBlockOnAdd", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
||||||
}),
|
}),
|
||||||
@ -521,7 +517,7 @@ export class NoCritTag extends ArenaTag {
|
|||||||
|
|
||||||
/** Queues a message upon adding this effect to the field */
|
/** Queues a message upon adding this effect to the field */
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(`arenaTag:noCritOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : "Enemy"}`, {
|
i18next.t(`arenaTag:noCritOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : "Enemy"}`, {
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
}),
|
}),
|
||||||
@ -536,7 +532,7 @@ export class NoCritTag extends ArenaTag {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:noCritOnRemove", {
|
i18next.t("arenaTag:noCritOnRemove", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(source ?? undefined),
|
pokemonNameWithAffix: getPokemonNameWithAffix(source ?? undefined),
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
@ -568,7 +564,7 @@ class WishTag extends ArenaTag {
|
|||||||
super.onAdd(_arena);
|
super.onAdd(_arena);
|
||||||
this.healHp = toDmgValue(source.getMaxHp() / 2);
|
this.healHp = toDmgValue(source.getMaxHp() / 2);
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:wishTagOnAdd", {
|
i18next.t("arenaTag:wishTagOnAdd", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
||||||
}),
|
}),
|
||||||
@ -578,8 +574,8 @@ class WishTag extends ArenaTag {
|
|||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
const target = globalScene.getField()[this.battlerIndex];
|
const target = globalScene.getField()[this.battlerIndex];
|
||||||
if (target?.isActive(true)) {
|
if (target?.isActive(true)) {
|
||||||
globalScene.queueMessage(this.triggerMessage);
|
globalScene.phaseManager.queueMessage(this.triggerMessage);
|
||||||
globalScene.unshiftPhase(new PokemonHealPhase(target.getBattlerIndex(), this.healHp, null, true, false));
|
globalScene.phaseManager.unshiftNew("PokemonHealPhase", target.getBattlerIndex(), this.healHp, null, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -632,11 +628,11 @@ class MudSportTag extends WeakenMoveTypeTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:mudSportOnAdd"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:mudSportOnAdd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:mudSportOnRemove"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:mudSportOnRemove"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,11 +646,11 @@ class WaterSportTag extends WeakenMoveTypeTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:waterSportOnAdd"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:waterSportOnAdd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:waterSportOnRemove"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:waterSportOnRemove"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,7 +666,7 @@ export class IonDelugeTag extends ArenaTag {
|
|||||||
|
|
||||||
/** Queues an on-add message */
|
/** Queues an on-add message */
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:plasmaFistsOnAdd"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:plasmaFistsOnAdd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {} // Removes default on-remove message
|
onRemove(_arena: Arena): void {} // Removes default on-remove message
|
||||||
@ -778,7 +774,7 @@ class SpikesTag extends ArenaTrapTag {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:spikesOnAdd", {
|
i18next.t("arenaTag:spikesOnAdd", {
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
opponentDesc: source.getOpponentDescriptor(),
|
opponentDesc: source.getOpponentDescriptor(),
|
||||||
@ -800,7 +796,7 @@ class SpikesTag extends ArenaTrapTag {
|
|||||||
const damageHpRatio = 1 / (10 - 2 * this.layers);
|
const damageHpRatio = 1 / (10 - 2 * this.layers);
|
||||||
const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio);
|
const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio);
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:spikesActivateTrap", {
|
i18next.t("arenaTag:spikesActivateTrap", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
}),
|
}),
|
||||||
@ -839,7 +835,7 @@ class ToxicSpikesTag extends ArenaTrapTag {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:toxicSpikesOnAdd", {
|
i18next.t("arenaTag:toxicSpikesOnAdd", {
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
opponentDesc: source.getOpponentDescriptor(),
|
opponentDesc: source.getOpponentDescriptor(),
|
||||||
@ -861,7 +857,7 @@ class ToxicSpikesTag extends ArenaTrapTag {
|
|||||||
if (pokemon.isOfType(PokemonType.POISON)) {
|
if (pokemon.isOfType(PokemonType.POISON)) {
|
||||||
this.neutralized = true;
|
this.neutralized = true;
|
||||||
if (globalScene.arena.removeTag(this.tagType)) {
|
if (globalScene.arena.removeTag(this.tagType)) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:toxicSpikesActivateTrapPoison", {
|
i18next.t("arenaTag:toxicSpikesActivateTrapPoison", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
@ -918,8 +914,13 @@ export class DelayedAttackTag extends ArenaTag {
|
|||||||
const ret = super.lapse(arena);
|
const ret = super.lapse(arena);
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new MoveEffectPhase(this.sourceId!, [this.targetIndex], allMoves[this.sourceMove!], false, true),
|
"MoveEffectPhase",
|
||||||
|
this.sourceId!,
|
||||||
|
[this.targetIndex],
|
||||||
|
allMoves[this.sourceMove!],
|
||||||
|
false,
|
||||||
|
true,
|
||||||
); // TODO: are those bangs correct?
|
); // TODO: are those bangs correct?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -948,7 +949,7 @@ class StealthRockTag extends ArenaTrapTag {
|
|||||||
|
|
||||||
const source = this.getSourcePokemon();
|
const source = this.getSourcePokemon();
|
||||||
if (!quiet && source) {
|
if (!quiet && source) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:stealthRockOnAdd", {
|
i18next.t("arenaTag:stealthRockOnAdd", {
|
||||||
opponentDesc: source.getOpponentDescriptor(),
|
opponentDesc: source.getOpponentDescriptor(),
|
||||||
}),
|
}),
|
||||||
@ -1002,7 +1003,7 @@ class StealthRockTag extends ArenaTrapTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio);
|
const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio);
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:stealthRockActivateTrap", {
|
i18next.t("arenaTag:stealthRockActivateTrap", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
}),
|
}),
|
||||||
@ -1042,7 +1043,7 @@ class StickyWebTag extends ArenaTrapTag {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:spikesOnAdd", {
|
i18next.t("arenaTag:spikesOnAdd", {
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
opponentDesc: source.getOpponentDescriptor(),
|
opponentDesc: source.getOpponentDescriptor(),
|
||||||
@ -1060,25 +1061,24 @@ class StickyWebTag extends ArenaTrapTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!cancelled.value) {
|
if (!cancelled.value) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:stickyWebActivateTrap", {
|
i18next.t("arenaTag:stickyWebActivateTrap", {
|
||||||
pokemonName: pokemon.getNameToRender(),
|
pokemonName: pokemon.getNameToRender(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
const stages = new NumberHolder(-1);
|
const stages = new NumberHolder(-1);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(
|
"StatStageChangePhase",
|
||||||
pokemon.getBattlerIndex(),
|
pokemon.getBattlerIndex(),
|
||||||
false,
|
false,
|
||||||
[Stat.SPD],
|
[Stat.SPD],
|
||||||
stages.value,
|
stages.value,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
null,
|
null,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1120,7 +1120,7 @@ export class TrickRoomTag extends ArenaTag {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:spikesOnAdd", {
|
i18next.t("arenaTag:spikesOnAdd", {
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
opponentDesc: source.getOpponentDescriptor(),
|
opponentDesc: source.getOpponentDescriptor(),
|
||||||
@ -1129,7 +1129,7 @@ export class TrickRoomTag extends ArenaTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:trickRoomOnRemove"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:trickRoomOnRemove"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1144,7 +1144,7 @@ export class GravityTag extends ArenaTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:gravityOnAdd"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:gravityOnAdd"));
|
||||||
globalScene.getField(true).forEach(pokemon => {
|
globalScene.getField(true).forEach(pokemon => {
|
||||||
if (pokemon !== null) {
|
if (pokemon !== null) {
|
||||||
pokemon.removeTag(BattlerTagType.FLOATING);
|
pokemon.removeTag(BattlerTagType.FLOATING);
|
||||||
@ -1157,7 +1157,7 @@ export class GravityTag extends ArenaTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:gravityOnRemove"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:gravityOnRemove"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1180,7 +1180,7 @@ class TailwindTag extends ArenaTag {
|
|||||||
super.onAdd(_arena, quiet);
|
super.onAdd(_arena, quiet);
|
||||||
|
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:tailwindOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:tailwindOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1191,28 +1191,30 @@ class TailwindTag extends ArenaTag {
|
|||||||
|
|
||||||
for (const pokemon of field) {
|
for (const pokemon of field) {
|
||||||
// Apply the CHARGED tag to party members with the WIND_POWER ability
|
// Apply the CHARGED tag to party members with the WIND_POWER ability
|
||||||
|
// TODO: This should not be handled here
|
||||||
if (pokemon.hasAbility(AbilityId.WIND_POWER) && !pokemon.getTag(BattlerTagType.CHARGED)) {
|
if (pokemon.hasAbility(AbilityId.WIND_POWER) && !pokemon.getTag(BattlerTagType.CHARGED)) {
|
||||||
pokemon.addTag(BattlerTagType.CHARGED);
|
pokemon.addTag(BattlerTagType.CHARGED);
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("abilityTriggers:windPowerCharged", {
|
i18next.t("abilityTriggers:windPowerCharged", {
|
||||||
pokemonName: getPokemonNameWithAffix(pokemon),
|
pokemonName: getPokemonNameWithAffix(pokemon),
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raise attack by one stage if party member has WIND_RIDER ability
|
// Raise attack by one stage if party member has WIND_RIDER ability
|
||||||
// TODO: Ability displays should be handled by the ability
|
// TODO: Ability displays should be handled by the ability
|
||||||
if (pokemon.hasAbility(AbilityId.WIND_RIDER)) {
|
if (pokemon.hasAbility(AbilityId.WIND_RIDER)) {
|
||||||
globalScene.queueAbilityDisplay(pokemon, false, true);
|
globalScene.phaseManager.queueAbilityDisplay(pokemon, false, true);
|
||||||
globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [Stat.ATK], 1, true));
|
globalScene.phaseManager.unshiftNew("StatStageChangePhase", pokemon.getBattlerIndex(), true, [Stat.ATK], 1, true);
|
||||||
globalScene.queueAbilityDisplay(pokemon, false, false);
|
globalScene.phaseManager.queueAbilityDisplay(pokemon, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena, quiet = false): void {
|
onRemove(_arena: Arena, quiet = false): void {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:tailwindOnRemove${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:tailwindOnRemove${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1231,11 +1233,11 @@ class HappyHourTag extends ArenaTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:happyHourOnAdd"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:happyHourOnAdd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:happyHourOnRemove"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:happyHourOnRemove"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1245,7 +1247,7 @@ class SafeguardTag extends ArenaTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:safeguardOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:safeguardOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1253,7 +1255,7 @@ class SafeguardTag extends ArenaTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:safeguardOnRemove${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:safeguardOnRemove${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1292,7 +1294,7 @@ class ImprisonTag extends ArenaTrapTag {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("battlerTags:imprisonOnAdd", {
|
i18next.t("battlerTags:imprisonOnAdd", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
||||||
}),
|
}),
|
||||||
@ -1346,7 +1348,7 @@ class FireGrassPledgeTag extends ArenaTag {
|
|||||||
|
|
||||||
override onAdd(_arena: Arena): void {
|
override onAdd(_arena: Arena): void {
|
||||||
// "A sea of fire enveloped your/the opposing team!"
|
// "A sea of fire enveloped your/the opposing team!"
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:fireGrassPledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:fireGrassPledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1361,14 +1363,17 @@ class FireGrassPledgeTag extends ArenaTag {
|
|||||||
.filter(pokemon => !pokemon.isOfType(PokemonType.FIRE) && !pokemon.switchOutStatus)
|
.filter(pokemon => !pokemon.isOfType(PokemonType.FIRE) && !pokemon.switchOutStatus)
|
||||||
.forEach(pokemon => {
|
.forEach(pokemon => {
|
||||||
// "{pokemonNameWithAffix} was hurt by the sea of fire!"
|
// "{pokemonNameWithAffix} was hurt by the sea of fire!"
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:fireGrassPledgeLapse", {
|
i18next.t("arenaTag:fireGrassPledgeLapse", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
// TODO: Replace this with a proper animation
|
// TODO: Replace this with a proper animation
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new CommonAnimPhase(pokemon.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.MAGMA_STORM),
|
"CommonAnimPhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
CommonAnim.MAGMA_STORM,
|
||||||
);
|
);
|
||||||
pokemon.damageAndUpdate(toDmgValue(pokemon.getMaxHp() / 8), { result: HitResult.INDIRECT });
|
pokemon.damageAndUpdate(toDmgValue(pokemon.getMaxHp() / 8), { result: HitResult.INDIRECT });
|
||||||
});
|
});
|
||||||
@ -1391,7 +1396,7 @@ class WaterFirePledgeTag extends ArenaTag {
|
|||||||
|
|
||||||
override onAdd(_arena: Arena): void {
|
override onAdd(_arena: Arena): void {
|
||||||
// "A rainbow appeared in the sky on your/the opposing team's side!"
|
// "A rainbow appeared in the sky on your/the opposing team's side!"
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:waterFirePledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:waterFirePledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1425,7 +1430,7 @@ class GrassWaterPledgeTag extends ArenaTag {
|
|||||||
|
|
||||||
override onAdd(_arena: Arena): void {
|
override onAdd(_arena: Arena): void {
|
||||||
// "A swamp enveloped your/the opposing team!"
|
// "A swamp enveloped your/the opposing team!"
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:grassWaterPledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:grassWaterPledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1446,7 +1451,7 @@ export class FairyLockTag extends ArenaTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:fairyLockOnAdd"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:fairyLockOnAdd"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1503,7 +1508,7 @@ export class SuppressAbilitiesTag extends ArenaTag {
|
|||||||
public override onRemove(_arena: Arena, quiet = false) {
|
public override onRemove(_arena: Arena, quiet = false) {
|
||||||
this.beingRemoved = true;
|
this.beingRemoved = true;
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:neutralizingGasOnRemove"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:neutralizingGasOnRemove"));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const pokemon of globalScene.getField(true)) {
|
for (const pokemon of globalScene.getField(true)) {
|
||||||
@ -1524,7 +1529,7 @@ export class SuppressAbilitiesTag extends ArenaTag {
|
|||||||
|
|
||||||
private playActivationMessage(pokemon: Pokemon | null) {
|
private playActivationMessage(pokemon: Pokemon | null) {
|
||||||
if (pokemon) {
|
if (pokemon) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:neutralizingGasOnAdd", {
|
i18next.t("arenaTag:neutralizingGasOnAdd", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
}),
|
}),
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,17 +3,11 @@ import type Pokemon from "../field/pokemon";
|
|||||||
import { HitResult } from "../field/pokemon";
|
import { HitResult } from "../field/pokemon";
|
||||||
import { getStatusEffectHealText } from "./status-effect";
|
import { getStatusEffectHealText } from "./status-effect";
|
||||||
import { NumberHolder, toDmgValue, randSeedInt } from "#app/utils/common";
|
import { NumberHolder, toDmgValue, randSeedInt } from "#app/utils/common";
|
||||||
import {
|
import { DoubleBerryEffectAbAttr, ReduceBerryUseThresholdAbAttr, applyAbAttrs } from "./abilities/ability";
|
||||||
DoubleBerryEffectAbAttr,
|
|
||||||
ReduceBerryUseThresholdAbAttr,
|
|
||||||
applyAbAttrs,
|
|
||||||
} from "./abilities/ability";
|
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { Stat, type BattleStat } from "#app/enums/stat";
|
import { Stat, type BattleStat } from "#app/enums/stat";
|
||||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
|
||||||
export function getBerryName(berryType: BerryType): string {
|
export function getBerryName(berryType: BerryType): string {
|
||||||
@ -79,23 +73,22 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
|
|||||||
{
|
{
|
||||||
const hpHealed = new NumberHolder(toDmgValue(consumer.getMaxHp() / 4));
|
const hpHealed = new NumberHolder(toDmgValue(consumer.getMaxHp() / 4));
|
||||||
applyAbAttrs(DoubleBerryEffectAbAttr, consumer, null, false, hpHealed);
|
applyAbAttrs(DoubleBerryEffectAbAttr, consumer, null, false, hpHealed);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new PokemonHealPhase(
|
"PokemonHealPhase",
|
||||||
consumer.getBattlerIndex(),
|
consumer.getBattlerIndex(),
|
||||||
hpHealed.value,
|
hpHealed.value,
|
||||||
i18next.t("battle:hpHealBerry", {
|
i18next.t("battle:hpHealBerry", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(consumer),
|
pokemonNameWithAffix: getPokemonNameWithAffix(consumer),
|
||||||
berryName: getBerryName(berryType),
|
berryName: getBerryName(berryType),
|
||||||
}),
|
}),
|
||||||
true,
|
true,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BerryType.LUM:
|
case BerryType.LUM:
|
||||||
{
|
{
|
||||||
if (consumer.status) {
|
if (consumer.status) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
getStatusEffectHealText(consumer.status.effect, getPokemonNameWithAffix(consumer)),
|
getStatusEffectHealText(consumer.status.effect, getPokemonNameWithAffix(consumer)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -113,8 +106,12 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
|
|||||||
const stat: BattleStat = berryType - BerryType.ENIGMA;
|
const stat: BattleStat = berryType - BerryType.ENIGMA;
|
||||||
const statStages = new NumberHolder(1);
|
const statStages = new NumberHolder(1);
|
||||||
applyAbAttrs(DoubleBerryEffectAbAttr, consumer, null, false, statStages);
|
applyAbAttrs(DoubleBerryEffectAbAttr, consumer, null, false, statStages);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(consumer.getBattlerIndex(), true, [stat], statStages.value),
|
"StatStageChangePhase",
|
||||||
|
consumer.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
[stat],
|
||||||
|
statStages.value,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -130,8 +127,12 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
|
|||||||
const randStat = randSeedInt(Stat.SPD, Stat.ATK);
|
const randStat = randSeedInt(Stat.SPD, Stat.ATK);
|
||||||
const stages = new NumberHolder(2);
|
const stages = new NumberHolder(2);
|
||||||
applyAbAttrs(DoubleBerryEffectAbAttr, consumer, null, false, stages);
|
applyAbAttrs(DoubleBerryEffectAbAttr, consumer, null, false, stages);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(consumer.getBattlerIndex(), true, [randStat], stages.value),
|
"StatStageChangePhase",
|
||||||
|
consumer.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
[randStat],
|
||||||
|
stages.value,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -144,7 +145,7 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
|
|||||||
consumer.getMoveset().find(m => m.ppUsed < m.getMovePp());
|
consumer.getMoveset().find(m => m.ppUsed < m.getMovePp());
|
||||||
if (ppRestoreMove) {
|
if (ppRestoreMove) {
|
||||||
ppRestoreMove.ppUsed = Math.max(ppRestoreMove.ppUsed - 10, 0);
|
ppRestoreMove.ppUsed = Math.max(ppRestoreMove.ppUsed - 10, 0);
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("battle:ppHealBerry", {
|
i18next.t("battle:ppHealBerry", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(consumer),
|
pokemonNameWithAffix: getPokemonNameWithAffix(consumer),
|
||||||
moveName: ppRestoreMove.getName(),
|
moveName: ppRestoreMove.getName(),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import type { DexEntry, StarterDataEntry } from "#app/system/game-data";
|
import type { StarterDataEntry } from "#app/system/game-data";
|
||||||
|
import type { DexEntry } from "#app/@types/dex-data";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores data associated with a specific egg and the hatched pokemon
|
* Stores data associated with a specific egg and the hatched pokemon
|
||||||
|
@ -29,7 +29,7 @@ import {
|
|||||||
} from "../status-effect";
|
} from "../status-effect";
|
||||||
import { getTypeDamageMultiplier } from "../type";
|
import { getTypeDamageMultiplier } from "../type";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { BooleanHolder, NumberHolder, isNullOrUndefined, toDmgValue, randSeedItem, randSeedInt, getEnumValues, toReadableString, type Constructor } from "#app/utils/common";
|
import { BooleanHolder, NumberHolder, isNullOrUndefined, toDmgValue, randSeedItem, randSeedInt, getEnumValues, toReadableString, type Constructor, randSeedFloat } from "#app/utils/common";
|
||||||
import { WeatherType } from "#enums/weather-type";
|
import { WeatherType } from "#enums/weather-type";
|
||||||
import type { ArenaTrapTag } from "../arena-tag";
|
import type { ArenaTrapTag } from "../arena-tag";
|
||||||
import { ArenaTagSide, WeakenMoveTypeTag } from "../arena-tag";
|
import { ArenaTagSide, WeakenMoveTypeTag } from "../arena-tag";
|
||||||
@ -81,7 +81,7 @@ import { TerrainType } from "../terrain";
|
|||||||
import { ModifierPoolType } from "#app/modifier/modifier-type";
|
import { ModifierPoolType } from "#app/modifier/modifier-type";
|
||||||
import { Command } from "../../ui/command-ui-handler";
|
import { Command } from "../../ui/command-ui-handler";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import type { Localizable } from "#app/interfaces/locales";
|
import type { Localizable } from "#app/@types/locales";
|
||||||
import { getBerryEffectFunc } from "../berry";
|
import { getBerryEffectFunc } from "../berry";
|
||||||
import { AbilityId } from "#enums/ability-id";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||||
@ -837,7 +837,7 @@ export default class Move implements Localizable {
|
|||||||
aura.applyPreAttack(source, null, simulated, target, this, [ power ]);
|
aura.applyPreAttack(source, null, simulated, target, this, [ power ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const alliedField: Pokemon[] = source instanceof PlayerPokemon ? globalScene.getPlayerField() : globalScene.getEnemyField();
|
const alliedField: Pokemon[] = source.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField();
|
||||||
alliedField.forEach(p => applyPreAttackAbAttrs(UserFieldMoveTypePowerBoostAbAttr, p, target, this, simulated, power));
|
alliedField.forEach(p => applyPreAttackAbAttrs(UserFieldMoveTypePowerBoostAbAttr, p, target, this, simulated, power));
|
||||||
|
|
||||||
power.value *= typeChangeMovePowerMultiplier.value;
|
power.value *= typeChangeMovePowerMultiplier.value;
|
||||||
@ -1048,7 +1048,7 @@ function ChargeMove<TBase extends SubMove>(Base: TBase) {
|
|||||||
* @param target the {@linkcode Pokemon} targeted by this move (optional)
|
* @param target the {@linkcode Pokemon} targeted by this move (optional)
|
||||||
*/
|
*/
|
||||||
showChargeText(user: Pokemon, target?: Pokemon): void {
|
showChargeText(user: Pokemon, target?: Pokemon): void {
|
||||||
globalScene.queueMessage(this._chargeText
|
globalScene.phaseManager.queueMessage(this._chargeText
|
||||||
.replace("{USER}", getPokemonNameWithAffix(user))
|
.replace("{USER}", getPokemonNameWithAffix(user))
|
||||||
.replace("{TARGET}", getPokemonNameWithAffix(target))
|
.replace("{TARGET}", getPokemonNameWithAffix(target))
|
||||||
);
|
);
|
||||||
@ -1310,7 +1310,7 @@ export class MessageHeaderAttr extends MoveHeaderAttr {
|
|||||||
: this.message(user, move);
|
: this.message(user, move);
|
||||||
|
|
||||||
if (message) {
|
if (message) {
|
||||||
globalScene.queueMessage(message);
|
globalScene.phaseManager.queueMessage(message);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1363,7 +1363,7 @@ export class PreMoveMessageAttr extends MoveAttr {
|
|||||||
? this.message as string
|
? this.message as string
|
||||||
: this.message(user, target, move);
|
: this.message(user, target, move);
|
||||||
if (message) {
|
if (message) {
|
||||||
globalScene.queueMessage(message, 500);
|
globalScene.phaseManager.queueMessage(message, 500);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1620,14 +1620,14 @@ export class SurviveDamageAttr extends ModifiedDamageAttr {
|
|||||||
|
|
||||||
export class SplashAttr extends MoveEffectAttr {
|
export class SplashAttr extends MoveEffectAttr {
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:splash"));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:splash"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CelebrateAttr extends MoveEffectAttr {
|
export class CelebrateAttr extends MoveEffectAttr {
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:celebrate", { playerName: loggedInUser?.username }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:celebrate", { playerName: loggedInUser?.username }));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1677,7 +1677,7 @@ export class RecoilAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
user.damageAndUpdate(recoilDamage, { result: HitResult.INDIRECT, ignoreSegments: true });
|
user.damageAndUpdate(recoilDamage, { result: HitResult.INDIRECT, ignoreSegments: true });
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:hitWithRecoil", { pokemonName: getPokemonNameWithAffix(user) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:hitWithRecoil", { pokemonName: getPokemonNameWithAffix(user) }));
|
||||||
user.turnData.damageTaken += recoilDamage;
|
user.turnData.damageTaken += recoilDamage;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1789,7 +1789,7 @@ export class HalfSacrificialAttr extends MoveEffectAttr {
|
|||||||
applyAbAttrs(BlockNonDirectDamageAbAttr, user, cancelled);
|
applyAbAttrs(BlockNonDirectDamageAbAttr, user, cancelled);
|
||||||
if (!cancelled.value) {
|
if (!cancelled.value) {
|
||||||
user.damageAndUpdate(toDmgValue(user.getMaxHp() / 2), { result: HitResult.INDIRECT, ignoreSegments: true });
|
user.damageAndUpdate(toDmgValue(user.getMaxHp() / 2), { result: HitResult.INDIRECT, ignoreSegments: true });
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:cutHpPowerUpMove", { pokemonName: getPokemonNameWithAffix(user) })); // Queue recoil message
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:cutHpPowerUpMove", { pokemonName: getPokemonNameWithAffix(user) })); // Queue recoil message
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1890,8 +1890,8 @@ export class HealAttr extends MoveEffectAttr {
|
|||||||
* This heals the target and shows the appropriate message.
|
* This heals the target and shows the appropriate message.
|
||||||
*/
|
*/
|
||||||
addHealPhase(target: Pokemon, healRatio: number) {
|
addHealPhase(target: Pokemon, healRatio: number) {
|
||||||
globalScene.unshiftPhase(new PokemonHealPhase(target.getBattlerIndex(),
|
globalScene.phaseManager.unshiftNew("PokemonHealPhase", target.getBattlerIndex(),
|
||||||
toDmgValue(target.getMaxHp() * healRatio), i18next.t("moveTriggers:healHp", { pokemonName: getPokemonNameWithAffix(target) }), true, !this.showAnim));
|
toDmgValue(target.getMaxHp() * healRatio), i18next.t("moveTriggers:healHp", { pokemonName: getPokemonNameWithAffix(target) }), true, !this.showAnim);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number {
|
getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number {
|
||||||
@ -1934,7 +1934,7 @@ export class PartyStatusCureAttr extends MoveEffectAttr {
|
|||||||
partyPokemon.forEach(p => this.cureStatus(p, user.id));
|
partyPokemon.forEach(p => this.cureStatus(p, user.id));
|
||||||
|
|
||||||
if (this.message) {
|
if (this.message) {
|
||||||
globalScene.queueMessage(this.message);
|
globalScene.phaseManager.queueMessage(this.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1954,8 +1954,8 @@ export class PartyStatusCureAttr extends MoveEffectAttr {
|
|||||||
pokemon.updateInfo();
|
pokemon.updateInfo();
|
||||||
} else {
|
} else {
|
||||||
// TODO: Ability displays should be handled by the ability
|
// TODO: Ability displays should be handled by the ability
|
||||||
globalScene.queueAbilityDisplay(pokemon, pokemon.getPassiveAbility()?.id === this.abilityCondition, true);
|
globalScene.phaseManager.queueAbilityDisplay(pokemon, pokemon.getPassiveAbility()?.id === this.abilityCondition, true);
|
||||||
globalScene.queueAbilityDisplay(pokemon, pokemon.getPassiveAbility()?.id === this.abilityCondition, false);
|
globalScene.phaseManager.queueAbilityDisplay(pokemon, pokemon.getPassiveAbility()?.id === this.abilityCondition, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2021,8 +2021,10 @@ export class SacrificialFullRestoreAttr extends SacrificialAttr {
|
|||||||
const party = user.isPlayer() ? globalScene.getPlayerParty() : globalScene.getEnemyParty();
|
const party = user.isPlayer() ? globalScene.getPlayerParty() : globalScene.getEnemyParty();
|
||||||
const maxPartyMemberHp = party.map(p => p.getMaxHp()).reduce((maxHp: number, hp: number) => Math.max(hp, maxHp), 0);
|
const maxPartyMemberHp = party.map(p => p.getMaxHp()).reduce((maxHp: number, hp: number) => Math.max(hp, maxHp), 0);
|
||||||
|
|
||||||
globalScene.pushPhase(
|
const pm = globalScene.phaseManager;
|
||||||
new PokemonHealPhase(
|
|
||||||
|
pm.pushPhase(
|
||||||
|
pm.create("PokemonHealPhase",
|
||||||
user.getBattlerIndex(),
|
user.getBattlerIndex(),
|
||||||
maxPartyMemberHp,
|
maxPartyMemberHp,
|
||||||
i18next.t(this.moveMessage, { pokemonName: getPokemonNameWithAffix(user) }),
|
i18next.t(this.moveMessage, { pokemonName: getPokemonNameWithAffix(user) }),
|
||||||
@ -2233,7 +2235,7 @@ export class HitHealAttr extends MoveEffectAttr {
|
|||||||
message = "";
|
message = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
globalScene.unshiftPhase(new PokemonHealPhase(user.getBattlerIndex(), healAmount, message, false, true));
|
globalScene.phaseManager.unshiftNew("PokemonHealPhase", user.getBattlerIndex(), healAmount, message, false, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2547,8 +2549,8 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
const rand = Phaser.Math.RND.realInRange(0, 1);
|
const rand = randSeedFloat();
|
||||||
if (rand >= this.chance) {
|
if (rand > this.chance) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2565,7 +2567,7 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:stoleItem", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: stolenItem.type.name }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:stoleItem", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: stolenItem.type.name }));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2643,9 +2645,9 @@ export class RemoveHeldItemAttr extends MoveEffectAttr {
|
|||||||
globalScene.updateModifiers(target.isPlayer());
|
globalScene.updateModifiers(target.isPlayer());
|
||||||
|
|
||||||
if (this.berriesOnly) {
|
if (this.berriesOnly) {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:incineratedItem", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: removedItem.type.name }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:incineratedItem", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: removedItem.type.name }));
|
||||||
} else {
|
} else {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:knockedOffItem", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: removedItem.type.name }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:knockedOffItem", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: removedItem.type.name }));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2777,7 +2779,7 @@ export class StealEatBerryAttr extends EatBerryAttr {
|
|||||||
this.chosenBerry = heldBerries[user.randBattleSeedInt(heldBerries.length)];
|
this.chosenBerry = heldBerries[user.randBattleSeedInt(heldBerries.length)];
|
||||||
applyPostItemLostAbAttrs(PostItemLostAbAttr, target, false);
|
applyPostItemLostAbAttrs(PostItemLostAbAttr, target, false);
|
||||||
const message = i18next.t("battle:stealEatBerry", { pokemonName: user.name, targetName: target.name, berryName: this.chosenBerry.type.name });
|
const message = i18next.t("battle:stealEatBerry", { pokemonName: user.name, targetName: target.name, berryName: this.chosenBerry.type.name });
|
||||||
globalScene.queueMessage(message);
|
globalScene.phaseManager.queueMessage(message);
|
||||||
this.reduceBerryModifier(target);
|
this.reduceBerryModifier(target);
|
||||||
this.eatBerry(user, target);
|
this.eatBerry(user, target);
|
||||||
|
|
||||||
@ -2822,7 +2824,7 @@ export class HealStatusEffectAttr extends MoveEffectAttr {
|
|||||||
|
|
||||||
const pokemon = this.selfTarget ? user : target;
|
const pokemon = this.selfTarget ? user : target;
|
||||||
if (pokemon.status && this.effects.includes(pokemon.status.effect)) {
|
if (pokemon.status && this.effects.includes(pokemon.status.effect)) {
|
||||||
globalScene.queueMessage(getStatusEffectHealText(pokemon.status.effect, getPokemonNameWithAffix(pokemon)));
|
globalScene.phaseManager.queueMessage(getStatusEffectHealText(pokemon.status.effect, getPokemonNameWithAffix(pokemon)));
|
||||||
pokemon.resetStatus();
|
pokemon.resetStatus();
|
||||||
pokemon.updateInfo();
|
pokemon.updateInfo();
|
||||||
|
|
||||||
@ -3067,13 +3069,13 @@ export class DelayedAttackAttr extends OverrideMoveEffectAttr {
|
|||||||
|
|
||||||
if (!virtual) {
|
if (!virtual) {
|
||||||
overridden.value = true;
|
overridden.value = true;
|
||||||
globalScene.unshiftPhase(new MoveAnimPhase(new MoveChargeAnim(this.chargeAnim, move.id, user)));
|
globalScene.phaseManager.unshiftNew("MoveAnimPhase", new MoveChargeAnim(this.chargeAnim, move.id, user));
|
||||||
globalScene.queueMessage(this.chargeText.replace("{TARGET}", getPokemonNameWithAffix(target)).replace("{USER}", getPokemonNameWithAffix(user)));
|
globalScene.phaseManager.queueMessage(this.chargeText.replace("{TARGET}", getPokemonNameWithAffix(target)).replace("{USER}", getPokemonNameWithAffix(user)));
|
||||||
user.pushMoveHistory({ move: move.id, targets: [ target.getBattlerIndex() ], result: MoveResult.OTHER });
|
user.pushMoveHistory({ move: move.id, targets: [ target.getBattlerIndex() ], result: MoveResult.OTHER });
|
||||||
const side = target.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
|
const side = target.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
|
||||||
globalScene.arena.addTag(this.tagType, 3, move.id, user.id, side, false, target.getBattlerIndex());
|
globalScene.arena.addTag(this.tagType, 3, move.id, user.id, side, false, target.getBattlerIndex());
|
||||||
} else {
|
} else {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:tookMoveAttack", { pokemonName: getPokemonNameWithAffix(globalScene.getPokemonById(target.id) ?? undefined), moveName: move.name }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:tookMoveAttack", { pokemonName: getPokemonNameWithAffix(globalScene.getPokemonById(target.id) ?? undefined), moveName: move.name }));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -3103,29 +3105,29 @@ export class AwaitCombinedPledgeAttr extends OverrideMoveEffectAttr {
|
|||||||
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
if (user.turnData.combiningPledge) {
|
if (user.turnData.combiningPledge) {
|
||||||
// "The two moves have become one!\nIt's a combined move!"
|
// "The two moves have become one!\nIt's a combined move!"
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:combiningPledge"));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:combiningPledge"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const overridden = args[0] as BooleanHolder;
|
const overridden = args[0] as BooleanHolder;
|
||||||
|
|
||||||
const allyMovePhase = globalScene.findPhase<MovePhase>((phase) => phase instanceof MovePhase && phase.pokemon.isPlayer() === user.isPlayer());
|
const allyMovePhase = globalScene.phaseManager.findPhase<MovePhase>((phase) => phase.is("MovePhase") && phase.pokemon.isPlayer() === user.isPlayer());
|
||||||
if (allyMovePhase) {
|
if (allyMovePhase) {
|
||||||
const allyMove = allyMovePhase.move.getMove();
|
const allyMove = allyMovePhase.move.getMove();
|
||||||
if (allyMove !== move && allyMove.hasAttr(AwaitCombinedPledgeAttr)) {
|
if (allyMove !== move && allyMove.hasAttr(AwaitCombinedPledgeAttr)) {
|
||||||
[ user, allyMovePhase.pokemon ].forEach((p) => p.turnData.combiningPledge = move.id);
|
[ user, allyMovePhase.pokemon ].forEach((p) => p.turnData.combiningPledge = move.id);
|
||||||
|
|
||||||
// "{userPokemonName} is waiting for {allyPokemonName}'s move..."
|
// "{userPokemonName} is waiting for {allyPokemonName}'s move..."
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:awaitingPledge", {
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:awaitingPledge", {
|
||||||
userPokemonName: getPokemonNameWithAffix(user),
|
userPokemonName: getPokemonNameWithAffix(user),
|
||||||
allyPokemonName: getPokemonNameWithAffix(allyMovePhase.pokemon)
|
allyPokemonName: getPokemonNameWithAffix(allyMovePhase.pokemon)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Move the ally's MovePhase (if needed) so that the ally moves next
|
// Move the ally's MovePhase (if needed) so that the ally moves next
|
||||||
const allyMovePhaseIndex = globalScene.phaseQueue.indexOf(allyMovePhase);
|
const allyMovePhaseIndex = globalScene.phaseManager.phaseQueue.indexOf(allyMovePhase);
|
||||||
const firstMovePhaseIndex = globalScene.phaseQueue.findIndex((phase) => phase instanceof MovePhase);
|
const firstMovePhaseIndex = globalScene.phaseManager.phaseQueue.findIndex((phase) => phase.is("MovePhase"));
|
||||||
if (allyMovePhaseIndex !== firstMovePhaseIndex) {
|
if (allyMovePhaseIndex !== firstMovePhaseIndex) {
|
||||||
globalScene.prependToPhase(globalScene.phaseQueue.splice(allyMovePhaseIndex, 1)[0], MovePhase);
|
globalScene.phaseManager.prependToPhase(globalScene.phaseManager.phaseQueue.splice(allyMovePhaseIndex, 1)[0], "MovePhase");
|
||||||
}
|
}
|
||||||
|
|
||||||
overridden.value = true;
|
overridden.value = true;
|
||||||
@ -3207,7 +3209,7 @@ export class StatStageChangeAttr extends MoveEffectAttr {
|
|||||||
const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true);
|
const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true);
|
||||||
if (moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance) {
|
if (moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance) {
|
||||||
const stages = this.getLevels(user);
|
const stages = this.getLevels(user);
|
||||||
globalScene.unshiftPhase(new StatStageChangePhase((this.selfTarget ? user : target).getBattlerIndex(), this.selfTarget, this.stats, stages, this.showMessage));
|
globalScene.phaseManager.unshiftNew("StatStageChangePhase", (this.selfTarget ? user : target).getBattlerIndex(), this.selfTarget, this.stats, stages, this.showMessage);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3432,7 +3434,7 @@ export class AcupressureStatStageChangeAttr extends MoveEffectAttr {
|
|||||||
const randStats = BATTLE_STATS.filter((s) => target.getStatStage(s) < 6);
|
const randStats = BATTLE_STATS.filter((s) => target.getStatStage(s) < 6);
|
||||||
if (randStats.length > 0) {
|
if (randStats.length > 0) {
|
||||||
const boostStat = [ randStats[user.randBattleSeedInt(randStats.length)] ];
|
const boostStat = [ randStats[user.randBattleSeedInt(randStats.length)] ];
|
||||||
globalScene.unshiftPhase(new StatStageChangePhase(target.getBattlerIndex(), this.selfTarget, boostStat, 2));
|
globalScene.phaseManager.unshiftNew("StatStageChangePhase", target.getBattlerIndex(), this.selfTarget, boostStat, 2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -3510,7 +3512,7 @@ export class OrderUpStatBoostAttr extends MoveEffectAttr {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.unshiftPhase(new StatStageChangePhase(user.getBattlerIndex(), this.selfTarget, [ increasedStat ], 1));
|
globalScene.phaseManager.unshiftNew("StatStageChangePhase", user.getBattlerIndex(), this.selfTarget, [ increasedStat ], 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3533,7 +3535,7 @@ export class CopyStatsAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
target.updateInfo();
|
target.updateInfo();
|
||||||
user.updateInfo();
|
user.updateInfo();
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:copiedStatChanges", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:copiedStatChanges", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3552,7 +3554,7 @@ export class InvertStatsAttr extends MoveEffectAttr {
|
|||||||
target.updateInfo();
|
target.updateInfo();
|
||||||
user.updateInfo();
|
user.updateInfo();
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:invertStats", { pokemonName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:invertStats", { pokemonName: getPokemonNameWithAffix(target) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3570,10 +3572,10 @@ export class ResetStatsAttr extends MoveEffectAttr {
|
|||||||
// Target all pokemon on the field when Freezy Frost or Haze are used
|
// Target all pokemon on the field when Freezy Frost or Haze are used
|
||||||
const activePokemon = globalScene.getField(true);
|
const activePokemon = globalScene.getField(true);
|
||||||
activePokemon.forEach((p) => this.resetStats(p));
|
activePokemon.forEach((p) => this.resetStats(p));
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:statEliminated"));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:statEliminated"));
|
||||||
} else { // Affects only the single target when Clear Smog is used
|
} else { // Affects only the single target when Clear Smog is used
|
||||||
this.resetStats(target);
|
this.resetStats(target);
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:resetStats", { pokemonName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:resetStats", { pokemonName: getPokemonNameWithAffix(target) }));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3623,9 +3625,9 @@ export class SwapStatStagesAttr extends MoveEffectAttr {
|
|||||||
user.updateInfo();
|
user.updateInfo();
|
||||||
|
|
||||||
if (this.stats.length === 7) {
|
if (this.stats.length === 7) {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:switchedStatChanges", { pokemonName: getPokemonNameWithAffix(user) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:switchedStatChanges", { pokemonName: getPokemonNameWithAffix(user) }));
|
||||||
} else if (this.stats.length === 2) {
|
} else if (this.stats.length === 2) {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:switchedTwoStatChanges", {
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:switchedTwoStatChanges", {
|
||||||
pokemonName: getPokemonNameWithAffix(user),
|
pokemonName: getPokemonNameWithAffix(user),
|
||||||
firstStat: i18next.t(getStatKey(this.stats[0])),
|
firstStat: i18next.t(getStatKey(this.stats[0])),
|
||||||
secondStat: i18next.t(getStatKey(this.stats[1]))
|
secondStat: i18next.t(getStatKey(this.stats[1]))
|
||||||
@ -4125,7 +4127,7 @@ export class FriendshipPowerAttr extends VariablePowerAttr {
|
|||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
const power = args[0] as NumberHolder;
|
const power = args[0] as NumberHolder;
|
||||||
|
|
||||||
const friendshipPower = Math.floor(Math.min(user instanceof PlayerPokemon ? user.friendship : user.species.baseFriendship, 255) / 2.5);
|
const friendshipPower = Math.floor(Math.min(user.isPlayer() ? user.friendship : user.species.baseFriendship, 255) / 2.5);
|
||||||
power.value = Math.max(!this.invert ? friendshipPower : 102 - friendshipPower, 1);
|
power.value = Math.max(!this.invert ? friendshipPower : 102 - friendshipPower, 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -4227,8 +4229,8 @@ export class PresentPowerAttr extends VariablePowerAttr {
|
|||||||
// If this move is multi-hit, disable all other hits
|
// If this move is multi-hit, disable all other hits
|
||||||
user.turnData.hitCount = 1;
|
user.turnData.hitCount = 1;
|
||||||
user.turnData.hitsLeft = 1;
|
user.turnData.hitsLeft = 1;
|
||||||
globalScene.unshiftPhase(new PokemonHealPhase(target.getBattlerIndex(),
|
globalScene.phaseManager.unshiftNew("PokemonHealPhase", target.getBattlerIndex(),
|
||||||
toDmgValue(target.getMaxHp() / 4), i18next.t("moveTriggers:regainedHealth", { pokemonName: getPokemonNameWithAffix(target) }), true));
|
toDmgValue(target.getMaxHp() / 4), i18next.t("moveTriggers:regainedHealth", { pokemonName: getPokemonNameWithAffix(target) }), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -4476,8 +4478,8 @@ export class CueNextRoundAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override apply(user: Pokemon, target: Pokemon, move: Move, args?: any[]): boolean {
|
override apply(user: Pokemon, target: Pokemon, move: Move, args?: any[]): boolean {
|
||||||
const nextRoundPhase = globalScene.findPhase<MovePhase>(phase =>
|
const nextRoundPhase = globalScene.phaseManager.findPhase<MovePhase>(phase =>
|
||||||
phase instanceof MovePhase && phase.move.moveId === MoveId.ROUND
|
phase.is("MovePhase") && phase.move.moveId === MoveId.ROUND
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!nextRoundPhase) {
|
if (!nextRoundPhase) {
|
||||||
@ -4485,10 +4487,10 @@ export class CueNextRoundAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the phase queue so that the next Pokemon using Round moves next
|
// Update the phase queue so that the next Pokemon using Round moves next
|
||||||
const nextRoundIndex = globalScene.phaseQueue.indexOf(nextRoundPhase);
|
const nextRoundIndex = globalScene.phaseManager.phaseQueue.indexOf(nextRoundPhase);
|
||||||
const nextMoveIndex = globalScene.phaseQueue.findIndex(phase => phase instanceof MovePhase);
|
const nextMoveIndex = globalScene.phaseManager.phaseQueue.findIndex(phase => phase.is("MovePhase"));
|
||||||
if (nextRoundIndex !== nextMoveIndex) {
|
if (nextRoundIndex !== nextMoveIndex) {
|
||||||
globalScene.prependToPhase(globalScene.phaseQueue.splice(nextRoundIndex, 1)[0], MovePhase);
|
globalScene.phaseManager.prependToPhase(globalScene.phaseManager.phaseQueue.splice(nextRoundIndex, 1)[0], "MovePhase");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark the corresponding Pokemon as having "joined the Round" (for doubling power later)
|
// Mark the corresponding Pokemon as having "joined the Round" (for doubling power later)
|
||||||
@ -4546,14 +4548,14 @@ export class SpectralThiefAttr extends StatChangeBeforeDmgCalcAttr {
|
|||||||
*/
|
*/
|
||||||
const availableToSteal = Math.min(statStageValueTarget, 6 - statStageValueUser);
|
const availableToSteal = Math.min(statStageValueTarget, 6 - statStageValueUser);
|
||||||
|
|
||||||
globalScene.unshiftPhase(new StatStageChangePhase(user.getBattlerIndex(), this.selfTarget, [ s ], availableToSteal));
|
globalScene.phaseManager.unshiftNew("StatStageChangePhase", user.getBattlerIndex(), this.selfTarget, [ s ], availableToSteal);
|
||||||
target.setStatStage(s, statStageValueTarget - availableToSteal);
|
target.setStatStage(s, statStageValueTarget - availableToSteal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target.updateInfo();
|
target.updateInfo();
|
||||||
user.updateInfo();
|
user.updateInfo();
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:stealPositiveStats", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:stealPositiveStats", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -5368,7 +5370,7 @@ const crashDamageFunc = (user: Pokemon, move: Move) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
user.damageAndUpdate(toDmgValue(user.getMaxHp() / 2), { result: HitResult.INDIRECT });
|
user.damageAndUpdate(toDmgValue(user.getMaxHp() / 2), { result: HitResult.INDIRECT });
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:keptGoingAndCrashed", { pokemonName: getPokemonNameWithAffix(user) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:keptGoingAndCrashed", { pokemonName: getPokemonNameWithAffix(user) }));
|
||||||
user.turnData.damageTaken += toDmgValue(user.getMaxHp() / 2);
|
user.turnData.damageTaken += toDmgValue(user.getMaxHp() / 2);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -5472,13 +5474,6 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
|
|||||||
this.failOnOverlap = !!failOnOverlap;
|
this.failOnOverlap = !!failOnOverlap;
|
||||||
}
|
}
|
||||||
|
|
||||||
canApply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
|
||||||
if (!super.canApply(user, target, move, args)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
if (!super.apply(user, target, move, args)) {
|
if (!super.apply(user, target, move, args)) {
|
||||||
return false;
|
return false;
|
||||||
@ -5588,7 +5583,7 @@ export class FallDownAttr extends AddBattlerTagAttr {
|
|||||||
*/
|
*/
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
if (!target.isGrounded()) {
|
if (!target.isGrounded()) {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:fallDown", { targetPokemonName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:fallDown", { targetPokemonName: getPokemonNameWithAffix(target) }));
|
||||||
}
|
}
|
||||||
return super.apply(user, target, move, args);
|
return super.apply(user, target, move, args);
|
||||||
}
|
}
|
||||||
@ -5672,12 +5667,12 @@ export class CurseAttr extends MoveEffectAttr {
|
|||||||
apply(user: Pokemon, target: Pokemon, move:Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move:Move, args: any[]): boolean {
|
||||||
if (user.getTypes(true).includes(PokemonType.GHOST)) {
|
if (user.getTypes(true).includes(PokemonType.GHOST)) {
|
||||||
if (target.getTag(BattlerTagType.CURSED)) {
|
if (target.getTag(BattlerTagType.CURSED)) {
|
||||||
globalScene.queueMessage(i18next.t("battle:attackFailed"));
|
globalScene.phaseManager.queueMessage(i18next.t("battle:attackFailed"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const curseRecoilDamage = Math.max(1, Math.floor(user.getMaxHp() / 2));
|
const curseRecoilDamage = Math.max(1, Math.floor(user.getMaxHp() / 2));
|
||||||
user.damageAndUpdate(curseRecoilDamage, { result: HitResult.INDIRECT, ignoreSegments: true });
|
user.damageAndUpdate(curseRecoilDamage, { result: HitResult.INDIRECT, ignoreSegments: true });
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("battlerTags:cursedOnAdd", {
|
i18next.t("battlerTags:cursedOnAdd", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(user),
|
pokemonNameWithAffix: getPokemonNameWithAffix(user),
|
||||||
pokemonName: getPokemonNameWithAffix(target)
|
pokemonName: getPokemonNameWithAffix(target)
|
||||||
@ -5687,8 +5682,8 @@ export class CurseAttr extends MoveEffectAttr {
|
|||||||
target.addTag(BattlerTagType.CURSED, 0, move.id, user.id);
|
target.addTag(BattlerTagType.CURSED, 0, move.id, user.id);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
globalScene.unshiftPhase(new StatStageChangePhase(user.getBattlerIndex(), true, [ Stat.ATK, Stat.DEF ], 1));
|
globalScene.phaseManager.unshiftNew("StatStageChangePhase", user.getBattlerIndex(), true, [ Stat.ATK, Stat.DEF ], 1);
|
||||||
globalScene.unshiftPhase(new StatStageChangePhase(user.getBattlerIndex(), true, [ Stat.SPD ], -1));
|
globalScene.phaseManager.unshiftNew("StatStageChangePhase", user.getBattlerIndex(), true, [ Stat.SPD ], -1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5752,7 +5747,7 @@ export class ConfuseAttr extends AddBattlerTagAttr {
|
|||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
if (!this.selfTarget && target.isSafeguarded(user)) {
|
if (!this.selfTarget && target.isSafeguarded(user)) {
|
||||||
if (move.category === MoveCategory.STATUS) {
|
if (move.category === MoveCategory.STATUS) {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:safeguard", { targetName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:safeguard", { targetName: getPokemonNameWithAffix(target) }));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -5809,7 +5804,7 @@ export class IgnoreAccuracyAttr extends AddBattlerTagAttr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:tookAimAtTarget", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:tookAimAtTarget", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -5825,7 +5820,7 @@ export class FaintCountdownAttr extends AddBattlerTagAttr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:faintCountdown", { pokemonName: getPokemonNameWithAffix(target), turnCount: this.turnCountMin - 1 }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:faintCountdown", { pokemonName: getPokemonNameWithAffix(target), turnCount: this.turnCountMin - 1 }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -6109,7 +6104,7 @@ export class SwapArenaTagsAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:swapArenaTags", { pokemonName: getPokemonNameWithAffix(user) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:swapArenaTags", { pokemonName: getPokemonNameWithAffix(user) }));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6156,14 +6151,14 @@ export class RevivalBlessingAttr extends MoveEffectAttr {
|
|||||||
* @param target {@linkcode Pokemon} target of this move
|
* @param target {@linkcode Pokemon} target of this move
|
||||||
* @param move {@linkcode Move} being used
|
* @param move {@linkcode Move} being used
|
||||||
* @param args N/A
|
* @param args N/A
|
||||||
* @returns Promise, true if function succeeds.
|
* @returns `true` if function succeeds.
|
||||||
*/
|
*/
|
||||||
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
// If user is player, checks if the user has fainted pokemon
|
// If user is player, checks if the user has fainted pokemon
|
||||||
if (user instanceof PlayerPokemon) {
|
if (user.isPlayer()) {
|
||||||
globalScene.unshiftPhase(new RevivalBlessingPhase(user));
|
globalScene.phaseManager.unshiftNew("RevivalBlessingPhase", user);
|
||||||
return true;
|
return true;
|
||||||
} else if (user instanceof EnemyPokemon && user.hasTrainer() && globalScene.getEnemyParty().findIndex((p) => p.isFainted() && !p.isBoss()) > -1) {
|
} else if (user.isEnemy() && user.hasTrainer() && globalScene.getEnemyParty().findIndex((p) => p.isFainted() && !p.isBoss()) > -1) {
|
||||||
// If used by an enemy trainer with at least one fainted non-boss Pokemon, this
|
// If used by an enemy trainer with at least one fainted non-boss Pokemon, this
|
||||||
// revives one of said Pokemon selected at random.
|
// revives one of said Pokemon selected at random.
|
||||||
const faintedPokemon = globalScene.getEnemyParty().filter((p) => p.isFainted() && !p.isBoss());
|
const faintedPokemon = globalScene.getEnemyParty().filter((p) => p.isFainted() && !p.isBoss());
|
||||||
@ -6171,20 +6166,20 @@ export class RevivalBlessingAttr extends MoveEffectAttr {
|
|||||||
const slotIndex = globalScene.getEnemyParty().findIndex((p) => pokemon.id === p.id);
|
const slotIndex = globalScene.getEnemyParty().findIndex((p) => pokemon.id === p.id);
|
||||||
pokemon.resetStatus(true, false, false, true);
|
pokemon.resetStatus(true, false, false, true);
|
||||||
pokemon.heal(Math.min(toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp()));
|
pokemon.heal(Math.min(toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp()));
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:revivalBlessing", { pokemonName: getPokemonNameWithAffix(pokemon) }), 0, true);
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:revivalBlessing", { pokemonName: getPokemonNameWithAffix(pokemon) }), 0, true);
|
||||||
const allyPokemon = user.getAlly();
|
const allyPokemon = user.getAlly();
|
||||||
if (globalScene.currentBattle.double && globalScene.getEnemyParty().length > 1 && !isNullOrUndefined(allyPokemon)) {
|
if (globalScene.currentBattle.double && globalScene.getEnemyParty().length > 1 && !isNullOrUndefined(allyPokemon)) {
|
||||||
// Handle cases where revived pokemon needs to get switched in on same turn
|
// Handle cases where revived pokemon needs to get switched in on same turn
|
||||||
if (allyPokemon.isFainted() || allyPokemon === pokemon) {
|
if (allyPokemon.isFainted() || allyPokemon === pokemon) {
|
||||||
// Enemy switch phase should be removed and replaced with the revived pkmn switching in
|
// Enemy switch phase should be removed and replaced with the revived pkmn switching in
|
||||||
globalScene.tryRemovePhase((phase: SwitchSummonPhase) => phase instanceof SwitchSummonPhase && phase.getPokemon() === pokemon);
|
globalScene.phaseManager.tryRemovePhase((phase: SwitchSummonPhase) => phase.is("SwitchSummonPhase") && phase.getPokemon() === pokemon);
|
||||||
// If the pokemon being revived was alive earlier in the turn, cancel its move
|
// If the pokemon being revived was alive earlier in the turn, cancel its move
|
||||||
// (revived pokemon can't move in the turn they're brought back)
|
// (revived pokemon can't move in the turn they're brought back)
|
||||||
globalScene.findPhase((phase: MovePhase) => phase.pokemon === pokemon)?.cancel();
|
globalScene.phaseManager.findPhase((phase: MovePhase) => phase.pokemon === pokemon)?.cancel();
|
||||||
if (user.fieldPosition === FieldPosition.CENTER) {
|
if (user.fieldPosition === FieldPosition.CENTER) {
|
||||||
user.setFieldPosition(FieldPosition.LEFT);
|
user.setFieldPosition(FieldPosition.LEFT);
|
||||||
}
|
}
|
||||||
globalScene.unshiftPhase(new SwitchSummonPhase(SwitchType.SWITCH, allyPokemon.getFieldIndex(), slotIndex, false, false));
|
globalScene.phaseManager.unshiftNew("SwitchSummonPhase", SwitchType.SWITCH, allyPokemon.getFieldIndex(), slotIndex, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -6194,10 +6189,8 @@ export class RevivalBlessingAttr extends MoveEffectAttr {
|
|||||||
|
|
||||||
getCondition(): MoveConditionFunc {
|
getCondition(): MoveConditionFunc {
|
||||||
return (user, target, move) =>
|
return (user, target, move) =>
|
||||||
(user instanceof PlayerPokemon && globalScene.getPlayerParty().some((p) => p.isFainted())) ||
|
user.hasTrainer() &&
|
||||||
(user instanceof EnemyPokemon &&
|
(user.isPlayer() ? globalScene.getPlayerParty() : globalScene.getEnemyParty()).some((p: Pokemon) => p.isFainted() && !p.isBoss());
|
||||||
user.hasTrainer() &&
|
|
||||||
globalScene.getEnemyParty().some((p) => p.isFainted() && !p.isBoss()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override getUserBenefitScore(user: Pokemon, _target: Pokemon, _move: Move): number {
|
override getUserBenefitScore(user: Pokemon, _target: Pokemon, _move: Move): number {
|
||||||
@ -6235,7 +6228,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
|||||||
// (e.g. when it uses Flip Turn), make it spit out the Tatsugiri before switching out.
|
// (e.g. when it uses Flip Turn), make it spit out the Tatsugiri before switching out.
|
||||||
switchOutTarget.lapseTag(BattlerTagType.COMMANDED);
|
switchOutTarget.lapseTag(BattlerTagType.COMMANDED);
|
||||||
|
|
||||||
if (switchOutTarget instanceof PlayerPokemon) {
|
if (switchOutTarget.isPlayer()) {
|
||||||
/**
|
/**
|
||||||
* Check if Wimp Out/Emergency Exit activates due to being hit by U-turn or Volt Switch
|
* Check if Wimp Out/Emergency Exit activates due to being hit by U-turn or Volt Switch
|
||||||
* If it did, the user of U-turn or Volt Switch will not be switched out.
|
* If it did, the user of U-turn or Volt Switch will not be switched out.
|
||||||
@ -6264,26 +6257,23 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
|||||||
if (this.switchType === SwitchType.FORCE_SWITCH) {
|
if (this.switchType === SwitchType.FORCE_SWITCH) {
|
||||||
switchOutTarget.leaveField(true);
|
switchOutTarget.leaveField(true);
|
||||||
const slotIndex = eligibleNewIndices[user.randBattleSeedInt(eligibleNewIndices.length)];
|
const slotIndex = eligibleNewIndices[user.randBattleSeedInt(eligibleNewIndices.length)];
|
||||||
globalScene.prependToPhase(
|
globalScene.phaseManager.prependNewToPhase(
|
||||||
new SwitchSummonPhase(
|
"MoveEndPhase",
|
||||||
this.switchType,
|
"SwitchSummonPhase",
|
||||||
switchOutTarget.getFieldIndex(),
|
this.switchType,
|
||||||
slotIndex,
|
switchOutTarget.getFieldIndex(),
|
||||||
false,
|
slotIndex,
|
||||||
true
|
false,
|
||||||
),
|
true
|
||||||
MoveEndPhase
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH);
|
switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH);
|
||||||
globalScene.prependToPhase(
|
globalScene.phaseManager.prependNewToPhase("MoveEndPhase",
|
||||||
new SwitchPhase(
|
"SwitchPhase",
|
||||||
this.switchType,
|
this.switchType,
|
||||||
switchOutTarget.getFieldIndex(),
|
switchOutTarget.getFieldIndex(),
|
||||||
true,
|
true,
|
||||||
true
|
true
|
||||||
),
|
|
||||||
MoveEndPhase
|
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -6307,27 +6297,23 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
|||||||
if (this.switchType === SwitchType.FORCE_SWITCH) {
|
if (this.switchType === SwitchType.FORCE_SWITCH) {
|
||||||
switchOutTarget.leaveField(true);
|
switchOutTarget.leaveField(true);
|
||||||
const slotIndex = eligibleNewIndices[user.randBattleSeedInt(eligibleNewIndices.length)];
|
const slotIndex = eligibleNewIndices[user.randBattleSeedInt(eligibleNewIndices.length)];
|
||||||
globalScene.prependToPhase(
|
globalScene.phaseManager.prependNewToPhase("MoveEndPhase",
|
||||||
new SwitchSummonPhase(
|
"SwitchSummonPhase",
|
||||||
this.switchType,
|
this.switchType,
|
||||||
switchOutTarget.getFieldIndex(),
|
switchOutTarget.getFieldIndex(),
|
||||||
slotIndex,
|
slotIndex,
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
),
|
|
||||||
MoveEndPhase
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH);
|
switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH);
|
||||||
globalScene.prependToPhase(
|
globalScene.phaseManager.prependNewToPhase("MoveEndPhase",
|
||||||
new SwitchSummonPhase(
|
"SwitchSummonPhase",
|
||||||
this.switchType,
|
this.switchType,
|
||||||
switchOutTarget.getFieldIndex(),
|
switchOutTarget.getFieldIndex(),
|
||||||
(globalScene.currentBattle.trainer ? globalScene.currentBattle.trainer.getNextSummonIndex((switchOutTarget as EnemyPokemon).trainerSlot) : 0),
|
(globalScene.currentBattle.trainer ? globalScene.currentBattle.trainer.getNextSummonIndex((switchOutTarget as EnemyPokemon).trainerSlot) : 0),
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
),
|
|
||||||
MoveEndPhase
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6348,7 +6334,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
|||||||
|
|
||||||
if (switchOutTarget.hp > 0) {
|
if (switchOutTarget.hp > 0) {
|
||||||
switchOutTarget.leaveField(false);
|
switchOutTarget.leaveField(false);
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:fled", { pokemonName: getPokemonNameWithAffix(switchOutTarget) }), null, true, 500);
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:fled", { pokemonName: getPokemonNameWithAffix(switchOutTarget) }), null, true, 500);
|
||||||
|
|
||||||
// in double battles redirect potential moves off fled pokemon
|
// in double battles redirect potential moves off fled pokemon
|
||||||
if (globalScene.currentBattle.double && !isNullOrUndefined(allyPokemon)) {
|
if (globalScene.currentBattle.double && !isNullOrUndefined(allyPokemon)) {
|
||||||
@ -6360,13 +6346,13 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
|||||||
globalScene.clearEnemyHeldItemModifiers(switchOutTarget);
|
globalScene.clearEnemyHeldItemModifiers(switchOutTarget);
|
||||||
|
|
||||||
if (!allyPokemon?.isActive(true) && switchOutTarget.hp) {
|
if (!allyPokemon?.isActive(true) && switchOutTarget.hp) {
|
||||||
globalScene.pushPhase(new BattleEndPhase(false));
|
globalScene.phaseManager.pushNew("BattleEndPhase", false);
|
||||||
|
|
||||||
if (globalScene.gameMode.hasRandomBiomes || globalScene.isNewBiome()) {
|
if (globalScene.gameMode.hasRandomBiomes || globalScene.isNewBiome()) {
|
||||||
globalScene.pushPhase(new SelectBiomePhase());
|
globalScene.phaseManager.pushNew("SelectBiomePhase");
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.pushPhase(new NewBattlePhase());
|
globalScene.phaseManager.pushNew("NewBattlePhase");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6389,7 +6375,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
|||||||
getSwitchOutCondition(): MoveConditionFunc {
|
getSwitchOutCondition(): MoveConditionFunc {
|
||||||
return (user, target, move) => {
|
return (user, target, move) => {
|
||||||
const switchOutTarget = (this.selfSwitch ? user : target);
|
const switchOutTarget = (this.selfSwitch ? user : target);
|
||||||
const player = switchOutTarget instanceof PlayerPokemon;
|
const player = switchOutTarget.isPlayer();
|
||||||
const forceSwitchAttr = move.getAttrs(ForceSwitchOutAttr).find(attr => attr.switchType === SwitchType.FORCE_SWITCH);
|
const forceSwitchAttr = move.getAttrs(ForceSwitchOutAttr).find(attr => attr.switchType === SwitchType.FORCE_SWITCH);
|
||||||
|
|
||||||
if (!this.selfSwitch) {
|
if (!this.selfSwitch) {
|
||||||
@ -6534,7 +6520,7 @@ export class CopyTypeAttr extends MoveEffectAttr {
|
|||||||
user.summonData.types = targetTypes;
|
user.summonData.types = targetTypes;
|
||||||
user.updateInfo();
|
user.updateInfo();
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:copyType", { pokemonName: getPokemonNameWithAffix(user), targetPokemonName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:copyType", { pokemonName: getPokemonNameWithAffix(user), targetPokemonName: getPokemonNameWithAffix(target) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -6565,7 +6551,7 @@ export class CopyBiomeTypeAttr extends MoveEffectAttr {
|
|||||||
user.summonData.types = [ typeChange ];
|
user.summonData.types = [ typeChange ];
|
||||||
user.updateInfo();
|
user.updateInfo();
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), typeName: i18next.t(`pokemonInfo:Type.${PokemonType[typeChange]}`) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), typeName: i18next.t(`pokemonInfo:Type.${PokemonType[typeChange]}`) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -6670,7 +6656,7 @@ export class ChangeTypeAttr extends MoveEffectAttr {
|
|||||||
target.summonData.types = [ this.type ];
|
target.summonData.types = [ this.type ];
|
||||||
target.updateInfo();
|
target.updateInfo();
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(target), typeName: i18next.t(`pokemonInfo:Type.${PokemonType[this.type]}`) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(target), typeName: i18next.t(`pokemonInfo:Type.${PokemonType[this.type]}`) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -6693,7 +6679,7 @@ export class AddTypeAttr extends MoveEffectAttr {
|
|||||||
target.summonData.addedType = this.type;
|
target.summonData.addedType = this.type;
|
||||||
target.updateInfo();
|
target.updateInfo();
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:addType", { typeName: i18next.t(`pokemonInfo:Type.${PokemonType[this.type]}`), pokemonName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:addType", { typeName: i18next.t(`pokemonInfo:Type.${PokemonType[this.type]}`), pokemonName: getPokemonNameWithAffix(target) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -6715,7 +6701,7 @@ export class FirstMoveTypeAttr extends MoveEffectAttr {
|
|||||||
|
|
||||||
const firstMoveType = target.getMoveset()[0].getMove().type;
|
const firstMoveType = target.getMoveset()[0].getMove().type;
|
||||||
user.summonData.types = [ firstMoveType ];
|
user.summonData.types = [ firstMoveType ];
|
||||||
globalScene.queueMessage(i18next.t("battle:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), type: i18next.t(`pokemonInfo:Type.${PokemonType[firstMoveType]}`) }));
|
globalScene.phaseManager.queueMessage(i18next.t("battle:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), type: i18next.t(`pokemonInfo:Type.${PokemonType[firstMoveType]}`) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -6734,7 +6720,7 @@ class CallMoveAttr extends OverrideMoveEffectAttr {
|
|||||||
const replaceMoveTarget = move.moveTarget === MoveTarget.NEAR_OTHER ? MoveTarget.NEAR_ENEMY : undefined;
|
const replaceMoveTarget = move.moveTarget === MoveTarget.NEAR_OTHER ? MoveTarget.NEAR_ENEMY : undefined;
|
||||||
const moveTargets = getMoveTargets(user, move.id, replaceMoveTarget);
|
const moveTargets = getMoveTargets(user, move.id, replaceMoveTarget);
|
||||||
if (moveTargets.targets.length === 0) {
|
if (moveTargets.targets.length === 0) {
|
||||||
globalScene.queueMessage(i18next.t("battle:attackFailed"));
|
globalScene.phaseManager.queueMessage(i18next.t("battle:attackFailed"));
|
||||||
console.log("CallMoveAttr failed due to no targets.");
|
console.log("CallMoveAttr failed due to no targets.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -6742,8 +6728,8 @@ class CallMoveAttr extends OverrideMoveEffectAttr {
|
|||||||
? moveTargets.targets
|
? moveTargets.targets
|
||||||
: [ this.hasTarget ? target.getBattlerIndex() : moveTargets.targets[user.randBattleSeedInt(moveTargets.targets.length)] ]; // account for Mirror Move having a target already
|
: [ this.hasTarget ? target.getBattlerIndex() : moveTargets.targets[user.randBattleSeedInt(moveTargets.targets.length)] ]; // account for Mirror Move having a target already
|
||||||
user.getMoveQueue().push({ move: move.id, targets: targets, virtual: true, ignorePP: true });
|
user.getMoveQueue().push({ move: move.id, targets: targets, virtual: true, ignorePP: true });
|
||||||
globalScene.unshiftPhase(new LoadMoveAnimPhase(move.id));
|
globalScene.phaseManager.unshiftNew("LoadMoveAnimPhase", move.id);
|
||||||
globalScene.unshiftPhase(new MovePhase(user, targets, new PokemonMove(move.id, 0, 0, true), true, true));
|
globalScene.phaseManager.unshiftNew("MovePhase", user, targets, new PokemonMove(move.id, 0, 0, true), true, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6971,8 +6957,8 @@ export class NaturePowerAttr extends OverrideMoveEffectAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
user.getMoveQueue().push({ move: moveId, targets: [ target.getBattlerIndex() ], ignorePP: true });
|
user.getMoveQueue().push({ move: moveId, targets: [ target.getBattlerIndex() ], ignorePP: true });
|
||||||
globalScene.unshiftPhase(new LoadMoveAnimPhase(moveId));
|
globalScene.phaseManager.unshiftNew("LoadMoveAnimPhase", moveId);
|
||||||
globalScene.unshiftPhase(new MovePhase(user, [ target.getBattlerIndex() ], new PokemonMove(moveId, 0, 0, true), true));
|
globalScene.phaseManager.unshiftNew("MovePhase", user, [ target.getBattlerIndex() ], new PokemonMove(moveId, 0, 0, true), true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7053,13 +7039,13 @@ export class RepeatMoveAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:instructingMove", {
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:instructingMove", {
|
||||||
userPokemonName: getPokemonNameWithAffix(user),
|
userPokemonName: getPokemonNameWithAffix(user),
|
||||||
targetPokemonName: getPokemonNameWithAffix(target)
|
targetPokemonName: getPokemonNameWithAffix(target)
|
||||||
}));
|
}));
|
||||||
target.getMoveQueue().unshift({ move: lastMove.move, targets: moveTargets, ignorePP: false });
|
target.getMoveQueue().unshift({ move: lastMove.move, targets: moveTargets, ignorePP: false });
|
||||||
target.turnData.extraTurns++;
|
target.turnData.extraTurns++;
|
||||||
globalScene.appendToPhase(new MovePhase(target, moveTargets, movesetMove), MoveEndPhase);
|
globalScene.phaseManager.appendNewToPhase("MoveEndPhase", "MovePhase", target, moveTargets, movesetMove);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7174,7 +7160,7 @@ export class ReducePpMoveAttr extends MoveEffectAttr {
|
|||||||
|
|
||||||
const message = i18next.t("battle:ppReduced", { targetName: getPokemonNameWithAffix(target), moveName: movesetMove.getName(), reduction: (movesetMove.ppUsed) - lastPpUsed });
|
const message = i18next.t("battle:ppReduced", { targetName: getPokemonNameWithAffix(target), moveName: movesetMove.getName(), reduction: (movesetMove.ppUsed) - lastPpUsed });
|
||||||
globalScene.eventTarget.dispatchEvent(new MoveUsedEvent(target.id, movesetMove.getMove(), movesetMove.ppUsed));
|
globalScene.eventTarget.dispatchEvent(new MoveUsedEvent(target.id, movesetMove.getMove(), movesetMove.ppUsed));
|
||||||
globalScene.queueMessage(message);
|
globalScene.phaseManager.queueMessage(message);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -7285,7 +7271,7 @@ export class MovesetCopyMoveAttr extends OverrideMoveEffectAttr {
|
|||||||
user.summonData.moveset = user.getMoveset().slice(0);
|
user.summonData.moveset = user.getMoveset().slice(0);
|
||||||
user.summonData.moveset[thisMoveIndex] = new PokemonMove(copiedMove.id, 0, 0);
|
user.summonData.moveset[thisMoveIndex] = new PokemonMove(copiedMove.id, 0, 0);
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:copiedMove", { pokemonName: getPokemonNameWithAffix(user), moveName: copiedMove.name }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:copiedMove", { pokemonName: getPokemonNameWithAffix(user), moveName: copiedMove.name }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -7335,7 +7321,7 @@ export class SketchAttr extends MoveEffectAttr {
|
|||||||
|
|
||||||
user.setMove(sketchIndex, sketchedMove.id);
|
user.setMove(sketchIndex, sketchedMove.id);
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:sketchedMove", { pokemonName: getPokemonNameWithAffix(user), moveName: sketchedMove.name }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:sketchedMove", { pokemonName: getPokemonNameWithAffix(user), moveName: sketchedMove.name }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -7367,11 +7353,7 @@ export class SketchAttr extends MoveEffectAttr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.getMoveset().find(m => m.moveId === targetMove.move)) {
|
return !user.getMoveset().some(m => m.moveId === targetMove.move);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7394,9 +7376,9 @@ export class AbilityChangeAttr extends MoveEffectAttr {
|
|||||||
|
|
||||||
globalScene.triggerPokemonFormChange(moveTarget, SpeciesFormChangeRevertWeatherFormTrigger);
|
globalScene.triggerPokemonFormChange(moveTarget, SpeciesFormChangeRevertWeatherFormTrigger);
|
||||||
if (moveTarget.breakIllusion()) {
|
if (moveTarget.breakIllusion()) {
|
||||||
globalScene.queueMessage(i18next.t("abilityTriggers:illusionBreak", { pokemonName: getPokemonNameWithAffix(moveTarget) }));
|
globalScene.phaseManager.queueMessage(i18next.t("abilityTriggers:illusionBreak", { pokemonName: getPokemonNameWithAffix(moveTarget) }));
|
||||||
}
|
}
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:acquiredAbility", { pokemonName: getPokemonNameWithAffix(moveTarget), abilityName: allAbilities[this.ability].name }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:acquiredAbility", { pokemonName: getPokemonNameWithAffix(moveTarget), abilityName: allAbilities[this.ability].name }));
|
||||||
moveTarget.setTempAbility(allAbilities[this.ability]);
|
moveTarget.setTempAbility(allAbilities[this.ability]);
|
||||||
globalScene.triggerPokemonFormChange(moveTarget, SpeciesFormChangeRevertWeatherFormTrigger);
|
globalScene.triggerPokemonFormChange(moveTarget, SpeciesFormChangeRevertWeatherFormTrigger);
|
||||||
return true;
|
return true;
|
||||||
@ -7421,13 +7403,13 @@ export class AbilityCopyAttr extends MoveEffectAttr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:copiedTargetAbility", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), abilityName: allAbilities[target.getAbility().id].name }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:copiedTargetAbility", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), abilityName: allAbilities[target.getAbility().id].name }));
|
||||||
|
|
||||||
user.setTempAbility(target.getAbility());
|
user.setTempAbility(target.getAbility());
|
||||||
const ally = user.getAlly();
|
const ally = user.getAlly();
|
||||||
|
|
||||||
if (this.copyToPartner && globalScene.currentBattle?.double && !isNullOrUndefined(ally) && ally.hp) { // TODO is this the best way to check that the ally is active?
|
if (this.copyToPartner && globalScene.currentBattle?.double && !isNullOrUndefined(ally) && ally.hp) { // TODO is this the best way to check that the ally is active?
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:copiedTargetAbility", { pokemonName: getPokemonNameWithAffix(ally), targetName: getPokemonNameWithAffix(target), abilityName: allAbilities[target.getAbility().id].name }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:copiedTargetAbility", { pokemonName: getPokemonNameWithAffix(ally), targetName: getPokemonNameWithAffix(target), abilityName: allAbilities[target.getAbility().id].name }));
|
||||||
ally.setTempAbility(target.getAbility());
|
ally.setTempAbility(target.getAbility());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7460,7 +7442,7 @@ export class AbilityGiveAttr extends MoveEffectAttr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:acquiredAbility", { pokemonName: getPokemonNameWithAffix(target), abilityName: allAbilities[user.getAbility().id].name }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:acquiredAbility", { pokemonName: getPokemonNameWithAffix(target), abilityName: allAbilities[user.getAbility().id].name }));
|
||||||
|
|
||||||
target.setTempAbility(user.getAbility());
|
target.setTempAbility(user.getAbility());
|
||||||
|
|
||||||
@ -7480,7 +7462,7 @@ export class SwitchAbilitiesAttr extends MoveEffectAttr {
|
|||||||
|
|
||||||
const tempAbility = user.getAbility();
|
const tempAbility = user.getAbility();
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:swappedAbilitiesWithTarget", { pokemonName: getPokemonNameWithAffix(user) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:swappedAbilitiesWithTarget", { pokemonName: getPokemonNameWithAffix(user) }));
|
||||||
|
|
||||||
user.setTempAbility(target.getAbility());
|
user.setTempAbility(target.getAbility());
|
||||||
target.setTempAbility(tempAbility);
|
target.setTempAbility(tempAbility);
|
||||||
@ -7510,7 +7492,7 @@ export class SuppressAbilitiesAttr extends MoveEffectAttr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:suppressAbilities", { pokemonName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:suppressAbilities", { pokemonName: getPokemonNameWithAffix(target) }));
|
||||||
|
|
||||||
target.suppressAbility();
|
target.suppressAbility();
|
||||||
|
|
||||||
@ -7563,9 +7545,9 @@ export class TransformAttr extends MoveEffectAttr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.unshiftPhase(new PokemonTransformPhase(user.getBattlerIndex(), target.getBattlerIndex()));
|
globalScene.phaseManager.unshiftNew("PokemonTransformPhase", user.getBattlerIndex(), target.getBattlerIndex());
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:transformedIntoTarget", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:transformedIntoTarget", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -7602,7 +7584,7 @@ export class SwapStatAttr extends MoveEffectAttr {
|
|||||||
user.setStat(this.stat, target.getStat(this.stat, false), false);
|
user.setStat(this.stat, target.getStat(this.stat, false), false);
|
||||||
target.setStat(this.stat, temp, false);
|
target.setStat(this.stat, temp, false);
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:switchedStat", {
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:switchedStat", {
|
||||||
pokemonName: getPokemonNameWithAffix(user),
|
pokemonName: getPokemonNameWithAffix(user),
|
||||||
stat: i18next.t(getStatKey(this.stat)),
|
stat: i18next.t(getStatKey(this.stat)),
|
||||||
}));
|
}));
|
||||||
@ -7648,7 +7630,7 @@ export class ShiftStatAttr extends MoveEffectAttr {
|
|||||||
user.setStat(this.statToSwitch, secondStat, false);
|
user.setStat(this.statToSwitch, secondStat, false);
|
||||||
user.setStat(this.statToSwitchWith, firstStat, false);
|
user.setStat(this.statToSwitchWith, firstStat, false);
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:shiftedStats", {
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:shiftedStats", {
|
||||||
pokemonName: getPokemonNameWithAffix(user),
|
pokemonName: getPokemonNameWithAffix(user),
|
||||||
statToSwitch: i18next.t(getStatKey(this.statToSwitch)),
|
statToSwitch: i18next.t(getStatKey(this.statToSwitch)),
|
||||||
statToSwitchWith: i18next.t(getStatKey(this.statToSwitchWith))
|
statToSwitchWith: i18next.t(getStatKey(this.statToSwitchWith))
|
||||||
@ -7707,7 +7689,7 @@ export class AverageStatsAttr extends MoveEffectAttr {
|
|||||||
target.setStat(s, avg, false);
|
target.setStat(s, avg, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t(this.msgKey, { pokemonName: getPokemonNameWithAffix(user) }));
|
globalScene.phaseManager.queueMessage(i18next.t(this.msgKey, { pokemonName: getPokemonNameWithAffix(user) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -7722,7 +7704,7 @@ export class MoneyAttr extends MoveEffectAttr {
|
|||||||
|
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move): boolean {
|
||||||
globalScene.currentBattle.moneyScattered += globalScene.getWaveMoneyAmount(0.2);
|
globalScene.currentBattle.moneyScattered += globalScene.getWaveMoneyAmount(0.2);
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:coinsScatteredEverywhere"));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:coinsScatteredEverywhere"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7746,7 +7728,7 @@ export class DestinyBondAttr extends MoveEffectAttr {
|
|||||||
* @returns true
|
* @returns true
|
||||||
*/
|
*/
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
globalScene.queueMessage(`${i18next.t("moveTriggers:tryingToTakeFoeDown", { pokemonName: getPokemonNameWithAffix(user) })}`);
|
globalScene.phaseManager.queueMessage(`${i18next.t("moveTriggers:tryingToTakeFoeDown", { pokemonName: getPokemonNameWithAffix(user) })}`);
|
||||||
user.addTag(BattlerTagType.DESTINY_BOND, undefined, move.id, user.id);
|
user.addTag(BattlerTagType.DESTINY_BOND, undefined, move.id, user.id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -7860,12 +7842,12 @@ export class AfterYouAttr extends MoveEffectAttr {
|
|||||||
* @returns true
|
* @returns true
|
||||||
*/
|
*/
|
||||||
override apply(user: Pokemon, target: Pokemon, _move: Move, _args: any[]): boolean {
|
override apply(user: Pokemon, target: Pokemon, _move: Move, _args: any[]): boolean {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:afterYou", { targetName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:afterYou", { targetName: getPokemonNameWithAffix(target) }));
|
||||||
|
|
||||||
//Will find next acting phase of the targeted pokémon, delete it and queue it next on successful delete.
|
//Will find next acting phase of the targeted pokémon, delete it and queue it next on successful delete.
|
||||||
const nextAttackPhase = globalScene.findPhase<MovePhase>((phase) => phase.pokemon === target);
|
const nextAttackPhase = globalScene.phaseManager.findPhase<MovePhase>((phase) => phase.pokemon === target);
|
||||||
if (nextAttackPhase && globalScene.tryRemovePhase((phase: MovePhase) => phase.pokemon === target)) {
|
if (nextAttackPhase && globalScene.phaseManager.tryRemovePhase((phase: MovePhase) => phase.pokemon === target)) {
|
||||||
globalScene.prependToPhase(new MovePhase(target, [ ...nextAttackPhase.targets ], nextAttackPhase.move), MovePhase);
|
globalScene.phaseManager.prependNewToPhase("MovePhase", "MovePhase", target, [ ...nextAttackPhase.targets ], nextAttackPhase.move);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -7888,21 +7870,21 @@ export class ForceLastAttr extends MoveEffectAttr {
|
|||||||
* @returns true
|
* @returns true
|
||||||
*/
|
*/
|
||||||
override apply(user: Pokemon, target: Pokemon, _move: Move, _args: any[]): boolean {
|
override apply(user: Pokemon, target: Pokemon, _move: Move, _args: any[]): boolean {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:forceLast", { targetPokemonName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:forceLast", { targetPokemonName: getPokemonNameWithAffix(target) }));
|
||||||
|
|
||||||
const targetMovePhase = globalScene.findPhase<MovePhase>((phase) => phase.pokemon === target);
|
const targetMovePhase = globalScene.phaseManager.findPhase<MovePhase>((phase) => phase.pokemon === target);
|
||||||
if (targetMovePhase && !targetMovePhase.isForcedLast() && globalScene.tryRemovePhase((phase: MovePhase) => phase.pokemon === target)) {
|
if (targetMovePhase && !targetMovePhase.isForcedLast() && globalScene.phaseManager.tryRemovePhase((phase: MovePhase) => phase.pokemon === target)) {
|
||||||
// Finding the phase to insert the move in front of -
|
// Finding the phase to insert the move in front of -
|
||||||
// Either the end of the turn or in front of another, slower move which has also been forced last
|
// Either the end of the turn or in front of another, slower move which has also been forced last
|
||||||
const prependPhase = globalScene.findPhase((phase) =>
|
const prependPhase = globalScene.phaseManager.findPhase((phase) =>
|
||||||
[ MovePhase, MoveEndPhase ].every(cls => !(phase instanceof cls))
|
[ MovePhase, MoveEndPhase ].every(cls => !(phase instanceof cls))
|
||||||
|| (phase instanceof MovePhase) && phaseForcedSlower(phase, target, !!globalScene.arena.getTag(ArenaTagType.TRICK_ROOM))
|
|| (phase.is("MovePhase")) && phaseForcedSlower(phase, target, !!globalScene.arena.getTag(ArenaTagType.TRICK_ROOM))
|
||||||
);
|
);
|
||||||
if (prependPhase) {
|
if (prependPhase) {
|
||||||
globalScene.phaseQueue.splice(
|
globalScene.phaseManager.phaseQueue.splice(
|
||||||
globalScene.phaseQueue.indexOf(prependPhase),
|
globalScene.phaseManager.phaseQueue.indexOf(prependPhase),
|
||||||
0,
|
0,
|
||||||
new MovePhase(target, [ ...targetMovePhase.targets ], targetMovePhase.move, false, false, false, true)
|
globalScene.phaseManager.create("MovePhase", target, [ ...targetMovePhase.targets ], targetMovePhase.move, false, false, false, true)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7933,7 +7915,7 @@ const failIfDampCondition: MoveConditionFunc = (user, target, move) => {
|
|||||||
globalScene.getField(true).map(p=>applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled));
|
globalScene.getField(true).map(p=>applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled));
|
||||||
// Queue a message if an ability prevented usage of the move
|
// Queue a message if an ability prevented usage of the move
|
||||||
if (cancelled.value) {
|
if (cancelled.value) {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:cannotUseMove", { pokemonName: getPokemonNameWithAffix(user), moveName: move.name }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:cannotUseMove", { pokemonName: getPokemonNameWithAffix(user), moveName: move.name }));
|
||||||
}
|
}
|
||||||
return !cancelled.value;
|
return !cancelled.value;
|
||||||
};
|
};
|
||||||
@ -7942,7 +7924,7 @@ const userSleptOrComatoseCondition: MoveConditionFunc = (user: Pokemon, target:
|
|||||||
|
|
||||||
const targetSleptOrComatoseCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => target.status?.effect === StatusEffect.SLEEP || target.hasAbility(AbilityId.COMATOSE);
|
const targetSleptOrComatoseCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => target.status?.effect === StatusEffect.SLEEP || target.hasAbility(AbilityId.COMATOSE);
|
||||||
|
|
||||||
const failIfLastCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => globalScene.phaseQueue.find(phase => phase instanceof MovePhase) !== undefined;
|
const failIfLastCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => globalScene.phaseManager.phaseQueue.find(phase => phase.is("MovePhase")) !== undefined;
|
||||||
|
|
||||||
const failIfLastInPartyCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => {
|
const failIfLastInPartyCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => {
|
||||||
const party: Pokemon[] = user.isPlayer() ? globalScene.getPlayerParty() : globalScene.getEnemyParty();
|
const party: Pokemon[] = user.isPlayer() ? globalScene.getPlayerParty() : globalScene.getEnemyParty();
|
||||||
@ -8120,7 +8102,7 @@ export class ResistLastMoveTypeAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
const type = validTypes[user.randBattleSeedInt(validTypes.length)];
|
const type = validTypes[user.randBattleSeedInt(validTypes.length)];
|
||||||
user.summonData.types = [ type ];
|
user.summonData.types = [ type ];
|
||||||
globalScene.queueMessage(i18next.t("battle:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), type: toReadableString(PokemonType[type]) }));
|
globalScene.phaseManager.queueMessage(i18next.t("battle:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), type: toReadableString(PokemonType[type]) }));
|
||||||
user.updateInfo();
|
user.updateInfo();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -8179,7 +8161,7 @@ export class ExposedMoveAttr extends AddBattlerTagAttr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:exposedMove", { pokemonName: getPokemonNameWithAffix(user), targetPokemonName: getPokemonNameWithAffix(target) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:exposedMove", { pokemonName: getPokemonNameWithAffix(user), targetPokemonName: getPokemonNameWithAffix(target) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -8815,7 +8797,7 @@ export function initMoves() {
|
|||||||
.reflectable(),
|
.reflectable(),
|
||||||
new SelfStatusMove(MoveId.BELLY_DRUM, PokemonType.NORMAL, -1, 10, -1, 0, 2)
|
new SelfStatusMove(MoveId.BELLY_DRUM, PokemonType.NORMAL, -1, 10, -1, 0, 2)
|
||||||
.attr(CutHpStatStageBoostAttr, [ Stat.ATK ], 12, 2, (user) => {
|
.attr(CutHpStatStageBoostAttr, [ Stat.ATK ], 12, 2, (user) => {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:cutOwnHpAndMaximizedStat", { pokemonName: getPokemonNameWithAffix(user), statName: i18next.t(getStatKey(Stat.ATK)) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:cutOwnHpAndMaximizedStat", { pokemonName: getPokemonNameWithAffix(user), statName: i18next.t(getStatKey(Stat.ATK)) }));
|
||||||
}),
|
}),
|
||||||
new AttackMove(MoveId.SLUDGE_BOMB, PokemonType.POISON, MoveCategory.SPECIAL, 90, 100, 10, 30, 0, 2)
|
new AttackMove(MoveId.SLUDGE_BOMB, PokemonType.POISON, MoveCategory.SPECIAL, 90, 100, 10, 30, 0, 2)
|
||||||
.attr(StatusEffectAttr, StatusEffect.POISON)
|
.attr(StatusEffectAttr, StatusEffect.POISON)
|
||||||
@ -9868,7 +9850,7 @@ export function initMoves() {
|
|||||||
const lastEnemyFaint = globalScene.currentBattle.enemyFaintsHistory[globalScene.currentBattle.enemyFaintsHistory.length - 1];
|
const lastEnemyFaint = globalScene.currentBattle.enemyFaintsHistory[globalScene.currentBattle.enemyFaintsHistory.length - 1];
|
||||||
return (
|
return (
|
||||||
(lastPlayerFaint !== undefined && turn - lastPlayerFaint.turn === 1 && user.isPlayer()) ||
|
(lastPlayerFaint !== undefined && turn - lastPlayerFaint.turn === 1 && user.isPlayer()) ||
|
||||||
(lastEnemyFaint !== undefined && turn - lastEnemyFaint.turn === 1 && !user.isPlayer())
|
(lastEnemyFaint !== undefined && turn - lastEnemyFaint.turn === 1 && user.isEnemy())
|
||||||
) ? 2 : 1;
|
) ? 2 : 1;
|
||||||
}),
|
}),
|
||||||
new AttackMove(MoveId.FINAL_GAMBIT, PokemonType.FIGHTING, MoveCategory.SPECIAL, -1, 100, 5, -1, 0, 5)
|
new AttackMove(MoveId.FINAL_GAMBIT, PokemonType.FIGHTING, MoveCategory.SPECIAL, -1, 100, 5, -1, 0, 5)
|
||||||
@ -10383,7 +10365,7 @@ export function initMoves() {
|
|||||||
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
|
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.BURNED_UP, true, false)
|
.attr(AddBattlerTagAttr, BattlerTagType.BURNED_UP, true, false)
|
||||||
.attr(RemoveTypeAttr, PokemonType.FIRE, (user) => {
|
.attr(RemoveTypeAttr, PokemonType.FIRE, (user) => {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:burnedItselfOut", { pokemonName: getPokemonNameWithAffix(user) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:burnedItselfOut", { pokemonName: getPokemonNameWithAffix(user) }));
|
||||||
}),
|
}),
|
||||||
new StatusMove(MoveId.SPEED_SWAP, PokemonType.PSYCHIC, -1, 10, -1, 0, 7)
|
new StatusMove(MoveId.SPEED_SWAP, PokemonType.PSYCHIC, -1, 10, -1, 0, 7)
|
||||||
.attr(SwapStatAttr, Stat.SPD)
|
.attr(SwapStatAttr, Stat.SPD)
|
||||||
@ -11167,7 +11149,7 @@ export function initMoves() {
|
|||||||
})
|
})
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.DOUBLE_SHOCKED, true, false)
|
.attr(AddBattlerTagAttr, BattlerTagType.DOUBLE_SHOCKED, true, false)
|
||||||
.attr(RemoveTypeAttr, PokemonType.ELECTRIC, (user) => {
|
.attr(RemoveTypeAttr, PokemonType.ELECTRIC, (user) => {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:usedUpAllElectricity", { pokemonName: getPokemonNameWithAffix(user) }));
|
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:usedUpAllElectricity", { pokemonName: getPokemonNameWithAffix(user) }));
|
||||||
}),
|
}),
|
||||||
new AttackMove(MoveId.GIGATON_HAMMER, PokemonType.STEEL, MoveCategory.PHYSICAL, 160, 100, 5, -1, 0, 9)
|
new AttackMove(MoveId.GIGATON_HAMMER, PokemonType.STEEL, MoveCategory.PHYSICAL, 160, 100, 5, -1, 0, 9)
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
|
@ -19,7 +19,6 @@ import i18next from "i18next";
|
|||||||
import type { IEggOptions } from "#app/data/egg";
|
import type { IEggOptions } from "#app/data/egg";
|
||||||
import { EggSourceType } from "#enums/egg-source-types";
|
import { EggSourceType } from "#enums/egg-source-types";
|
||||||
import { EggTier } from "#enums/egg-type";
|
import { EggTier } from "#enums/egg-type";
|
||||||
import { PartyHealPhase } from "#app/phases/party-heal-phase";
|
|
||||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
@ -182,7 +181,7 @@ export const ATrainersTestEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
|||||||
async () => {
|
async () => {
|
||||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||||
// Full heal party
|
// Full heal party
|
||||||
globalScene.unshiftPhase(new PartyHealPhase(true));
|
globalScene.phaseManager.unshiftNew("PartyHealPhase", true);
|
||||||
|
|
||||||
const eggOptions: IEggOptions = {
|
const eggOptions: IEggOptions = {
|
||||||
pulled: false,
|
pulled: false,
|
||||||
|
@ -33,9 +33,8 @@ import {
|
|||||||
} from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
} from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { TrainerSlot } from "#enums/trainer-slot";
|
import { TrainerSlot } from "#enums/trainer-slot";
|
||||||
import { PokeballType } from "#enums/pokeball";
|
import { PokeballType } from "#enums/pokeball";
|
||||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||||
import type { BerryType } from "#enums/berry-type";
|
import type { BerryType } from "#enums/berry-type";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
@ -237,8 +236,12 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
queueEncounterMessage(`${namespace}:option.1.boss_enraged`);
|
queueEncounterMessage(`${namespace}:option.1.boss_enraged`);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(pokemon.getBattlerIndex(), true, statChangesForBattle, 1),
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
statChangesForBattle,
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -22,7 +22,6 @@ import { getPokemonSpecies } from "#app/data/pokemon-species";
|
|||||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
@ -137,7 +136,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = MysteryEncounterB
|
|||||||
})
|
})
|
||||||
.withOptionPhase(async () => {
|
.withOptionPhase(async () => {
|
||||||
// Give the player a Shiny Charm
|
// Give the player a Shiny Charm
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.SHINY_CHARM));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.SHINY_CHARM);
|
||||||
leaveEncounterWithoutBattle(true);
|
leaveEncounterWithoutBattle(true);
|
||||||
})
|
})
|
||||||
.build(),
|
.build(),
|
||||||
|
@ -35,7 +35,6 @@ import { BerryModifier } from "#app/modifier/modifier";
|
|||||||
import i18next from "#app/plugins/i18n";
|
import i18next from "#app/plugins/i18n";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { PERMANENT_STATS, Stat } from "#enums/stat";
|
import { PERMANENT_STATS, Stat } from "#enums/stat";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
@ -237,8 +236,12 @@ export const BerriesAboundEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
|||||||
config.pokemonConfigs![0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
|
config.pokemonConfigs![0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
|
||||||
config.pokemonConfigs![0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => {
|
config.pokemonConfigs![0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => {
|
||||||
queueEncounterMessage(`${namespace}:option.2.boss_enraged`);
|
queueEncounterMessage(`${namespace}:option.2.boss_enraged`);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(pokemon.getBattlerIndex(), true, statChangesForBattle, 1),
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
statChangesForBattle,
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
setEncounterRewards(
|
setEncounterRewards(
|
||||||
|
@ -26,7 +26,6 @@ import type { PlayerPokemon } from "#app/field/pokemon";
|
|||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "#app/field/pokemon";
|
||||||
import { getEncounterText, showEncounterDialogue } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText, showEncounterDialogue } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
@ -766,8 +765,10 @@ function doBugTypeMoveTutor(): Promise<void> {
|
|||||||
|
|
||||||
// Option select complete, handle if they are learning a move
|
// Option select complete, handle if they are learning a move
|
||||||
if (result && result.selectedOptionIndex < moveOptions.length) {
|
if (result && result.selectedOptionIndex < moveOptions.length) {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new LearnMovePhase(result.selectedPokemonIndex, moveOptions[result.selectedOptionIndex].moveId),
|
"LearnMovePhase",
|
||||||
|
result.selectedPokemonIndex,
|
||||||
|
moveOptions[result.selectedOptionIndex].moveId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,8 +26,6 @@ import type Pokemon from "#app/field/pokemon";
|
|||||||
import { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
|
import { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import PokemonData from "#app/system/pokemon-data";
|
import PokemonData from "#app/system/pokemon-data";
|
||||||
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
@ -176,13 +174,12 @@ export const DancingLessonsEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
queueEncounterMessage(`${namespace}:option.1.boss_enraged`);
|
queueEncounterMessage(`${namespace}:option.1.boss_enraged`);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(
|
"StatStageChangePhase",
|
||||||
pokemon.getBattlerIndex(),
|
pokemon.getBattlerIndex(),
|
||||||
true,
|
true,
|
||||||
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF],
|
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF],
|
||||||
1,
|
1,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -245,8 +242,10 @@ export const DancingLessonsEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
|
|
||||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||||
encounter.setDialogueToken("selectedPokemon", pokemon.getNameToRender());
|
encounter.setDialogueToken("selectedPokemon", pokemon.getNameToRender());
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new LearnMovePhase(globalScene.getPlayerParty().indexOf(pokemon), MoveId.REVELATION_DANCE),
|
"LearnMovePhase",
|
||||||
|
globalScene.getPlayerParty().indexOf(pokemon),
|
||||||
|
MoveId.REVELATION_DANCE,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Play animation again to "learn" the dance
|
// Play animation again to "learn" the dance
|
||||||
|
@ -16,7 +16,6 @@ import {
|
|||||||
} from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
} from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
|
||||||
import type { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
import type { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||||
import { PokemonFormChangeItemModifier } from "#app/modifier/modifier";
|
import { PokemonFormChangeItemModifier } from "#app/modifier/modifier";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
@ -165,7 +164,7 @@ export const DarkDealEncounter: MysteryEncounter = MysteryEncounterBuilder.withE
|
|||||||
.withOptionPhase(async () => {
|
.withOptionPhase(async () => {
|
||||||
// Give the player 5 Rogue Balls
|
// Give the player 5 Rogue Balls
|
||||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.ROGUE_BALL));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.ROGUE_BALL);
|
||||||
|
|
||||||
// Start encounter with random legendary (7-10 starter strength) that has level additive
|
// Start encounter with random legendary (7-10 starter strength) that has level additive
|
||||||
// If this is a mono-type challenge, always ensure the required type is filtered for
|
// If this is a mono-type challenge, always ensure the required type is filtered for
|
||||||
|
@ -29,7 +29,6 @@ import {
|
|||||||
} from "#app/modifier/modifier";
|
} from "#app/modifier/modifier";
|
||||||
import type { PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
import type { PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
|
||||||
import i18next from "#app/plugins/i18n";
|
import i18next from "#app/plugins/i18n";
|
||||||
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import { randSeedItem } from "#app/utils/common";
|
import { randSeedItem } from "#app/utils/common";
|
||||||
@ -65,10 +64,10 @@ const doEventReward = () => {
|
|||||||
return !(existingCharm && existingCharm.getStackCount() >= existingCharm.getMaxStackCount());
|
return !(existingCharm && existingCharm.getStackCount() >= existingCharm.getMaxStackCount());
|
||||||
});
|
});
|
||||||
if (candidates.length > 0) {
|
if (candidates.length > 0) {
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes[randSeedItem(candidates)]));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes[randSeedItem(candidates)]);
|
||||||
} else {
|
} else {
|
||||||
// At max stacks, give a Voucher instead
|
// At max stacks, give a Voucher instead
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.VOUCHER));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.VOUCHER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -181,7 +180,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
);
|
);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
} else {
|
} else {
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.AMULET_COIN));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.AMULET_COIN);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,7 +265,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
);
|
);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
} else {
|
} else {
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.CANDY_JAR));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.CANDY_JAR);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -288,7 +287,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
);
|
);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
} else {
|
} else {
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.BERRY_POUCH));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.BERRY_POUCH);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,7 +371,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
);
|
);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
} else {
|
} else {
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.HEALING_CHARM));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.HEALING_CHARM);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,6 @@ import { EncounterAnim } from "#enums/encounter-anims";
|
|||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import { AbilityId } from "#enums/ability-id";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { Ability } from "#app/data/abilities/ability-class";
|
import { Ability } from "#app/data/abilities/ability-class";
|
||||||
import { FIRE_RESISTANT_ABILITIES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
import { FIRE_RESISTANT_ABILITIES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||||
@ -92,8 +91,12 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w
|
|||||||
gender: Gender.MALE,
|
gender: Gender.MALE,
|
||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(pokemon.getBattlerIndex(), true, [Stat.SPDEF, Stat.SPD], 1),
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
[Stat.SPDEF, Stat.SPD],
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -103,8 +106,12 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w
|
|||||||
gender: Gender.FEMALE,
|
gender: Gender.FEMALE,
|
||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(pokemon.getBattlerIndex(), true, [Stat.SPDEF, Stat.SPD], 1),
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
[Stat.SPDEF, Stat.SPD],
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -32,7 +32,6 @@ import PokemonData from "#app/system/pokemon-data";
|
|||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { randSeedInt } from "#app/utils/common";
|
import { randSeedInt } from "#app/utils/common";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
@ -76,7 +75,13 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
|||||||
queueEncounterMessage(`${namespace}:option.1.stat_boost`);
|
queueEncounterMessage(`${namespace}:option.1.stat_boost`);
|
||||||
// Randomly boost 1 stat 2 stages
|
// Randomly boost 1 stat 2 stages
|
||||||
// Cannot boost Spd, Acc, or Evasion
|
// Cannot boost Spd, Acc, or Evasion
|
||||||
globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [randSeedInt(4, 1)], 2));
|
globalScene.phaseManager.unshiftNew(
|
||||||
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
[randSeedInt(4, 1)],
|
||||||
|
2,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -25,9 +25,7 @@ import { getPokemonNameWithAffix } from "#app/messages";
|
|||||||
import { PlayerGender } from "#enums/player-gender";
|
import { PlayerGender } from "#enums/player-gender";
|
||||||
import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball";
|
import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball";
|
||||||
import { addPokeballOpenParticles } from "#app/field/anims";
|
import { addPokeballOpenParticles } from "#app/field/anims";
|
||||||
import { ShinySparklePhase } from "#app/phases/shiny-sparkle-phase";
|
|
||||||
import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms";
|
import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms";
|
||||||
import { PostSummonPhase } from "#app/phases/post-summon-phase";
|
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
@ -411,13 +409,13 @@ function summonPlayerPokemonAnimation(pokemon: PlayerPokemon): Promise<void> {
|
|||||||
pokemon.resetSummonData();
|
pokemon.resetSummonData();
|
||||||
globalScene.time.delayedCall(1000, () => {
|
globalScene.time.delayedCall(1000, () => {
|
||||||
if (pokemon.isShiny()) {
|
if (pokemon.isShiny()) {
|
||||||
globalScene.unshiftPhase(new ShinySparklePhase(pokemon.getBattlerIndex()));
|
globalScene.phaseManager.unshiftNew("ShinySparklePhase", pokemon.getBattlerIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
pokemon.resetTurnData();
|
pokemon.resetTurnData();
|
||||||
|
|
||||||
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeActiveTrigger, true);
|
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeActiveTrigger, true);
|
||||||
globalScene.pushPhase(new PostSummonPhase(pokemon.getBattlerIndex()));
|
globalScene.phaseManager.pushNew("PostSummonPhase", pokemon.getBattlerIndex());
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -17,7 +17,6 @@ import {
|
|||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||||
import { GameOverPhase } from "#app/phases/game-over-phase";
|
|
||||||
import { randSeedInt } from "#app/utils/common";
|
import { randSeedInt } from "#app/utils/common";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
@ -189,8 +188,8 @@ export const MysteriousChestEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
const allowedPokemon = globalScene.getPokemonAllowedInBattle();
|
const allowedPokemon = globalScene.getPokemonAllowedInBattle();
|
||||||
if (allowedPokemon.length === 0) {
|
if (allowedPokemon.length === 0) {
|
||||||
// If there are no longer any legal pokemon in the party, game over.
|
// If there are no longer any legal pokemon in the party, game over.
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.unshiftPhase(new GameOverPhase());
|
globalScene.phaseManager.unshiftNew("GameOverPhase");
|
||||||
} else {
|
} else {
|
||||||
// Show which Pokemon was KOed, then start battle against Gimmighoul
|
// Show which Pokemon was KOed, then start battle against Gimmighoul
|
||||||
await transitionMysteryEncounterIntroVisuals(true, true, 500);
|
await transitionMysteryEncounterIntroVisuals(true, true, 500);
|
||||||
|
@ -29,8 +29,6 @@ import { getEncounterText, showEncounterText } from "#app/data/mystery-encounter
|
|||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { ScanIvsPhase } from "#app/phases/scan-ivs-phase";
|
|
||||||
import { SummonPhase } from "#app/phases/summon-phase";
|
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import { NON_LEGEND_PARADOX_POKEMON } from "#app/data/balance/special-species-groups";
|
import { NON_LEGEND_PARADOX_POKEMON } from "#app/data/balance/special-species-groups";
|
||||||
|
|
||||||
@ -276,7 +274,7 @@ async function summonSafariPokemon() {
|
|||||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||||
// Message pokemon remaining
|
// Message pokemon remaining
|
||||||
encounter.setDialogueToken("remainingCount", encounter.misc.safariPokemonRemaining);
|
encounter.setDialogueToken("remainingCount", encounter.misc.safariPokemonRemaining);
|
||||||
globalScene.queueMessage(getEncounterText(`${namespace}:safari.remaining_count`) ?? "", null, true);
|
globalScene.phaseManager.queueMessage(getEncounterText(`${namespace}:safari.remaining_count`) ?? "", null, true);
|
||||||
|
|
||||||
// Generate pokemon using safariPokemonRemaining so they are always the same pokemon no matter how many turns are taken
|
// Generate pokemon using safariPokemonRemaining so they are always the same pokemon no matter how many turns are taken
|
||||||
// Safari pokemon roll twice on shiny and HA chances, but are otherwise normal
|
// Safari pokemon roll twice on shiny and HA chances, but are otherwise normal
|
||||||
@ -325,7 +323,7 @@ async function summonSafariPokemon() {
|
|||||||
encounter.misc.pokemon = pokemon;
|
encounter.misc.pokemon = pokemon;
|
||||||
encounter.misc.safariPokemonRemaining -= 1;
|
encounter.misc.safariPokemonRemaining -= 1;
|
||||||
|
|
||||||
globalScene.unshiftPhase(new SummonPhase(0, false));
|
globalScene.phaseManager.unshiftNew("SummonPhase", 0, false);
|
||||||
|
|
||||||
encounter.setDialogueToken("pokemonName", getPokemonNameWithAffix(pokemon));
|
encounter.setDialogueToken("pokemonName", getPokemonNameWithAffix(pokemon));
|
||||||
|
|
||||||
@ -336,7 +334,7 @@ async function summonSafariPokemon() {
|
|||||||
|
|
||||||
const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier);
|
const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier);
|
||||||
if (ivScannerModifier) {
|
if (ivScannerModifier) {
|
||||||
globalScene.pushPhase(new ScanIvsPhase(pokemon.getBattlerIndex()));
|
globalScene.phaseManager.pushNew("ScanIvsPhase", pokemon.getBattlerIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,7 +557,7 @@ async function doEndTurn(cursorIndex: number) {
|
|||||||
leaveEncounterWithoutBattle(true);
|
leaveEncounterWithoutBattle(true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
globalScene.queueMessage(getEncounterText(`${namespace}:safari.watching`) ?? "", 0, null, 1000);
|
globalScene.phaseManager.queueMessage(getEncounterText(`${namespace}:safari.watching`) ?? "", 0, null, 1000);
|
||||||
initSubsequentOptionSelect({
|
initSubsequentOptionSelect({
|
||||||
overrideOptions: safariZoneGameOptions,
|
overrideOptions: safariZoneGameOptions,
|
||||||
startingCursorIndex: cursorIndex,
|
startingCursorIndex: cursorIndex,
|
||||||
|
@ -26,7 +26,6 @@ import { AiType, PokemonMove } from "#app/field/pokemon";
|
|||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { PartyHealPhase } from "#app/phases/party-heal-phase";
|
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
@ -155,7 +154,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuil
|
|||||||
async () => {
|
async () => {
|
||||||
// Fall asleep waiting for Snorlax
|
// Fall asleep waiting for Snorlax
|
||||||
// Full heal party
|
// Full heal party
|
||||||
globalScene.unshiftPhase(new PartyHealPhase(true));
|
globalScene.phaseManager.unshiftNew("PartyHealPhase", true);
|
||||||
queueEncounterMessage(`${namespace}:option.2.rest_result`);
|
queueEncounterMessage(`${namespace}:option.2.rest_result`);
|
||||||
leaveEncounterWithoutBattle();
|
leaveEncounterWithoutBattle();
|
||||||
},
|
},
|
||||||
|
@ -27,7 +27,6 @@ import { getPartyLuckValue, modifierTypes } from "#app/modifier/modifier-type";
|
|||||||
import { TrainerSlot } from "#enums/trainer-slot";
|
import { TrainerSlot } from "#enums/trainer-slot";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import {
|
import {
|
||||||
@ -227,7 +226,13 @@ async function doBiomeTransitionDialogueAndBattleInit() {
|
|||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
queueEncounterMessage(`${namespace}:boss_enraged`);
|
queueEncounterMessage(`${namespace}:boss_enraged`);
|
||||||
globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, statChangesForBattle, 1));
|
globalScene.phaseManager.unshiftNew(
|
||||||
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
statChangesForBattle,
|
||||||
|
1,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -658,8 +658,8 @@ function onGameOver() {
|
|||||||
globalScene.playBgm(globalScene.arena.bgm);
|
globalScene.playBgm(globalScene.arena.bgm);
|
||||||
|
|
||||||
// Clear any leftover battle phases
|
// Clear any leftover battle phases
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.clearPhaseQueueSplice();
|
globalScene.phaseManager.clearPhaseQueueSplice();
|
||||||
|
|
||||||
// Return enemy Pokemon
|
// Return enemy Pokemon
|
||||||
const pokemon = globalScene.getEnemyPokemon();
|
const pokemon = globalScene.getEnemyPokemon();
|
||||||
|
@ -27,7 +27,6 @@ import { BerryType } from "#enums/berry-type";
|
|||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
@ -116,8 +115,12 @@ export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
queueEncounterMessage(`${namespace}:option.2.stat_boost`);
|
queueEncounterMessage(`${namespace}:option.2.stat_boost`);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(pokemon.getBattlerIndex(), true, [Stat.DEF, Stat.SPDEF], 1),
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
[Stat.DEF, Stat.SPDEF],
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -27,9 +27,6 @@ import { SpeciesFormChangeAbilityTrigger } from "#app/data/pokemon-forms";
|
|||||||
import { applyPostBattleInitAbAttrs, PostBattleInitAbAttr } from "#app/data/abilities/ability";
|
import { applyPostBattleInitAbAttrs, PostBattleInitAbAttr } from "#app/data/abilities/ability";
|
||||||
import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
import { PartyHealPhase } from "#app/phases/party-heal-phase";
|
|
||||||
import { ShowTrainerPhase } from "#app/phases/show-trainer-phase";
|
|
||||||
import { ReturnPhase } from "#app/phases/return-phase";
|
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
@ -143,7 +140,7 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter = MysteryEncounter
|
|||||||
},
|
},
|
||||||
async () => {
|
async () => {
|
||||||
// Refuse the challenge, they full heal the party and give the player a Rarer Candy
|
// Refuse the challenge, they full heal the party and give the player a Rarer Candy
|
||||||
globalScene.unshiftPhase(new PartyHealPhase(true));
|
globalScene.phaseManager.unshiftNew("PartyHealPhase", true);
|
||||||
setEncounterRewards({
|
setEncounterRewards({
|
||||||
guaranteedModifierTypeFuncs: [modifierTypes.RARER_CANDY],
|
guaranteedModifierTypeFuncs: [modifierTypes.RARER_CANDY],
|
||||||
fillRemaining: false,
|
fillRemaining: false,
|
||||||
@ -209,7 +206,7 @@ function endTrainerBattleAndShowDialogue(): Promise<void> {
|
|||||||
for (const pokemon of playerField) {
|
for (const pokemon of playerField) {
|
||||||
pokemon.lapseTag(BattlerTagType.COMMANDED);
|
pokemon.lapseTag(BattlerTagType.COMMANDED);
|
||||||
}
|
}
|
||||||
playerField.forEach((_, p) => globalScene.unshiftPhase(new ReturnPhase(p)));
|
playerField.forEach((_, p) => globalScene.phaseManager.unshiftNew("ReturnPhase", p));
|
||||||
|
|
||||||
for (const pokemon of globalScene.getPlayerParty()) {
|
for (const pokemon of globalScene.getPlayerParty()) {
|
||||||
// Only trigger form change when Eiscue is in Noice form
|
// Only trigger form change when Eiscue is in Noice form
|
||||||
@ -227,7 +224,7 @@ function endTrainerBattleAndShowDialogue(): Promise<void> {
|
|||||||
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, pokemon);
|
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, pokemon);
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.unshiftPhase(new ShowTrainerPhase());
|
globalScene.phaseManager.unshiftNew("ShowTrainerPhase");
|
||||||
// Hide the trainer and init next battle
|
// Hide the trainer and init next battle
|
||||||
const trainer = globalScene.currentBattle.trainer;
|
const trainer = globalScene.currentBattle.trainer;
|
||||||
// Unassign previous trainer from battle so it isn't destroyed before animation completes
|
// Unassign previous trainer from battle so it isn't destroyed before animation completes
|
||||||
|
@ -25,7 +25,7 @@ import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/myst
|
|||||||
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { getStatKey } from "#enums/stat";
|
import { getStatKey } from "#enums/stat";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
|
@ -35,7 +35,6 @@ import { PokeballType } from "#enums/pokeball";
|
|||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { BerryModifier } from "#app/modifier/modifier";
|
import { BerryModifier } from "#app/modifier/modifier";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
|
|
||||||
@ -103,8 +102,12 @@ export const UncommonBreedEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
|||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
queueEncounterMessage(`${namespace}:option.1.stat_boost`);
|
queueEncounterMessage(`${namespace}:option.1.stat_boost`);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(pokemon.getBattlerIndex(), true, statChangesForBattle, 1),
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
statChangesForBattle,
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -39,7 +39,7 @@ import { PlayerGender } from "#enums/player-gender";
|
|||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import PokemonData from "#app/system/pokemon-data";
|
import PokemonData from "#app/system/pokemon-data";
|
||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||||
import { trainerConfigs } from "#app/data/trainers/trainer-config";
|
import { trainerConfigs } from "#app/data/trainers/trainer-config";
|
||||||
import { TrainerPartyTemplate } from "#app/data/trainers/TrainerPartyTemplate";
|
import { TrainerPartyTemplate } from "#app/data/trainers/TrainerPartyTemplate";
|
||||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
|
@ -275,15 +275,11 @@ export class TimeOfDayRequirement extends EncounterSceneRequirement {
|
|||||||
|
|
||||||
override meetsRequirement(): boolean {
|
override meetsRequirement(): boolean {
|
||||||
const timeOfDay = globalScene.arena?.getTimeOfDay();
|
const timeOfDay = globalScene.arena?.getTimeOfDay();
|
||||||
if (
|
return !(
|
||||||
!isNullOrUndefined(timeOfDay) &&
|
!isNullOrUndefined(timeOfDay) &&
|
||||||
this.requiredTimeOfDay?.length > 0 &&
|
this.requiredTimeOfDay?.length > 0 &&
|
||||||
!this.requiredTimeOfDay.includes(timeOfDay)
|
!this.requiredTimeOfDay.includes(timeOfDay)
|
||||||
) {
|
);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override getDialogueToken(_pokemon?: PlayerPokemon): [string, string] {
|
override getDialogueToken(_pokemon?: PlayerPokemon): [string, string] {
|
||||||
@ -301,15 +297,11 @@ export class WeatherRequirement extends EncounterSceneRequirement {
|
|||||||
|
|
||||||
override meetsRequirement(): boolean {
|
override meetsRequirement(): boolean {
|
||||||
const currentWeather = globalScene.arena.weather?.weatherType;
|
const currentWeather = globalScene.arena.weather?.weatherType;
|
||||||
if (
|
return !(
|
||||||
!isNullOrUndefined(currentWeather) &&
|
!isNullOrUndefined(currentWeather) &&
|
||||||
this.requiredWeather?.length > 0 &&
|
this.requiredWeather?.length > 0 &&
|
||||||
!this.requiredWeather.includes(currentWeather!)
|
!this.requiredWeather.includes(currentWeather!)
|
||||||
) {
|
);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override getDialogueToken(_pokemon?: PlayerPokemon): [string, string] {
|
override getDialogueToken(_pokemon?: PlayerPokemon): [string, string] {
|
||||||
@ -803,7 +795,7 @@ export class CanFormChangeWithItemRequirement extends EncounterPokemonRequiremen
|
|||||||
}
|
}
|
||||||
|
|
||||||
filterByForm(pokemon, formChangeItem) {
|
filterByForm(pokemon, formChangeItem) {
|
||||||
if (
|
return (
|
||||||
pokemonFormChanges.hasOwnProperty(pokemon.species.speciesId) &&
|
pokemonFormChanges.hasOwnProperty(pokemon.species.speciesId) &&
|
||||||
// Get all form changes for this species with an item trigger, including any compound triggers
|
// Get all form changes for this species with an item trigger, including any compound triggers
|
||||||
pokemonFormChanges[pokemon.species.speciesId]
|
pokemonFormChanges[pokemon.species.speciesId]
|
||||||
@ -812,10 +804,7 @@ export class CanFormChangeWithItemRequirement extends EncounterPokemonRequiremen
|
|||||||
.flatMap(fc => fc.findTrigger(SpeciesFormChangeItemTrigger) as SpeciesFormChangeItemTrigger)
|
.flatMap(fc => fc.findTrigger(SpeciesFormChangeItemTrigger) as SpeciesFormChangeItemTrigger)
|
||||||
.flatMap(fc => fc.item)
|
.flatMap(fc => fc.item)
|
||||||
.includes(formChangeItem)
|
.includes(formChangeItem)
|
||||||
) {
|
);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||||
@ -873,17 +862,15 @@ export class CanEvolveWithItemRequirement extends EncounterPokemonRequirement {
|
|||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
|
return (
|
||||||
pokemon.isFusion() &&
|
pokemon.isFusion() &&
|
||||||
pokemonEvolutions.hasOwnProperty(pokemon.fusionSpecies.speciesId) &&
|
pokemonEvolutions.hasOwnProperty(pokemon.fusionSpecies.speciesId) &&
|
||||||
pokemonEvolutions[pokemon.fusionSpecies.speciesId].filter(
|
pokemonEvolutions[pokemon.fusionSpecies.speciesId].filter(
|
||||||
e => e.item === evolutionItem && (!e.condition || e.condition.predicate(pokemon)),
|
e => e.item === evolutionItem && (!e.condition || e.condition.predicate(pokemon)),
|
||||||
).length &&
|
).length &&
|
||||||
pokemon.getFusionFormKey() !== SpeciesFormKey.GIGANTAMAX
|
pokemon.getFusionFormKey() !== SpeciesFormKey.GIGANTAMAX
|
||||||
) {
|
);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||||
|
@ -51,7 +51,7 @@ function getTextWithDialogueTokens(keyOrString: string): string | null {
|
|||||||
*/
|
*/
|
||||||
export function queueEncounterMessage(contentKey: string): void {
|
export function queueEncounterMessage(contentKey: string): void {
|
||||||
const text: string | null = getEncounterText(contentKey);
|
const text: string | null = getEncounterText(contentKey);
|
||||||
globalScene.queueMessage(text ?? "", null, true);
|
globalScene.phaseManager.queueMessage(text ?? "", null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,12 +20,6 @@ import {
|
|||||||
modifierTypes,
|
modifierTypes,
|
||||||
regenerateModifierPoolThresholds,
|
regenerateModifierPoolThresholds,
|
||||||
} from "#app/modifier/modifier-type";
|
} from "#app/modifier/modifier-type";
|
||||||
import {
|
|
||||||
MysteryEncounterBattlePhase,
|
|
||||||
MysteryEncounterBattleStartCleanupPhase,
|
|
||||||
MysteryEncounterPhase,
|
|
||||||
MysteryEncounterRewardsPhase,
|
|
||||||
} from "#app/phases/mystery-encounter-phases";
|
|
||||||
import type PokemonData from "#app/system/pokemon-data";
|
import type PokemonData from "#app/system/pokemon-data";
|
||||||
import type { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import type { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import type { PartyOption, PokemonSelectFilter } from "#app/ui/party-ui-handler";
|
import type { PartyOption, PokemonSelectFilter } from "#app/ui/party-ui-handler";
|
||||||
@ -50,14 +44,7 @@ import type PokemonSpecies from "#app/data/pokemon-species";
|
|||||||
import type { IEggOptions } from "#app/data/egg";
|
import type { IEggOptions } from "#app/data/egg";
|
||||||
import { Egg } from "#app/data/egg";
|
import { Egg } from "#app/data/egg";
|
||||||
import type { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
import type { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||||
import { MovePhase } from "#app/phases/move-phase";
|
|
||||||
import { EggLapsePhase } from "#app/phases/egg-lapse-phase";
|
|
||||||
import { TrainerVictoryPhase } from "#app/phases/trainer-victory-phase";
|
|
||||||
import { BattleEndPhase } from "#app/phases/battle-end-phase";
|
|
||||||
import { GameOverPhase } from "#app/phases/game-over-phase";
|
|
||||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
|
||||||
import { PartyExpPhase } from "#app/phases/party-exp-phase";
|
|
||||||
import type { Variant } from "#app/sprites/variant";
|
import type { Variant } from "#app/sprites/variant";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
@ -428,7 +415,7 @@ export async function initBattleWithEnemyConfig(partyConfig: EnemyPartyConfig):
|
|||||||
console.log("Moveset:", moveset);
|
console.log("Moveset:", moveset);
|
||||||
});
|
});
|
||||||
|
|
||||||
globalScene.pushPhase(new MysteryEncounterBattlePhase(partyConfig.disableSwitch));
|
globalScene.phaseManager.pushNew("MysteryEncounterBattlePhase", partyConfig.disableSwitch);
|
||||||
|
|
||||||
await Promise.all(loadEnemyAssets);
|
await Promise.all(loadEnemyAssets);
|
||||||
battle.enemyParty.forEach((enemyPokemon_2, e_1) => {
|
battle.enemyParty.forEach((enemyPokemon_2, e_1) => {
|
||||||
@ -480,7 +467,7 @@ export function updatePlayerMoney(changeValue: number, playSound = true, showMes
|
|||||||
}
|
}
|
||||||
if (showMessage) {
|
if (showMessage) {
|
||||||
if (changeValue < 0) {
|
if (changeValue < 0) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("mysteryEncounterMessages:paid_money", {
|
i18next.t("mysteryEncounterMessages:paid_money", {
|
||||||
amount: -changeValue,
|
amount: -changeValue,
|
||||||
}),
|
}),
|
||||||
@ -488,7 +475,7 @@ export function updatePlayerMoney(changeValue: number, playSound = true, showMes
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("mysteryEncounterMessages:receive_money", {
|
i18next.t("mysteryEncounterMessages:receive_money", {
|
||||||
amount: changeValue,
|
amount: changeValue,
|
||||||
}),
|
}),
|
||||||
@ -767,9 +754,9 @@ export function setEncounterRewards(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (customShopRewards) {
|
if (customShopRewards) {
|
||||||
globalScene.unshiftPhase(new SelectModifierPhase(0, undefined, customShopRewards));
|
globalScene.phaseManager.unshiftNew("SelectModifierPhase", 0, undefined, customShopRewards);
|
||||||
} else {
|
} else {
|
||||||
globalScene.tryRemovePhase(p => p instanceof SelectModifierPhase);
|
globalScene.phaseManager.tryRemovePhase(p => p.is("MysteryEncounterRewardsPhase"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eggRewards) {
|
if (eggRewards) {
|
||||||
@ -807,7 +794,7 @@ export function setEncounterExp(participantId: number | number[], baseExpValue:
|
|||||||
const participantIds = Array.isArray(participantId) ? participantId : [participantId];
|
const participantIds = Array.isArray(participantId) ? participantId : [participantId];
|
||||||
|
|
||||||
globalScene.currentBattle.mysteryEncounter!.doEncounterExp = () => {
|
globalScene.currentBattle.mysteryEncounter!.doEncounterExp = () => {
|
||||||
globalScene.unshiftPhase(new PartyExpPhase(baseExpValue, useWaveIndex, new Set(participantIds)));
|
globalScene.phaseManager.unshiftNew("PartyExpPhase", baseExpValue, useWaveIndex, new Set(participantIds));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@ -829,7 +816,7 @@ export class OptionSelectSettings {
|
|||||||
* @param optionSelectSettings
|
* @param optionSelectSettings
|
||||||
*/
|
*/
|
||||||
export function initSubsequentOptionSelect(optionSelectSettings: OptionSelectSettings) {
|
export function initSubsequentOptionSelect(optionSelectSettings: OptionSelectSettings) {
|
||||||
globalScene.pushPhase(new MysteryEncounterPhase(optionSelectSettings));
|
globalScene.phaseManager.pushNew("MysteryEncounterPhase", optionSelectSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -843,8 +830,8 @@ export function leaveEncounterWithoutBattle(
|
|||||||
encounterMode: MysteryEncounterMode = MysteryEncounterMode.NO_BATTLE,
|
encounterMode: MysteryEncounterMode = MysteryEncounterMode.NO_BATTLE,
|
||||||
) {
|
) {
|
||||||
globalScene.currentBattle.mysteryEncounter!.encounterMode = encounterMode;
|
globalScene.currentBattle.mysteryEncounter!.encounterMode = encounterMode;
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.clearPhaseQueueSplice();
|
globalScene.phaseManager.clearPhaseQueueSplice();
|
||||||
handleMysteryEncounterVictory(addHealPhase);
|
handleMysteryEncounterVictory(addHealPhase);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -857,8 +844,8 @@ export function handleMysteryEncounterVictory(addHealPhase = false, doNotContinu
|
|||||||
const allowedPkm = globalScene.getPlayerParty().filter(pkm => pkm.isAllowedInBattle());
|
const allowedPkm = globalScene.getPlayerParty().filter(pkm => pkm.isAllowedInBattle());
|
||||||
|
|
||||||
if (allowedPkm.length === 0) {
|
if (allowedPkm.length === 0) {
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.unshiftPhase(new GameOverPhase());
|
globalScene.phaseManager.unshiftNew("GameOverPhase");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -869,8 +856,8 @@ export function handleMysteryEncounterVictory(addHealPhase = false, doNotContinu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (encounter.encounterMode === MysteryEncounterMode.NO_BATTLE) {
|
if (encounter.encounterMode === MysteryEncounterMode.NO_BATTLE) {
|
||||||
globalScene.pushPhase(new MysteryEncounterRewardsPhase(addHealPhase));
|
globalScene.phaseManager.pushNew("MysteryEncounterRewardsPhase", addHealPhase);
|
||||||
globalScene.pushPhase(new EggLapsePhase());
|
globalScene.phaseManager.pushNew("EggLapsePhase");
|
||||||
} else if (
|
} else if (
|
||||||
!globalScene
|
!globalScene
|
||||||
.getEnemyParty()
|
.getEnemyParty()
|
||||||
@ -878,15 +865,15 @@ export function handleMysteryEncounterVictory(addHealPhase = false, doNotContinu
|
|||||||
encounter.encounterMode !== MysteryEncounterMode.TRAINER_BATTLE ? p.isOnField() : !p?.isFainted(true),
|
encounter.encounterMode !== MysteryEncounterMode.TRAINER_BATTLE ? p.isOnField() : !p?.isFainted(true),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
globalScene.pushPhase(new BattleEndPhase(true));
|
globalScene.phaseManager.pushNew("BattleEndPhase", true);
|
||||||
if (encounter.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
if (encounter.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
||||||
globalScene.pushPhase(new TrainerVictoryPhase());
|
globalScene.phaseManager.pushNew("TrainerVictoryPhase");
|
||||||
}
|
}
|
||||||
if (globalScene.gameMode.isEndless || !globalScene.gameMode.isWaveFinal(globalScene.currentBattle.waveIndex)) {
|
if (globalScene.gameMode.isEndless || !globalScene.gameMode.isWaveFinal(globalScene.currentBattle.waveIndex)) {
|
||||||
globalScene.pushPhase(new MysteryEncounterRewardsPhase(addHealPhase));
|
globalScene.phaseManager.pushNew("MysteryEncounterRewardsPhase", addHealPhase);
|
||||||
if (!encounter.doContinueEncounter) {
|
if (!encounter.doContinueEncounter) {
|
||||||
// Only lapse eggs once for multi-battle encounters
|
// Only lapse eggs once for multi-battle encounters
|
||||||
globalScene.pushPhase(new EggLapsePhase());
|
globalScene.phaseManager.pushNew("EggLapsePhase");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -900,8 +887,8 @@ export function handleMysteryEncounterBattleFailed(addHealPhase = false, doNotCo
|
|||||||
const allowedPkm = globalScene.getPlayerParty().filter(pkm => pkm.isAllowedInBattle());
|
const allowedPkm = globalScene.getPlayerParty().filter(pkm => pkm.isAllowedInBattle());
|
||||||
|
|
||||||
if (allowedPkm.length === 0) {
|
if (allowedPkm.length === 0) {
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.unshiftPhase(new GameOverPhase());
|
globalScene.phaseManager.unshiftNew("GameOverPhase");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -912,14 +899,14 @@ export function handleMysteryEncounterBattleFailed(addHealPhase = false, doNotCo
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (encounter.encounterMode !== MysteryEncounterMode.NO_BATTLE) {
|
if (encounter.encounterMode !== MysteryEncounterMode.NO_BATTLE) {
|
||||||
globalScene.pushPhase(new BattleEndPhase(false));
|
globalScene.phaseManager.pushNew("BattleEndPhase", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.pushPhase(new MysteryEncounterRewardsPhase(addHealPhase));
|
globalScene.phaseManager.pushNew("MysteryEncounterRewardsPhase", addHealPhase);
|
||||||
|
|
||||||
if (!encounter.doContinueEncounter) {
|
if (!encounter.doContinueEncounter) {
|
||||||
// Only lapse eggs once for multi-battle encounters
|
// Only lapse eggs once for multi-battle encounters
|
||||||
globalScene.pushPhase(new EggLapsePhase());
|
globalScene.phaseManager.pushNew("EggLapsePhase");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1004,12 +991,19 @@ export function handleMysteryEncounterBattleStartEffects() {
|
|||||||
} else {
|
} else {
|
||||||
source = globalScene.getEnemyField()[0];
|
source = globalScene.getEnemyField()[0];
|
||||||
}
|
}
|
||||||
// @ts-ignore: source cannot be undefined
|
globalScene.phaseManager.pushNew(
|
||||||
globalScene.pushPhase(new MovePhase(source, effect.targets, effect.move, effect.followUp, effect.ignorePp));
|
"MovePhase",
|
||||||
|
// @ts-expect-error: source is guaranteed to be defined
|
||||||
|
source,
|
||||||
|
effect.targets,
|
||||||
|
effect.move,
|
||||||
|
effect.followUp,
|
||||||
|
effect.ignorePp,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Pseudo turn end phase to reset flinch states, Endure, etc.
|
// Pseudo turn end phase to reset flinch states, Endure, etc.
|
||||||
globalScene.pushPhase(new MysteryEncounterBattleStartCleanupPhase());
|
globalScene.phaseManager.pushNew("MysteryEncounterBattleStartCleanupPhase");
|
||||||
|
|
||||||
encounter.startOfBattleEffectsComplete = true;
|
encounter.startOfBattleEffectsComplete = true;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,6 @@ import type { PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
|||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { Gender } from "#app/data/gender";
|
import { Gender } from "#app/data/gender";
|
||||||
import type { PermanentStat } from "#enums/stat";
|
import type { PermanentStat } from "#enums/stat";
|
||||||
import { VictoryPhase } from "#app/phases/victory-phase";
|
|
||||||
import { SummaryUiMode } from "#app/ui/summary-ui-handler";
|
import { SummaryUiMode } from "#app/ui/summary-ui-handler";
|
||||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import type { AbilityId } from "#enums/ability-id";
|
import type { AbilityId } from "#enums/ability-id";
|
||||||
@ -675,7 +674,7 @@ export async function catchPokemon(
|
|||||||
if (!globalScene.getEnemyParty().some(p => p.id === pokemon.id)) {
|
if (!globalScene.getEnemyParty().some(p => p.id === pokemon.id)) {
|
||||||
globalScene.getEnemyParty().push(pokemon);
|
globalScene.getEnemyParty().push(pokemon);
|
||||||
}
|
}
|
||||||
globalScene.unshiftPhase(new VictoryPhase(pokemon.id, true));
|
globalScene.phaseManager.unshiftNew("VictoryPhase", pokemon.id, true);
|
||||||
globalScene.pokemonInfoContainer.hide();
|
globalScene.pokemonInfoContainer.hide();
|
||||||
if (pokeball) {
|
if (pokeball) {
|
||||||
removePb(pokeball);
|
removePb(pokeball);
|
||||||
|
@ -186,11 +186,7 @@ export class SpeciesFormChange {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.trigger.canChange(pokemon)) {
|
return this.trigger.canChange(pokemon);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
findTrigger(triggerType: Constructor<SpeciesFormChangeTrigger>): SpeciesFormChangeTrigger | nil {
|
findTrigger(triggerType: Constructor<SpeciesFormChangeTrigger>): SpeciesFormChangeTrigger | nil {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { Localizable } from "#app/interfaces/locales";
|
import type { Localizable } from "#app/@types/locales";
|
||||||
import { AbilityId } from "#enums/ability-id";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
@ -8,7 +8,14 @@ import type { AnySound } from "#app/battle-scene";
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { GameMode } from "#app/game-mode";
|
import type { GameMode } from "#app/game-mode";
|
||||||
import { DexAttr, type StarterMoveset } from "#app/system/game-data";
|
import { DexAttr, type StarterMoveset } from "#app/system/game-data";
|
||||||
import { isNullOrUndefined, capitalizeString, randSeedInt, randSeedGauss, randSeedItem } from "#app/utils/common";
|
import {
|
||||||
|
isNullOrUndefined,
|
||||||
|
capitalizeString,
|
||||||
|
randSeedInt,
|
||||||
|
randSeedGauss,
|
||||||
|
randSeedItem,
|
||||||
|
randSeedFloat,
|
||||||
|
} from "#app/utils/common";
|
||||||
import { uncatchableSpecies } from "#app/data/balance/biomes";
|
import { uncatchableSpecies } from "#app/data/balance/biomes";
|
||||||
import { speciesEggMoves } from "#app/data/balance/egg-moves";
|
import { speciesEggMoves } from "#app/data/balance/egg-moves";
|
||||||
import { GrowthRate } from "#app/data/exp";
|
import { GrowthRate } from "#app/data/exp";
|
||||||
@ -750,7 +757,7 @@ export abstract class PokemonSpeciesForm {
|
|||||||
let paletteColors: Map<number, number> = new Map();
|
let paletteColors: Map<number, number> = new Map();
|
||||||
|
|
||||||
const originalRandom = Math.random;
|
const originalRandom = Math.random;
|
||||||
Math.random = Phaser.Math.RND.frac;
|
Math.random = randSeedFloat;
|
||||||
|
|
||||||
globalScene.executeWithSeedOffset(
|
globalScene.executeWithSeedOffset(
|
||||||
() => {
|
() => {
|
||||||
@ -773,6 +780,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||||||
readonly mythical: boolean;
|
readonly mythical: boolean;
|
||||||
readonly species: string;
|
readonly species: string;
|
||||||
readonly growthRate: GrowthRate;
|
readonly growthRate: GrowthRate;
|
||||||
|
/** The chance (as a decimal) for this Species to be male, or `null` for genderless species */
|
||||||
readonly malePercent: number | null;
|
readonly malePercent: number | null;
|
||||||
readonly genderDiffs: boolean;
|
readonly genderDiffs: boolean;
|
||||||
readonly canChangeForm: boolean;
|
readonly canChangeForm: boolean;
|
||||||
@ -889,7 +897,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||||||
return Gender.GENDERLESS;
|
return Gender.GENDERLESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Phaser.Math.RND.realInRange(0, 1) <= this.malePercent) {
|
if (randSeedFloat() <= this.malePercent) {
|
||||||
return Gender.MALE;
|
return Gender.MALE;
|
||||||
}
|
}
|
||||||
return Gender.FEMALE;
|
return Gender.FEMALE;
|
||||||
@ -1138,7 +1146,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noEvolutionChance === 1 || Phaser.Math.RND.realInRange(0, 1) < noEvolutionChance) {
|
if (noEvolutionChance === 1 || randSeedFloat() <= noEvolutionChance) {
|
||||||
return this.speciesId;
|
return this.speciesId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1281,10 +1289,6 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
isObtainable() {
|
|
||||||
return super.isObtainable();
|
|
||||||
}
|
|
||||||
|
|
||||||
hasVariants() {
|
hasVariants() {
|
||||||
let variantDataIndex: string | number = this.speciesId;
|
let variantDataIndex: string | number = this.speciesId;
|
||||||
if (this.forms.length > 0) {
|
if (this.forms.length > 0) {
|
||||||
@ -2026,9 +2030,9 @@ export function initSpecies() {
|
|||||||
new PokemonForm("Normal", "", PokemonType.GROUND, null, 3.5, 950, AbilityId.DROUGHT, AbilityId.NONE, AbilityId.NONE, 670, 100, 150, 140, 100, 90, 90, 3, 0, 335, false, null, true),
|
new PokemonForm("Normal", "", PokemonType.GROUND, null, 3.5, 950, AbilityId.DROUGHT, AbilityId.NONE, AbilityId.NONE, 670, 100, 150, 140, 100, 90, 90, 3, 0, 335, false, null, true),
|
||||||
new PokemonForm("Primal", "primal", PokemonType.GROUND, PokemonType.FIRE, 5, 999.7, AbilityId.DESOLATE_LAND, AbilityId.NONE, AbilityId.NONE, 770, 100, 180, 160, 150, 90, 90, 3, 0, 335),
|
new PokemonForm("Primal", "primal", PokemonType.GROUND, PokemonType.FIRE, 5, 999.7, AbilityId.DESOLATE_LAND, AbilityId.NONE, AbilityId.NONE, 770, 100, 180, 160, 150, 90, 90, 3, 0, 335),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(SpeciesId.RAYQUAZA, 3, false, true, false, "Sky High Pokémon", PokemonType.DRAGON, PokemonType.FLYING, 7, 206.5, AbilityId.AIR_LOCK, AbilityId.NONE, AbilityId.NONE, 680, 105, 150, 90, 150, 90, 95, 45, 0, 340, GrowthRate.SLOW, null, false, true,
|
new PokemonSpecies(SpeciesId.RAYQUAZA, 3, false, true, false, "Sky High Pokémon", PokemonType.DRAGON, PokemonType.FLYING, 7, 206.5, AbilityId.AIR_LOCK, AbilityId.NONE, AbilityId.NONE, 680, 105, 150, 90, 150, 90, 95, 3, 0, 340, GrowthRate.SLOW, null, false, true,
|
||||||
new PokemonForm("Normal", "", PokemonType.DRAGON, PokemonType.FLYING, 7, 206.5, AbilityId.AIR_LOCK, AbilityId.NONE, AbilityId.NONE, 680, 105, 150, 90, 150, 90, 95, 45, 0, 340, false, null, true),
|
new PokemonForm("Normal", "", PokemonType.DRAGON, PokemonType.FLYING, 7, 206.5, AbilityId.AIR_LOCK, AbilityId.NONE, AbilityId.NONE, 680, 105, 150, 90, 150, 90, 95, 3, 0, 340, false, null, true),
|
||||||
new PokemonForm("Mega", SpeciesFormKey.MEGA, PokemonType.DRAGON, PokemonType.FLYING, 10.8, 392, AbilityId.DELTA_STREAM, AbilityId.NONE, AbilityId.NONE, 780, 105, 180, 100, 180, 100, 115, 45, 0, 340),
|
new PokemonForm("Mega", SpeciesFormKey.MEGA, PokemonType.DRAGON, PokemonType.FLYING, 10.8, 392, AbilityId.DELTA_STREAM, AbilityId.NONE, AbilityId.NONE, 780, 105, 180, 100, 180, 100, 115, 3, 0, 340),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(SpeciesId.JIRACHI, 3, false, false, true, "Wish Pokémon", PokemonType.STEEL, PokemonType.PSYCHIC, 0.3, 1.1, AbilityId.SERENE_GRACE, AbilityId.NONE, AbilityId.NONE, 600, 100, 100, 100, 100, 100, 100, 3, 100, 300, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.JIRACHI, 3, false, false, true, "Wish Pokémon", PokemonType.STEEL, PokemonType.PSYCHIC, 0.3, 1.1, AbilityId.SERENE_GRACE, AbilityId.NONE, AbilityId.NONE, 600, 100, 100, 100, 100, 100, 100, 3, 100, 300, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(SpeciesId.DEOXYS, 3, false, false, true, "DNA Pokémon", PokemonType.PSYCHIC, null, 1.7, 60.8, AbilityId.PRESSURE, AbilityId.NONE, AbilityId.NONE, 600, 50, 150, 50, 150, 50, 150, 3, 0, 300, GrowthRate.SLOW, null, false, true,
|
new PokemonSpecies(SpeciesId.DEOXYS, 3, false, false, true, "DNA Pokémon", PokemonType.PSYCHIC, null, 1.7, 60.8, AbilityId.PRESSURE, AbilityId.NONE, AbilityId.NONE, 600, 50, 150, 50, 150, 50, 150, 3, 0, 300, GrowthRate.SLOW, null, false, true,
|
||||||
@ -2274,10 +2278,10 @@ export function initSpecies() {
|
|||||||
new PokemonSpecies(SpeciesId.WHIMSICOTT, 5, false, false, false, "Windveiled Pokémon", PokemonType.GRASS, PokemonType.FAIRY, 0.7, 6.6, AbilityId.PRANKSTER, AbilityId.INFILTRATOR, AbilityId.CHLOROPHYLL, 480, 60, 67, 85, 77, 75, 116, 75, 50, 168, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(SpeciesId.WHIMSICOTT, 5, false, false, false, "Windveiled Pokémon", PokemonType.GRASS, PokemonType.FAIRY, 0.7, 6.6, AbilityId.PRANKSTER, AbilityId.INFILTRATOR, AbilityId.CHLOROPHYLL, 480, 60, 67, 85, 77, 75, 116, 75, 50, 168, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
new PokemonSpecies(SpeciesId.PETILIL, 5, false, false, false, "Bulb Pokémon", PokemonType.GRASS, null, 0.5, 6.6, AbilityId.CHLOROPHYLL, AbilityId.OWN_TEMPO, AbilityId.LEAF_GUARD, 280, 45, 35, 50, 70, 50, 30, 190, 50, 56, GrowthRate.MEDIUM_FAST, 0, false),
|
new PokemonSpecies(SpeciesId.PETILIL, 5, false, false, false, "Bulb Pokémon", PokemonType.GRASS, null, 0.5, 6.6, AbilityId.CHLOROPHYLL, AbilityId.OWN_TEMPO, AbilityId.LEAF_GUARD, 280, 45, 35, 50, 70, 50, 30, 190, 50, 56, GrowthRate.MEDIUM_FAST, 0, false),
|
||||||
new PokemonSpecies(SpeciesId.LILLIGANT, 5, false, false, false, "Flowering Pokémon", PokemonType.GRASS, null, 1.1, 16.3, AbilityId.CHLOROPHYLL, AbilityId.OWN_TEMPO, AbilityId.LEAF_GUARD, 480, 70, 60, 75, 110, 75, 90, 75, 50, 168, GrowthRate.MEDIUM_FAST, 0, false),
|
new PokemonSpecies(SpeciesId.LILLIGANT, 5, false, false, false, "Flowering Pokémon", PokemonType.GRASS, null, 1.1, 16.3, AbilityId.CHLOROPHYLL, AbilityId.OWN_TEMPO, AbilityId.LEAF_GUARD, 480, 70, 60, 75, 110, 75, 90, 75, 50, 168, GrowthRate.MEDIUM_FAST, 0, false),
|
||||||
new PokemonSpecies(SpeciesId.BASCULIN, 5, false, false, false, "Hostile Pokémon", PokemonType.WATER, null, 1, 18, AbilityId.RECKLESS, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 25, 50, 161, GrowthRate.MEDIUM_FAST, 50, false, false,
|
new PokemonSpecies(SpeciesId.BASCULIN, 5, false, false, false, "Hostile Pokémon", PokemonType.WATER, null, 1, 18, AbilityId.RECKLESS, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 190, 50, 161, GrowthRate.MEDIUM_FAST, 50, false, false,
|
||||||
new PokemonForm("Red-Striped Form", "red-striped", PokemonType.WATER, null, 1, 18, AbilityId.RECKLESS, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 25, 50, 161, false, null, true),
|
new PokemonForm("Red-Striped Form", "red-striped", PokemonType.WATER, null, 1, 18, AbilityId.RECKLESS, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 190, 50, 161, false, null, true),
|
||||||
new PokemonForm("Blue-Striped Form", "blue-striped", PokemonType.WATER, null, 1, 18, AbilityId.ROCK_HEAD, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 25, 50, 161, false, null, true),
|
new PokemonForm("Blue-Striped Form", "blue-striped", PokemonType.WATER, null, 1, 18, AbilityId.ROCK_HEAD, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 190, 50, 161, false, null, true),
|
||||||
new PokemonForm("White-Striped Form", "white-striped", PokemonType.WATER, null, 1, 18, AbilityId.RATTLED, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 25, 50, 161, false, null, true),
|
new PokemonForm("White-Striped Form", "white-striped", PokemonType.WATER, null, 1, 18, AbilityId.RATTLED, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 190, 50, 161, false, null, true),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(SpeciesId.SANDILE, 5, false, false, false, "Desert Croc Pokémon", PokemonType.GROUND, PokemonType.DARK, 0.7, 15.2, AbilityId.INTIMIDATE, AbilityId.MOXIE, AbilityId.ANGER_POINT, 292, 50, 72, 35, 35, 35, 65, 180, 50, 58, GrowthRate.MEDIUM_SLOW, 50, false),
|
new PokemonSpecies(SpeciesId.SANDILE, 5, false, false, false, "Desert Croc Pokémon", PokemonType.GROUND, PokemonType.DARK, 0.7, 15.2, AbilityId.INTIMIDATE, AbilityId.MOXIE, AbilityId.ANGER_POINT, 292, 50, 72, 35, 35, 35, 65, 180, 50, 58, GrowthRate.MEDIUM_SLOW, 50, false),
|
||||||
new PokemonSpecies(SpeciesId.KROKOROK, 5, false, false, false, "Desert Croc Pokémon", PokemonType.GROUND, PokemonType.DARK, 1, 33.4, AbilityId.INTIMIDATE, AbilityId.MOXIE, AbilityId.ANGER_POINT, 351, 60, 82, 45, 45, 45, 74, 90, 50, 123, GrowthRate.MEDIUM_SLOW, 50, false),
|
new PokemonSpecies(SpeciesId.KROKOROK, 5, false, false, false, "Desert Croc Pokémon", PokemonType.GROUND, PokemonType.DARK, 1, 33.4, AbilityId.INTIMIDATE, AbilityId.MOXIE, AbilityId.ANGER_POINT, 351, 60, 82, 45, 45, 45, 74, 90, 50, 123, GrowthRate.MEDIUM_SLOW, 50, false),
|
||||||
@ -2744,10 +2748,10 @@ export function initSpecies() {
|
|||||||
new PokemonSpecies(SpeciesId.TAPU_LELE, 7, true, false, false, "Land Spirit Pokémon", PokemonType.PSYCHIC, PokemonType.FAIRY, 1.2, 18.6, AbilityId.PSYCHIC_SURGE, AbilityId.NONE, AbilityId.TELEPATHY, 570, 70, 85, 75, 130, 115, 95, 3, 50, 285, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.TAPU_LELE, 7, true, false, false, "Land Spirit Pokémon", PokemonType.PSYCHIC, PokemonType.FAIRY, 1.2, 18.6, AbilityId.PSYCHIC_SURGE, AbilityId.NONE, AbilityId.TELEPATHY, 570, 70, 85, 75, 130, 115, 95, 3, 50, 285, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(SpeciesId.TAPU_BULU, 7, true, false, false, "Land Spirit Pokémon", PokemonType.GRASS, PokemonType.FAIRY, 1.9, 45.5, AbilityId.GRASSY_SURGE, AbilityId.NONE, AbilityId.TELEPATHY, 570, 70, 130, 115, 85, 95, 75, 3, 50, 285, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.TAPU_BULU, 7, true, false, false, "Land Spirit Pokémon", PokemonType.GRASS, PokemonType.FAIRY, 1.9, 45.5, AbilityId.GRASSY_SURGE, AbilityId.NONE, AbilityId.TELEPATHY, 570, 70, 130, 115, 85, 95, 75, 3, 50, 285, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(SpeciesId.TAPU_FINI, 7, true, false, false, "Land Spirit Pokémon", PokemonType.WATER, PokemonType.FAIRY, 1.3, 21.2, AbilityId.MISTY_SURGE, AbilityId.NONE, AbilityId.TELEPATHY, 570, 70, 75, 115, 95, 130, 85, 3, 50, 285, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.TAPU_FINI, 7, true, false, false, "Land Spirit Pokémon", PokemonType.WATER, PokemonType.FAIRY, 1.3, 21.2, AbilityId.MISTY_SURGE, AbilityId.NONE, AbilityId.TELEPATHY, 570, 70, 75, 115, 95, 130, 85, 3, 50, 285, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(SpeciesId.COSMOG, 7, true, false, false, "Nebula Pokémon", PokemonType.PSYCHIC, null, 0.2, 0.1, AbilityId.UNAWARE, AbilityId.NONE, AbilityId.NONE, 200, 43, 29, 31, 29, 31, 37, 45, 0, 40, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.COSMOG, 7, true, false, false, "Nebula Pokémon", PokemonType.PSYCHIC, null, 0.2, 0.1, AbilityId.UNAWARE, AbilityId.NONE, AbilityId.NONE, 200, 43, 29, 31, 29, 31, 37, 3, 0, 40, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(SpeciesId.COSMOEM, 7, true, false, false, "Protostar Pokémon", PokemonType.PSYCHIC, null, 0.1, 999.9, AbilityId.STURDY, AbilityId.NONE, AbilityId.NONE, 400, 43, 29, 131, 29, 131, 37, 45, 0, 140, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.COSMOEM, 7, true, false, false, "Protostar Pokémon", PokemonType.PSYCHIC, null, 0.1, 999.9, AbilityId.STURDY, AbilityId.NONE, AbilityId.NONE, 400, 43, 29, 131, 29, 131, 37, 3, 0, 140, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(SpeciesId.SOLGALEO, 7, false, true, false, "Sunne Pokémon", PokemonType.PSYCHIC, PokemonType.STEEL, 3.4, 230, AbilityId.FULL_METAL_BODY, AbilityId.NONE, AbilityId.NONE, 680, 137, 137, 107, 113, 89, 97, 45, 0, 340, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.SOLGALEO, 7, false, true, false, "Sunne Pokémon", PokemonType.PSYCHIC, PokemonType.STEEL, 3.4, 230, AbilityId.FULL_METAL_BODY, AbilityId.NONE, AbilityId.NONE, 680, 137, 137, 107, 113, 89, 97, 3, 0, 340, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(SpeciesId.LUNALA, 7, false, true, false, "Moone Pokémon", PokemonType.PSYCHIC, PokemonType.GHOST, 4, 120, AbilityId.SHADOW_SHIELD, AbilityId.NONE, AbilityId.NONE, 680, 137, 113, 89, 137, 107, 97, 45, 0, 340, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.LUNALA, 7, false, true, false, "Moone Pokémon", PokemonType.PSYCHIC, PokemonType.GHOST, 4, 120, AbilityId.SHADOW_SHIELD, AbilityId.NONE, AbilityId.NONE, 680, 137, 113, 89, 137, 107, 97, 3, 0, 340, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(SpeciesId.NIHILEGO, 7, true, false, false, "Parasite Pokémon", PokemonType.ROCK, PokemonType.POISON, 1.2, 55.5, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 109, 53, 47, 127, 131, 103, 45, 0, 285, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.NIHILEGO, 7, true, false, false, "Parasite Pokémon", PokemonType.ROCK, PokemonType.POISON, 1.2, 55.5, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 109, 53, 47, 127, 131, 103, 45, 0, 285, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(SpeciesId.BUZZWOLE, 7, true, false, false, "Swollen Pokémon", PokemonType.BUG, PokemonType.FIGHTING, 2.4, 333.6, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 107, 139, 139, 53, 53, 79, 45, 0, 285, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.BUZZWOLE, 7, true, false, false, "Swollen Pokémon", PokemonType.BUG, PokemonType.FIGHTING, 2.4, 333.6, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 107, 139, 139, 53, 53, 79, 45, 0, 285, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(SpeciesId.PHEROMOSA, 7, true, false, false, "Lissome Pokémon", PokemonType.BUG, PokemonType.FIGHTING, 1.8, 25, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 71, 137, 37, 137, 37, 151, 45, 0, 285, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.PHEROMOSA, 7, true, false, false, "Lissome Pokémon", PokemonType.BUG, PokemonType.FIGHTING, 1.8, 25, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 71, 137, 37, 137, 37, 151, 45, 0, 285, GrowthRate.SLOW, null, false),
|
||||||
@ -2755,11 +2759,11 @@ export function initSpecies() {
|
|||||||
new PokemonSpecies(SpeciesId.CELESTEELA, 7, true, false, false, "Launch Pokémon", PokemonType.STEEL, PokemonType.FLYING, 9.2, 999.9, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 97, 101, 103, 107, 101, 61, 45, 0, 285, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.CELESTEELA, 7, true, false, false, "Launch Pokémon", PokemonType.STEEL, PokemonType.FLYING, 9.2, 999.9, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 97, 101, 103, 107, 101, 61, 45, 0, 285, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(SpeciesId.KARTANA, 7, true, false, false, "Drawn Sword Pokémon", PokemonType.GRASS, PokemonType.STEEL, 0.3, 0.1, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 59, 181, 131, 59, 31, 109, 45, 0, 285, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.KARTANA, 7, true, false, false, "Drawn Sword Pokémon", PokemonType.GRASS, PokemonType.STEEL, 0.3, 0.1, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 59, 181, 131, 59, 31, 109, 45, 0, 285, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(SpeciesId.GUZZLORD, 7, true, false, false, "Junkivore Pokémon", PokemonType.DARK, PokemonType.DRAGON, 5.5, 888, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 223, 101, 53, 97, 53, 43, 45, 0, 285, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(SpeciesId.GUZZLORD, 7, true, false, false, "Junkivore Pokémon", PokemonType.DARK, PokemonType.DRAGON, 5.5, 888, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 223, 101, 53, 97, 53, 43, 45, 0, 285, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(SpeciesId.NECROZMA, 7, false, true, false, "Prism Pokémon", PokemonType.PSYCHIC, null, 2.4, 230, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 600, 97, 107, 101, 127, 89, 79, 255, 0, 300, GrowthRate.SLOW, null, false, false,
|
new PokemonSpecies(SpeciesId.NECROZMA, 7, false, true, false, "Prism Pokémon", PokemonType.PSYCHIC, null, 2.4, 230, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 600, 97, 107, 101, 127, 89, 79, 3, 0, 300, GrowthRate.SLOW, null, false, false,
|
||||||
new PokemonForm("Normal", "", PokemonType.PSYCHIC, null, 2.4, 230, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 600, 97, 107, 101, 127, 89, 79, 255, 0, 300, false, null, true),
|
new PokemonForm("Normal", "", PokemonType.PSYCHIC, null, 2.4, 230, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 600, 97, 107, 101, 127, 89, 79, 3, 0, 300, false, null, true),
|
||||||
new PokemonForm("Dusk Mane", "dusk-mane", PokemonType.PSYCHIC, PokemonType.STEEL, 3.8, 460, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 680, 97, 157, 127, 113, 109, 77, 255, 0, 340),
|
new PokemonForm("Dusk Mane", "dusk-mane", PokemonType.PSYCHIC, PokemonType.STEEL, 3.8, 460, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 680, 97, 157, 127, 113, 109, 77, 3, 0, 340),
|
||||||
new PokemonForm("Dawn Wings", "dawn-wings", PokemonType.PSYCHIC, PokemonType.GHOST, 4.2, 350, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 680, 97, 113, 109, 157, 127, 77, 255, 0, 340),
|
new PokemonForm("Dawn Wings", "dawn-wings", PokemonType.PSYCHIC, PokemonType.GHOST, 4.2, 350, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 680, 97, 113, 109, 157, 127, 77, 3, 0, 340),
|
||||||
new PokemonForm("Ultra", "ultra", PokemonType.PSYCHIC, PokemonType.DRAGON, 7.5, 230, AbilityId.NEUROFORCE, AbilityId.NONE, AbilityId.NONE, 754, 97, 167, 97, 167, 97, 129, 255, 0, 377),
|
new PokemonForm("Ultra", "ultra", PokemonType.PSYCHIC, PokemonType.DRAGON, 7.5, 230, AbilityId.NEUROFORCE, AbilityId.NONE, AbilityId.NONE, 754, 97, 167, 97, 167, 97, 129, 3, 0, 377),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(SpeciesId.MAGEARNA, 7, false, false, true, "Artificial Pokémon", PokemonType.STEEL, PokemonType.FAIRY, 1, 80.5, AbilityId.SOUL_HEART, AbilityId.NONE, AbilityId.NONE, 600, 80, 95, 115, 130, 115, 65, 3, 0, 300, GrowthRate.SLOW, null, false, false,
|
new PokemonSpecies(SpeciesId.MAGEARNA, 7, false, false, true, "Artificial Pokémon", PokemonType.STEEL, PokemonType.FAIRY, 1, 80.5, AbilityId.SOUL_HEART, AbilityId.NONE, AbilityId.NONE, 600, 80, 95, 115, 130, 115, 65, 3, 0, 300, GrowthRate.SLOW, null, false, false,
|
||||||
new PokemonForm("Normal", "", PokemonType.STEEL, PokemonType.FAIRY, 1, 80.5, AbilityId.SOUL_HEART, AbilityId.NONE, AbilityId.NONE, 600, 80, 95, 115, 130, 115, 65, 3, 0, 300, false, null, true),
|
new PokemonForm("Normal", "", PokemonType.STEEL, PokemonType.FAIRY, 1, 80.5, AbilityId.SOUL_HEART, AbilityId.NONE, AbilityId.NONE, 600, 80, 95, 115, 130, 115, 65, 3, 0, 300, false, null, true),
|
||||||
@ -2968,15 +2972,15 @@ export function initSpecies() {
|
|||||||
new PokemonForm("Ice", "ice", PokemonType.PSYCHIC, PokemonType.ICE, 2.4, 809.1, AbilityId.AS_ONE_GLASTRIER, AbilityId.NONE, AbilityId.NONE, 680, 100, 165, 150, 85, 130, 50, 3, 100, 340),
|
new PokemonForm("Ice", "ice", PokemonType.PSYCHIC, PokemonType.ICE, 2.4, 809.1, AbilityId.AS_ONE_GLASTRIER, AbilityId.NONE, AbilityId.NONE, 680, 100, 165, 150, 85, 130, 50, 3, 100, 340),
|
||||||
new PokemonForm("Shadow", "shadow", PokemonType.PSYCHIC, PokemonType.GHOST, 2.4, 53.6, AbilityId.AS_ONE_SPECTRIER, AbilityId.NONE, AbilityId.NONE, 680, 100, 85, 80, 165, 100, 150, 3, 100, 340),
|
new PokemonForm("Shadow", "shadow", PokemonType.PSYCHIC, PokemonType.GHOST, 2.4, 53.6, AbilityId.AS_ONE_SPECTRIER, AbilityId.NONE, AbilityId.NONE, 680, 100, 85, 80, 165, 100, 150, 3, 100, 340),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(SpeciesId.WYRDEER, 8, false, false, false, "Big Horn Pokémon", PokemonType.NORMAL, PokemonType.PSYCHIC, 1.8, 95.1, AbilityId.INTIMIDATE, AbilityId.FRISK, AbilityId.SAP_SIPPER, 525, 103, 105, 72, 105, 75, 65, 135, 50, 263, GrowthRate.SLOW, 50, false),
|
new PokemonSpecies(SpeciesId.WYRDEER, 8, false, false, false, "Big Horn Pokémon", PokemonType.NORMAL, PokemonType.PSYCHIC, 1.8, 95.1, AbilityId.INTIMIDATE, AbilityId.FRISK, AbilityId.SAP_SIPPER, 525, 103, 105, 72, 105, 75, 65, 45, 50, 263, GrowthRate.SLOW, 50, false),
|
||||||
new PokemonSpecies(SpeciesId.KLEAVOR, 8, false, false, false, "Axe Pokémon", PokemonType.BUG, PokemonType.ROCK, 1.8, 89, AbilityId.SWARM, AbilityId.SHEER_FORCE, AbilityId.SHARPNESS, 500, 70, 135, 95, 45, 70, 85, 115, 50, 175, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(SpeciesId.KLEAVOR, 8, false, false, false, "Axe Pokémon", PokemonType.BUG, PokemonType.ROCK, 1.8, 89, AbilityId.SWARM, AbilityId.SHEER_FORCE, AbilityId.SHARPNESS, 500, 70, 135, 95, 45, 70, 85, 15, 50, 175, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
new PokemonSpecies(SpeciesId.URSALUNA, 8, false, false, false, "Peat Pokémon", PokemonType.GROUND, PokemonType.NORMAL, 2.4, 290, AbilityId.GUTS, AbilityId.BULLETPROOF, AbilityId.UNNERVE, 550, 130, 140, 105, 45, 80, 50, 75, 50, 275, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(SpeciesId.URSALUNA, 8, false, false, false, "Peat Pokémon", PokemonType.GROUND, PokemonType.NORMAL, 2.4, 290, AbilityId.GUTS, AbilityId.BULLETPROOF, AbilityId.UNNERVE, 550, 130, 140, 105, 45, 80, 50, 20, 50, 275, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
new PokemonSpecies(SpeciesId.BASCULEGION, 8, false, false, false, "Big Fish Pokémon", PokemonType.WATER, PokemonType.GHOST, 3, 110, AbilityId.SWIFT_SWIM, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 530, 120, 112, 65, 80, 75, 78, 135, 50, 265, GrowthRate.MEDIUM_FAST, 50, false, false,
|
new PokemonSpecies(SpeciesId.BASCULEGION, 8, false, false, false, "Big Fish Pokémon", PokemonType.WATER, PokemonType.GHOST, 3, 110, AbilityId.SWIFT_SWIM, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 530, 120, 112, 65, 80, 75, 78, 45, 50, 265, GrowthRate.MEDIUM_FAST, 50, false, false,
|
||||||
new PokemonForm("Male", "male", PokemonType.WATER, PokemonType.GHOST, 3, 110, AbilityId.SWIFT_SWIM, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 530, 120, 112, 65, 80, 75, 78, 135, 50, 265, false, "", true),
|
new PokemonForm("Male", "male", PokemonType.WATER, PokemonType.GHOST, 3, 110, AbilityId.SWIFT_SWIM, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 530, 120, 112, 65, 80, 75, 78, 45, 50, 265, false, "", true),
|
||||||
new PokemonForm("Female", "female", PokemonType.WATER, PokemonType.GHOST, 3, 110, AbilityId.SWIFT_SWIM, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 530, 120, 92, 65, 100, 75, 78, 135, 50, 265, false, null, true),
|
new PokemonForm("Female", "female", PokemonType.WATER, PokemonType.GHOST, 3, 110, AbilityId.SWIFT_SWIM, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 530, 120, 92, 65, 100, 75, 78, 45, 50, 265, false, null, true),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(SpeciesId.SNEASLER, 8, false, false, false, "Free Climb Pokémon", PokemonType.FIGHTING, PokemonType.POISON, 1.3, 43, AbilityId.PRESSURE, AbilityId.UNBURDEN, AbilityId.POISON_TOUCH, 510, 80, 130, 60, 40, 80, 120, 135, 50, 102, GrowthRate.MEDIUM_SLOW, 50, false),
|
new PokemonSpecies(SpeciesId.SNEASLER, 8, false, false, false, "Free Climb Pokémon", PokemonType.FIGHTING, PokemonType.POISON, 1.3, 43, AbilityId.PRESSURE, AbilityId.UNBURDEN, AbilityId.POISON_TOUCH, 510, 80, 130, 60, 40, 80, 120, 20, 50, 102, GrowthRate.MEDIUM_SLOW, 50, false),
|
||||||
new PokemonSpecies(SpeciesId.OVERQWIL, 8, false, false, false, "Pin Cluster Pokémon", PokemonType.DARK, PokemonType.POISON, 2.5, 60.5, AbilityId.POISON_POINT, AbilityId.SWIFT_SWIM, AbilityId.INTIMIDATE, 510, 85, 115, 95, 65, 65, 85, 135, 50, 179, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(SpeciesId.OVERQWIL, 8, false, false, false, "Pin Cluster Pokémon", PokemonType.DARK, PokemonType.POISON, 2.5, 60.5, AbilityId.POISON_POINT, AbilityId.SWIFT_SWIM, AbilityId.INTIMIDATE, 510, 85, 115, 95, 65, 65, 85, 45, 50, 179, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
new PokemonSpecies(SpeciesId.ENAMORUS, 8, true, false, false, "Love-Hate Pokémon", PokemonType.FAIRY, PokemonType.FLYING, 1.6, 48, AbilityId.CUTE_CHARM, AbilityId.NONE, AbilityId.CONTRARY, 580, 74, 115, 70, 135, 80, 106, 3, 50, 116, GrowthRate.SLOW, 0, false, true,
|
new PokemonSpecies(SpeciesId.ENAMORUS, 8, true, false, false, "Love-Hate Pokémon", PokemonType.FAIRY, PokemonType.FLYING, 1.6, 48, AbilityId.CUTE_CHARM, AbilityId.NONE, AbilityId.CONTRARY, 580, 74, 115, 70, 135, 80, 106, 3, 50, 116, GrowthRate.SLOW, 0, false, true,
|
||||||
new PokemonForm("Incarnate Forme", "incarnate", PokemonType.FAIRY, PokemonType.FLYING, 1.6, 48, AbilityId.CUTE_CHARM, AbilityId.NONE, AbilityId.CONTRARY, 580, 74, 115, 70, 135, 80, 106, 3, 50, 116, false, null, true),
|
new PokemonForm("Incarnate Forme", "incarnate", PokemonType.FAIRY, PokemonType.FLYING, 1.6, 48, AbilityId.CUTE_CHARM, AbilityId.NONE, AbilityId.CONTRARY, 580, 74, 115, 70, 135, 80, 106, 3, 50, 116, false, null, true),
|
||||||
new PokemonForm("Therian Forme", "therian", PokemonType.FAIRY, PokemonType.FLYING, 1.6, 48, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.OVERCOAT, 580, 74, 115, 110, 135, 100, 46, 3, 50, 116),
|
new PokemonForm("Therian Forme", "therian", PokemonType.FAIRY, PokemonType.FLYING, 1.6, 48, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.OVERCOAT, 580, 74, 115, 110, 135, 100, 46, 3, 50, 116),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { TrainerTierPools } from "#app/data/trainers/typedefs";
|
import type { TrainerTierPools } from "#app/@types/trainer-funcs";
|
||||||
import { TrainerPoolTier } from "#enums/trainer-pool-tier";
|
import { TrainerPoolTier } from "#enums/trainer-pool-tier";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ import type {
|
|||||||
TrainerTierPools,
|
TrainerTierPools,
|
||||||
TrainerConfigs,
|
TrainerConfigs,
|
||||||
PartyMemberFuncs,
|
PartyMemberFuncs,
|
||||||
} from "./typedefs";
|
} from "../../@types/trainer-funcs";
|
||||||
|
|
||||||
/** Minimum BST for Pokemon generated onto the Elite Four's teams */
|
/** Minimum BST for Pokemon generated onto the Elite Four's teams */
|
||||||
const ELITE_FOUR_MINIMUM_BST = 460;
|
const ELITE_FOUR_MINIMUM_BST = 460;
|
||||||
|
17
src/debug.js
17
src/debug.js
@ -1,17 +0,0 @@
|
|||||||
export function getData() {
|
|
||||||
const dataStr = localStorage.getItem("data");
|
|
||||||
if (!dataStr) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return JSON.parse(atob(dataStr), (k, v) =>
|
|
||||||
k.endsWith("Attr") && !["natureAttr", "abilityAttr", "passiveAttr"].includes(k) ? BigInt(v) : v,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getSession() {
|
|
||||||
const sessionStr = localStorage.getItem("sessionData");
|
|
||||||
if (!sessionStr) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return JSON.parse(atob(sessionStr));
|
|
||||||
}
|
|
@ -38,7 +38,6 @@ import { TimeOfDay } from "#enums/time-of-day";
|
|||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { AbilityId } from "#enums/ability-id";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { SpeciesFormChangeRevertWeatherFormTrigger, SpeciesFormChangeWeatherTrigger } from "#app/data/pokemon-forms";
|
import { SpeciesFormChangeRevertWeatherFormTrigger, SpeciesFormChangeWeatherTrigger } from "#app/data/pokemon-forms";
|
||||||
import { CommonAnimPhase } from "#app/phases/common-anim-phase";
|
|
||||||
import { WeatherType } from "#enums/weather-type";
|
import { WeatherType } from "#enums/weather-type";
|
||||||
import { FieldEffectModifier } from "#app/modifier/modifier";
|
import { FieldEffectModifier } from "#app/modifier/modifier";
|
||||||
|
|
||||||
@ -297,8 +296,8 @@ export class Arena {
|
|||||||
*/
|
*/
|
||||||
trySetWeatherOverride(weather: WeatherType): boolean {
|
trySetWeatherOverride(weather: WeatherType): boolean {
|
||||||
this.weather = new Weather(weather, 0);
|
this.weather = new Weather(weather, 0);
|
||||||
globalScene.unshiftPhase(new CommonAnimPhase(undefined, undefined, CommonAnim.SUNNY + (weather - 1)));
|
globalScene.phaseManager.unshiftNew("CommonAnimPhase", undefined, undefined, CommonAnim.SUNNY + (weather - 1));
|
||||||
globalScene.queueMessage(getWeatherStartMessage(weather)!); // TODO: is this bang correct?
|
globalScene.phaseManager.queueMessage(getWeatherStartMessage(weather)!); // TODO: is this bang correct?
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,10 +327,14 @@ export class Arena {
|
|||||||
this.weather?.isImmutable() &&
|
this.weather?.isImmutable() &&
|
||||||
![WeatherType.HARSH_SUN, WeatherType.HEAVY_RAIN, WeatherType.STRONG_WINDS, WeatherType.NONE].includes(weather)
|
![WeatherType.HARSH_SUN, WeatherType.HEAVY_RAIN, WeatherType.STRONG_WINDS, WeatherType.NONE].includes(weather)
|
||||||
) {
|
) {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new CommonAnimPhase(undefined, undefined, CommonAnim.SUNNY + (oldWeatherType - 1), true),
|
"CommonAnimPhase",
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
CommonAnim.SUNNY + (oldWeatherType - 1),
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
globalScene.queueMessage(getLegendaryWeatherContinuesMessage(oldWeatherType)!);
|
globalScene.phaseManager.queueMessage(getLegendaryWeatherContinuesMessage(oldWeatherType)!);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,10 +351,16 @@ export class Arena {
|
|||||||
); // TODO: is this bang correct?
|
); // TODO: is this bang correct?
|
||||||
|
|
||||||
if (this.weather) {
|
if (this.weather) {
|
||||||
globalScene.unshiftPhase(new CommonAnimPhase(undefined, undefined, CommonAnim.SUNNY + (weather - 1), true));
|
globalScene.phaseManager.unshiftNew(
|
||||||
globalScene.queueMessage(getWeatherStartMessage(weather)!); // TODO: is this bang correct?
|
"CommonAnimPhase",
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
CommonAnim.SUNNY + (weather - 1),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
globalScene.phaseManager.queueMessage(getWeatherStartMessage(weather)!); // TODO: is this bang correct?
|
||||||
} else {
|
} else {
|
||||||
globalScene.queueMessage(getWeatherClearMessage(oldWeatherType)!); // TODO: is this bang correct?
|
globalScene.phaseManager.queueMessage(getWeatherClearMessage(oldWeatherType)!); // TODO: is this bang correct?
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene
|
globalScene
|
||||||
@ -431,11 +440,16 @@ export class Arena {
|
|||||||
|
|
||||||
if (this.terrain) {
|
if (this.terrain) {
|
||||||
if (!ignoreAnim) {
|
if (!ignoreAnim) {
|
||||||
globalScene.unshiftPhase(new CommonAnimPhase(undefined, undefined, CommonAnim.MISTY_TERRAIN + (terrain - 1)));
|
globalScene.phaseManager.unshiftNew(
|
||||||
|
"CommonAnimPhase",
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
CommonAnim.MISTY_TERRAIN + (terrain - 1),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
globalScene.queueMessage(getTerrainStartMessage(terrain)!); // TODO: is this bang correct?
|
globalScene.phaseManager.queueMessage(getTerrainStartMessage(terrain)!); // TODO: is this bang correct?
|
||||||
} else {
|
} else {
|
||||||
globalScene.queueMessage(getTerrainClearMessage(oldTerrainType)!); // TODO: is this bang correct?
|
globalScene.phaseManager.queueMessage(getTerrainClearMessage(oldTerrainType)!); // TODO: is this bang correct?
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene
|
globalScene
|
||||||
|
@ -65,6 +65,7 @@ import {
|
|||||||
rgbToHsv,
|
rgbToHsv,
|
||||||
deltaRgb,
|
deltaRgb,
|
||||||
isBetween,
|
isBetween,
|
||||||
|
randSeedFloat,
|
||||||
type nil,
|
type nil,
|
||||||
type Constructor,
|
type Constructor,
|
||||||
randSeedIntRange,
|
randSeedIntRange,
|
||||||
@ -229,14 +230,6 @@ import { BiomeId } from "#enums/biome-id";
|
|||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
|
|
||||||
import { FaintPhase } from "#app/phases/faint-phase";
|
|
||||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
|
||||||
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
|
||||||
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
|
||||||
import { ObtainStatusEffectPhase } from "#app/phases/obtain-status-effect-phase";
|
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
|
|
||||||
import { Challenges } from "#enums/challenges";
|
import { Challenges } from "#enums/challenges";
|
||||||
import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
||||||
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
|
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
|
||||||
@ -256,7 +249,6 @@ import { doShinySparkleAnim } from "#app/field/anims";
|
|||||||
import { MoveFlags } from "#enums/MoveFlags";
|
import { MoveFlags } from "#enums/MoveFlags";
|
||||||
import { timedEventManager } from "#app/global-event-manager";
|
import { timedEventManager } from "#app/global-event-manager";
|
||||||
import { loadMoveAnimations } from "#app/sprites/pokemon-asset-loader";
|
import { loadMoveAnimations } from "#app/sprites/pokemon-asset-loader";
|
||||||
import { ResetStatusPhase } from "#app/phases/reset-status-phase";
|
|
||||||
|
|
||||||
export enum LearnMoveSituation {
|
export enum LearnMoveSituation {
|
||||||
MISC,
|
MISC,
|
||||||
@ -504,7 +496,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
if (level > 1) {
|
if (level > 1) {
|
||||||
const fused = new BooleanHolder(globalScene.gameMode.isSplicedOnly);
|
const fused = new BooleanHolder(globalScene.gameMode.isSplicedOnly);
|
||||||
if (!fused.value && !this.isPlayer() && !this.hasTrainer()) {
|
if (!fused.value && this.isEnemy() && !this.hasTrainer()) {
|
||||||
globalScene.applyModifier(EnemyFusionChanceModifier, false, fused);
|
globalScene.applyModifier(EnemyFusionChanceModifier, false, fused);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -789,7 +781,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract isPlayer(): boolean;
|
abstract isPlayer(): this is PlayerPokemon;
|
||||||
|
|
||||||
|
abstract isEnemy(): this is EnemyPokemon;
|
||||||
|
|
||||||
abstract hasTrainer(): boolean;
|
abstract hasTrainer(): boolean;
|
||||||
|
|
||||||
@ -1293,19 +1287,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
*/
|
*/
|
||||||
isOffsetBySubstitute(): boolean {
|
isOffsetBySubstitute(): boolean {
|
||||||
const substitute = this.getTag(SubstituteTag);
|
const substitute = this.getTag(SubstituteTag);
|
||||||
if (substitute) {
|
if (!substitute || substitute.sprite === undefined) {
|
||||||
if (substitute.sprite === undefined) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// During the Pokemon's MoveEffect phase, the offset is removed to put the Pokemon "in focus"
|
|
||||||
const currentPhase = globalScene.getCurrentPhase();
|
|
||||||
if (currentPhase instanceof MoveEffectPhase && currentPhase.getPokemon() === this) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
// During the Pokemon's MoveEffect phase, the offset is removed to put the Pokemon "in focus"
|
||||||
|
const currentPhase = globalScene.phaseManager.getCurrentPhase();
|
||||||
|
return !(currentPhase?.is("MoveEffectPhase") && currentPhase.getPokemon() === this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** If this Pokemon has a Substitute on the field, removes its sprite from the field. */
|
/** If this Pokemon has a Substitute on the field, removes its sprite from the field. */
|
||||||
@ -2058,7 +2045,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
if (Overrides.ABILITY_OVERRIDE && this.isPlayer()) {
|
if (Overrides.ABILITY_OVERRIDE && this.isPlayer()) {
|
||||||
return allAbilities[Overrides.ABILITY_OVERRIDE];
|
return allAbilities[Overrides.ABILITY_OVERRIDE];
|
||||||
}
|
}
|
||||||
if (Overrides.OPP_ABILITY_OVERRIDE && !this.isPlayer()) {
|
if (Overrides.OPP_ABILITY_OVERRIDE && this.isEnemy()) {
|
||||||
return allAbilities[Overrides.OPP_ABILITY_OVERRIDE];
|
return allAbilities[Overrides.OPP_ABILITY_OVERRIDE];
|
||||||
}
|
}
|
||||||
if (this.isFusion()) {
|
if (this.isFusion()) {
|
||||||
@ -2088,7 +2075,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
if (Overrides.PASSIVE_ABILITY_OVERRIDE && this.isPlayer()) {
|
if (Overrides.PASSIVE_ABILITY_OVERRIDE && this.isPlayer()) {
|
||||||
return allAbilities[Overrides.PASSIVE_ABILITY_OVERRIDE];
|
return allAbilities[Overrides.PASSIVE_ABILITY_OVERRIDE];
|
||||||
}
|
}
|
||||||
if (Overrides.OPP_PASSIVE_ABILITY_OVERRIDE && !this.isPlayer()) {
|
if (Overrides.OPP_PASSIVE_ABILITY_OVERRIDE && this.isEnemy()) {
|
||||||
return allAbilities[Overrides.OPP_PASSIVE_ABILITY_OVERRIDE];
|
return allAbilities[Overrides.OPP_PASSIVE_ABILITY_OVERRIDE];
|
||||||
}
|
}
|
||||||
if (!isNullOrUndefined(this.customPokemonData.passive) && this.customPokemonData.passive !== -1) {
|
if (!isNullOrUndefined(this.customPokemonData.passive) && this.customPokemonData.passive !== -1) {
|
||||||
@ -2160,7 +2147,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
// returns override if valid for current case
|
// returns override if valid for current case
|
||||||
if (
|
if (
|
||||||
(Overrides.HAS_PASSIVE_ABILITY_OVERRIDE === false && this.isPlayer()) ||
|
(Overrides.HAS_PASSIVE_ABILITY_OVERRIDE === false && this.isPlayer()) ||
|
||||||
(Overrides.OPP_HAS_PASSIVE_ABILITY_OVERRIDE === false && !this.isPlayer())
|
(Overrides.OPP_HAS_PASSIVE_ABILITY_OVERRIDE === false && this.isEnemy())
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2168,7 +2155,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
((Overrides.PASSIVE_ABILITY_OVERRIDE !== AbilityId.NONE || Overrides.HAS_PASSIVE_ABILITY_OVERRIDE) &&
|
((Overrides.PASSIVE_ABILITY_OVERRIDE !== AbilityId.NONE || Overrides.HAS_PASSIVE_ABILITY_OVERRIDE) &&
|
||||||
this.isPlayer()) ||
|
this.isPlayer()) ||
|
||||||
((Overrides.OPP_PASSIVE_ABILITY_OVERRIDE !== AbilityId.NONE || Overrides.OPP_HAS_PASSIVE_ABILITY_OVERRIDE) &&
|
((Overrides.OPP_PASSIVE_ABILITY_OVERRIDE !== AbilityId.NONE || Overrides.OPP_HAS_PASSIVE_ABILITY_OVERRIDE) &&
|
||||||
!this.isPlayer())
|
this.isEnemy())
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2177,7 +2164,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
const { currentBattle, gameMode } = globalScene;
|
const { currentBattle, gameMode } = globalScene;
|
||||||
const waveIndex = currentBattle?.waveIndex;
|
const waveIndex = currentBattle?.waveIndex;
|
||||||
if (
|
if (
|
||||||
this instanceof EnemyPokemon &&
|
this.isEnemy() &&
|
||||||
(currentBattle?.battleSpec === BattleSpec.FINAL_BOSS ||
|
(currentBattle?.battleSpec === BattleSpec.FINAL_BOSS ||
|
||||||
gameMode.isEndlessMinorBoss(waveIndex) ||
|
gameMode.isEndlessMinorBoss(waveIndex) ||
|
||||||
gameMode.isEndlessMajorBoss(waveIndex))
|
gameMode.isEndlessMajorBoss(waveIndex))
|
||||||
@ -2242,10 +2229,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
if (this.getAbility(ignoreOverride).id === ability && (!canApply || this.canApplyAbility())) {
|
if (this.getAbility(ignoreOverride).id === ability && (!canApply || this.canApplyAbility())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (this.getPassiveAbility().id === ability && this.hasPassive() && (!canApply || this.canApplyAbility(true))) {
|
return this.getPassiveAbility().id === ability && this.hasPassive() && (!canApply || this.canApplyAbility(true));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2262,10 +2246,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
if ((!canApply || this.canApplyAbility()) && this.getAbility(ignoreOverride).hasAttr(attrType)) {
|
if ((!canApply || this.canApplyAbility()) && this.getAbility(ignoreOverride).hasAttr(attrType)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (this.hasPassive() && (!canApply || this.canApplyAbility(true)) && this.getPassiveAbility().hasAttr(attrType)) {
|
return this.hasPassive() && (!canApply || this.canApplyAbility(true)) && this.getPassiveAbility().hasAttr(attrType);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2549,7 +2530,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
) {
|
) {
|
||||||
multiplier /= 2;
|
multiplier /= 2;
|
||||||
if (!simulated) {
|
if (!simulated) {
|
||||||
globalScene.queueMessage(i18next.t("weather:strongWindsEffectMessage"));
|
globalScene.phaseManager.queueMessage(i18next.t("weather:strongWindsEffectMessage"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return multiplier as TypeDamageMultiplier;
|
return multiplier as TypeDamageMultiplier;
|
||||||
@ -2993,9 +2974,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
let fusionOverride: PokemonSpecies | undefined = undefined;
|
let fusionOverride: PokemonSpecies | undefined = undefined;
|
||||||
|
|
||||||
if (forStarter && this instanceof PlayerPokemon && Overrides.STARTER_FUSION_SPECIES_OVERRIDE) {
|
if (forStarter && this.isPlayer() && Overrides.STARTER_FUSION_SPECIES_OVERRIDE) {
|
||||||
fusionOverride = getPokemonSpecies(Overrides.STARTER_FUSION_SPECIES_OVERRIDE);
|
fusionOverride = getPokemonSpecies(Overrides.STARTER_FUSION_SPECIES_OVERRIDE);
|
||||||
} else if (this instanceof EnemyPokemon && Overrides.OPP_FUSION_SPECIES_OVERRIDE) {
|
} else if (this.isEnemy() && Overrides.OPP_FUSION_SPECIES_OVERRIDE) {
|
||||||
fusionOverride = getPokemonSpecies(Overrides.OPP_FUSION_SPECIES_OVERRIDE);
|
fusionOverride = getPokemonSpecies(Overrides.OPP_FUSION_SPECIES_OVERRIDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3306,7 +3287,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
this.battleInfo.setX(this.battleInfo.x + (this.isPlayer() ? 150 : !this.isBoss() ? -150 : -198));
|
this.battleInfo.setX(this.battleInfo.x + (this.isPlayer() ? 150 : !this.isBoss() ? -150 : -198));
|
||||||
this.battleInfo.setVisible(true);
|
this.battleInfo.setVisible(true);
|
||||||
if (this.isPlayer()) {
|
if (this.isPlayer()) {
|
||||||
this.battleInfo.expMaskRect.x += 150;
|
// TODO: How do you get this to not require a private property access?
|
||||||
|
this["battleInfo"].expMaskRect.x += 150;
|
||||||
}
|
}
|
||||||
globalScene.tweens.add({
|
globalScene.tweens.add({
|
||||||
targets: [this.battleInfo, this.battleInfo.expMaskRect],
|
targets: [this.battleInfo, this.battleInfo.expMaskRect],
|
||||||
@ -3327,7 +3309,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
ease: "Cubic.easeIn",
|
ease: "Cubic.easeIn",
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
if (this.isPlayer()) {
|
if (this.isPlayer()) {
|
||||||
this.battleInfo.expMaskRect.x -= 150;
|
// TODO: How do you get this to not require a private property access?
|
||||||
|
this["battleInfo"].expMaskRect.x -= 150;
|
||||||
}
|
}
|
||||||
this.battleInfo.setVisible(false);
|
this.battleInfo.setVisible(false);
|
||||||
this.battleInfo.setX(this.battleInfo.x - (this.isPlayer() ? 150 : !this.isBoss() ? -150 : -198));
|
this.battleInfo.setX(this.battleInfo.x - (this.isPlayer() ? 150 : !this.isBoss() ? -150 : -198));
|
||||||
@ -3422,7 +3405,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
* @returns An array of Pokémon on the allied field.
|
* @returns An array of Pokémon on the allied field.
|
||||||
*/
|
*/
|
||||||
getAlliedField(): Pokemon[] {
|
getAlliedField(): Pokemon[] {
|
||||||
return this instanceof PlayerPokemon ? globalScene.getPlayerField() : globalScene.getEnemyField();
|
return this.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4021,8 +4004,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
*
|
*
|
||||||
* Once the MoveEffectPhase is over (and calls it's .end() function, shiftPhase() will reset the PhaseQueueSplice via clearPhaseQueueSplice() )
|
* Once the MoveEffectPhase is over (and calls it's .end() function, shiftPhase() will reset the PhaseQueueSplice via clearPhaseQueueSplice() )
|
||||||
*/
|
*/
|
||||||
globalScene.setPhaseQueueSplice();
|
globalScene.phaseManager.setPhaseQueueSplice();
|
||||||
globalScene.unshiftPhase(new FaintPhase(this.getBattlerIndex(), preventEndure));
|
globalScene.phaseManager.unshiftNew("FaintPhase", this.getBattlerIndex(), preventEndure);
|
||||||
this.destroySubstitute();
|
this.destroySubstitute();
|
||||||
this.lapseTag(BattlerTagType.COMMANDED);
|
this.lapseTag(BattlerTagType.COMMANDED);
|
||||||
}
|
}
|
||||||
@ -4058,8 +4041,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
} = {},
|
} = {},
|
||||||
): number {
|
): number {
|
||||||
const isIndirectDamage = [HitResult.INDIRECT, HitResult.INDIRECT_KO].includes(result);
|
const isIndirectDamage = [HitResult.INDIRECT, HitResult.INDIRECT_KO].includes(result);
|
||||||
const damagePhase = new DamageAnimPhase(this.getBattlerIndex(), damage, result as DamageResult, isCritical);
|
const damagePhase = globalScene.phaseManager.create(
|
||||||
globalScene.unshiftPhase(damagePhase);
|
"DamageAnimPhase",
|
||||||
|
this.getBattlerIndex(),
|
||||||
|
damage,
|
||||||
|
result as DamageResult,
|
||||||
|
isCritical,
|
||||||
|
);
|
||||||
|
globalScene.phaseManager.unshiftPhase(damagePhase);
|
||||||
if (this.switchOutStatus && source) {
|
if (this.switchOutStatus && source) {
|
||||||
damage = 0;
|
damage = 0;
|
||||||
}
|
}
|
||||||
@ -4274,7 +4263,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
// Copy all stat stages
|
// Copy all stat stages
|
||||||
for (const s of BATTLE_STATS) {
|
for (const s of BATTLE_STATS) {
|
||||||
const sourceStage = source.getStatStage(s);
|
const sourceStage = source.getStatStage(s);
|
||||||
if (this instanceof PlayerPokemon && sourceStage === 6) {
|
if (this.isPlayer() && sourceStage === 6) {
|
||||||
globalScene.validateAchv(achvs.TRANSFER_MAX_STAT_STAGE);
|
globalScene.validateAchv(achvs.TRANSFER_MAX_STAT_STAGE);
|
||||||
}
|
}
|
||||||
this.setStatStage(s, sourceStage);
|
this.setStatStage(s, sourceStage);
|
||||||
@ -4625,7 +4614,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
: i18next.t("abilityTriggers:moveImmunity", {
|
: i18next.t("abilityTriggers:moveImmunity", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(this),
|
pokemonNameWithAffix: getPokemonNameWithAffix(this),
|
||||||
});
|
});
|
||||||
globalScene.queueMessage(message);
|
globalScene.phaseManager.queueMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4745,7 +4734,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
if (sourcePokemon && sourcePokemon !== this && this.isSafeguarded(sourcePokemon)) {
|
if (sourcePokemon && sourcePokemon !== this && this.isSafeguarded(sourcePokemon)) {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(i18next.t("moveTriggers:safeguard", { targetName: getPokemonNameWithAffix(this) }));
|
globalScene.phaseManager.queueMessage(
|
||||||
|
i18next.t("moveTriggers:safeguard", { targetName: getPokemonNameWithAffix(this) }),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -4774,8 +4765,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
* cancel the attack's subsequent hits.
|
* cancel the attack's subsequent hits.
|
||||||
*/
|
*/
|
||||||
if (effect === StatusEffect.SLEEP || effect === StatusEffect.FREEZE) {
|
if (effect === StatusEffect.SLEEP || effect === StatusEffect.FREEZE) {
|
||||||
const currentPhase = globalScene.getCurrentPhase();
|
const currentPhase = globalScene.phaseManager.getCurrentPhase();
|
||||||
if (currentPhase instanceof MoveEffectPhase && currentPhase.getUserPokemon() === this) {
|
if (currentPhase?.is("MoveEffectPhase") && currentPhase.getUserPokemon() === this) {
|
||||||
this.turnData.hitCount = 1;
|
this.turnData.hitCount = 1;
|
||||||
this.turnData.hitsLeft = 1;
|
this.turnData.hitsLeft = 1;
|
||||||
}
|
}
|
||||||
@ -4785,8 +4776,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
if (overrideStatus) {
|
if (overrideStatus) {
|
||||||
this.resetStatus(false);
|
this.resetStatus(false);
|
||||||
}
|
}
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new ObtainStatusEffectPhase(this.getBattlerIndex(), effect, turnsRemaining, sourceText, sourcePokemon),
|
"ObtainStatusEffectPhase",
|
||||||
|
this.getBattlerIndex(),
|
||||||
|
effect,
|
||||||
|
turnsRemaining,
|
||||||
|
sourceText,
|
||||||
|
sourcePokemon,
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -4835,7 +4831,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (asPhase) {
|
if (asPhase) {
|
||||||
globalScene.unshiftPhase(new ResetStatusPhase(this, confusion, reloadAssets));
|
globalScene.phaseManager.unshiftNew("ResetStatusPhase", this, confusion, reloadAssets);
|
||||||
} else {
|
} else {
|
||||||
this.clearStatus(confusion, reloadAssets);
|
this.clearStatus(confusion, reloadAssets);
|
||||||
}
|
}
|
||||||
@ -5135,7 +5131,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("battleInfo:newKey2", {
|
i18next.t("battleInfo:newKey2", {
|
||||||
// arguments for the locale key go here;
|
// arguments for the locale key go here;
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(this),
|
pokemonNameWithAffix: getPokemonNameWithAffix(this),
|
||||||
@ -5240,7 +5236,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
let fusionPaletteColors: Map<number, number>;
|
let fusionPaletteColors: Map<number, number>;
|
||||||
|
|
||||||
const originalRandom = Math.random;
|
const originalRandom = Math.random;
|
||||||
Math.random = () => Phaser.Math.RND.realInRange(0, 1);
|
Math.random = () => randSeedFloat();
|
||||||
|
|
||||||
globalScene.executeWithSeedOffset(
|
globalScene.executeWithSeedOffset(
|
||||||
() => {
|
() => {
|
||||||
@ -5472,10 +5468,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
if ((ownedAbilityAttrs & 2) > 0 && this.hasSameAbilityInRootForm(1)) {
|
if ((ownedAbilityAttrs & 2) > 0 && this.hasSameAbilityInRootForm(1)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((ownedAbilityAttrs & 4) > 0 && this.hasSameAbilityInRootForm(2)) {
|
return (ownedAbilityAttrs & 4) > 0 && this.hasSameAbilityInRootForm(2);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -5492,7 +5485,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
heldItem.stackCount--;
|
heldItem.stackCount--;
|
||||||
if (heldItem.stackCount <= 0) {
|
if (heldItem.stackCount <= 0) {
|
||||||
globalScene.removeModifier(heldItem, !this.isPlayer());
|
globalScene.removeModifier(heldItem, this.isEnemy());
|
||||||
}
|
}
|
||||||
if (forBattle) {
|
if (forBattle) {
|
||||||
applyPostItemLostAbAttrs(PostItemLostAbAttr, this, false);
|
applyPostItemLostAbAttrs(PostItemLostAbAttr, this, false);
|
||||||
@ -5565,15 +5558,19 @@ export class PlayerPokemon extends Pokemon {
|
|||||||
this.battleInfo.initInfo(this);
|
this.battleInfo.initInfo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
isPlayer(): boolean {
|
override isPlayer(): this is PlayerPokemon {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasTrainer(): boolean {
|
override isEnemy(): this is EnemyPokemon {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
override hasTrainer(): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
isBoss(): boolean {
|
override isBoss(): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5648,9 +5645,13 @@ export class PlayerPokemon extends Pokemon {
|
|||||||
this.getFieldIndex(),
|
this.getFieldIndex(),
|
||||||
(slotIndex: number, _option: PartyOption) => {
|
(slotIndex: number, _option: PartyOption) => {
|
||||||
if (slotIndex >= globalScene.currentBattle.getBattlerCount() && slotIndex < 6) {
|
if (slotIndex >= globalScene.currentBattle.getBattlerCount() && slotIndex < 6) {
|
||||||
globalScene.prependToPhase(
|
globalScene.phaseManager.prependNewToPhase(
|
||||||
new SwitchSummonPhase(switchType, this.getFieldIndex(), slotIndex, false),
|
"MoveEndPhase",
|
||||||
MoveEndPhase,
|
"SwitchSummonPhase",
|
||||||
|
switchType,
|
||||||
|
this.getFieldIndex(),
|
||||||
|
slotIndex,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE).then(resolve);
|
globalScene.ui.setMode(UiMode.MESSAGE).then(resolve);
|
||||||
@ -6012,7 +6013,9 @@ export class PlayerPokemon extends Pokemon {
|
|||||||
const newPartyMemberIndex = globalScene.getPlayerParty().indexOf(this);
|
const newPartyMemberIndex = globalScene.getPlayerParty().indexOf(this);
|
||||||
pokemon
|
pokemon
|
||||||
.getMoveset(true)
|
.getMoveset(true)
|
||||||
.map((m: PokemonMove) => globalScene.unshiftPhase(new LearnMovePhase(newPartyMemberIndex, m.getMove().id)));
|
.map((m: PokemonMove) =>
|
||||||
|
globalScene.phaseManager.unshiftNew("LearnMovePhase", newPartyMemberIndex, m.getMove().id),
|
||||||
|
);
|
||||||
pokemon.destroy();
|
pokemon.destroy();
|
||||||
this.updateFusionPalette();
|
this.updateFusionPalette();
|
||||||
}
|
}
|
||||||
@ -6517,15 +6520,19 @@ export class EnemyPokemon extends Pokemon {
|
|||||||
return [sortedBenefitScores[targetIndex][0]];
|
return [sortedBenefitScores[targetIndex][0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
isPlayer() {
|
override isPlayer(): this is PlayerPokemon {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasTrainer(): boolean {
|
override isEnemy(): this is EnemyPokemon {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
override hasTrainer(): boolean {
|
||||||
return !!this.trainerSlot;
|
return !!this.trainerSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
isBoss(): boolean {
|
override isBoss(): boolean {
|
||||||
return !!this.bossSegments;
|
return !!this.bossSegments;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6650,8 +6657,14 @@ export class EnemyPokemon extends Pokemon {
|
|||||||
stages++;
|
stages++;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(this.getBattlerIndex(), true, [boostedStat!], stages, true, true),
|
"StatStageChangePhase",
|
||||||
|
this.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
[boostedStat!],
|
||||||
|
stages,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
this.bossSegmentIndex--;
|
this.bossSegmentIndex--;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
export const starterColors: StarterColors = {};
|
export const starterColors: {
|
||||||
interface StarterColors {
|
|
||||||
[key: string]: [string, string];
|
[key: string]: [string, string];
|
||||||
}
|
} = {};
|
||||||
|
@ -16,7 +16,7 @@ export function getPokemonNameWithAffix(pokemon: Pokemon | undefined, useIllusio
|
|||||||
|
|
||||||
switch (globalScene.currentBattle.battleSpec) {
|
switch (globalScene.currentBattle.battleSpec) {
|
||||||
case BattleSpec.DEFAULT:
|
case BattleSpec.DEFAULT:
|
||||||
return !pokemon.isPlayer()
|
return pokemon.isEnemy()
|
||||||
? pokemon.hasTrainer()
|
? pokemon.hasTrainer()
|
||||||
? i18next.t("battle:foePokemonWithAffix", {
|
? i18next.t("battle:foePokemonWithAffix", {
|
||||||
pokemonName: pokemon.getNameToRender(useIllusion),
|
pokemonName: pokemon.getNameToRender(useIllusion),
|
||||||
@ -26,7 +26,7 @@ export function getPokemonNameWithAffix(pokemon: Pokemon | undefined, useIllusio
|
|||||||
})
|
})
|
||||||
: pokemon.getNameToRender(useIllusion);
|
: pokemon.getNameToRender(useIllusion);
|
||||||
case BattleSpec.FINAL_BOSS:
|
case BattleSpec.FINAL_BOSS:
|
||||||
return !pokemon.isPlayer()
|
return pokemon.isEnemy()
|
||||||
? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.getNameToRender(useIllusion) })
|
? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.getNameToRender(useIllusion) })
|
||||||
: pokemon.getNameToRender(useIllusion);
|
: pokemon.getNameToRender(useIllusion);
|
||||||
default:
|
default:
|
||||||
|
@ -8,14 +8,11 @@ import { getStatusEffectHealText } from "#app/data/status-effect";
|
|||||||
import Pokemon, { type PlayerPokemon } from "#app/field/pokemon";
|
import Pokemon, { type PlayerPokemon } from "#app/field/pokemon";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import Overrides from "#app/overrides";
|
import Overrides from "#app/overrides";
|
||||||
import { EvolutionPhase } from "#app/phases/evolution-phase";
|
import { LearnMoveType } from "#app/phases/learn-move-phase";
|
||||||
import { LearnMovePhase, LearnMoveType } from "#app/phases/learn-move-phase";
|
|
||||||
import { LevelUpPhase } from "#app/phases/level-up-phase";
|
|
||||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
|
||||||
import type { VoucherType } from "#app/system/voucher";
|
import type { VoucherType } from "#app/system/voucher";
|
||||||
import { Command } from "#app/ui/command-ui-handler";
|
import { Command } from "#app/ui/command-ui-handler";
|
||||||
import { addTextObject, TextStyle } from "#app/ui/text";
|
import { addTextObject, TextStyle } from "#app/ui/text";
|
||||||
import { BooleanHolder, hslToHex, isNullOrUndefined, NumberHolder, toDmgValue } from "#app/utils/common";
|
import { BooleanHolder, hslToHex, isNullOrUndefined, NumberHolder, randSeedFloat, toDmgValue } from "#app/utils/common";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import type { MoveId } from "#enums/move-id";
|
import type { MoveId } from "#enums/move-id";
|
||||||
@ -40,7 +37,6 @@ import {
|
|||||||
type TerastallizeModifierType,
|
type TerastallizeModifierType,
|
||||||
type TmModifierType,
|
type TmModifierType,
|
||||||
getModifierType,
|
getModifierType,
|
||||||
ModifierPoolType,
|
|
||||||
ModifierTypeGenerator,
|
ModifierTypeGenerator,
|
||||||
modifierTypes,
|
modifierTypes,
|
||||||
PokemonHeldItemModifierType,
|
PokemonHeldItemModifierType,
|
||||||
@ -1091,10 +1087,6 @@ export class PokemonIncrementingStatModifier extends PokemonHeldItemModifier {
|
|||||||
return new PokemonIncrementingStatModifier(this.type, this.pokemonId, this.stackCount);
|
return new PokemonIncrementingStatModifier(this.type, this.pokemonId, this.stackCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
getArgs(): any[] {
|
|
||||||
return super.getArgs();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the {@linkcode PokemonIncrementingStatModifier} should be applied to the {@linkcode Pokemon}.
|
* Checks if the {@linkcode PokemonIncrementingStatModifier} should be applied to the {@linkcode Pokemon}.
|
||||||
* @param pokemon The {@linkcode Pokemon} that holds the item
|
* @param pokemon The {@linkcode Pokemon} that holds the item
|
||||||
@ -1217,10 +1209,6 @@ export class StatBoosterModifier extends PokemonHeldItemModifier {
|
|||||||
* @see {@linkcode apply}
|
* @see {@linkcode apply}
|
||||||
*/
|
*/
|
||||||
export class EvolutionStatBoosterModifier extends StatBoosterModifier {
|
export class EvolutionStatBoosterModifier extends StatBoosterModifier {
|
||||||
clone() {
|
|
||||||
return super.clone() as EvolutionStatBoosterModifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
matchType(modifier: Modifier): boolean {
|
matchType(modifier: Modifier): boolean {
|
||||||
return modifier instanceof EvolutionStatBoosterModifier;
|
return modifier instanceof EvolutionStatBoosterModifier;
|
||||||
}
|
}
|
||||||
@ -1557,7 +1545,7 @@ export class SurviveDamageModifier extends PokemonHeldItemModifier {
|
|||||||
if (!surviveDamage.value && pokemon.randBattleSeedInt(10) < this.getStackCount()) {
|
if (!surviveDamage.value && pokemon.randBattleSeedInt(10) < this.getStackCount()) {
|
||||||
surviveDamage.value = true;
|
surviveDamage.value = true;
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("modifier:surviveDamageApply", {
|
i18next.t("modifier:surviveDamageApply", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
typeName: this.type.name,
|
typeName: this.type.name,
|
||||||
@ -1607,7 +1595,7 @@ export class BypassSpeedChanceModifier extends PokemonHeldItemModifier {
|
|||||||
const hasQuickClaw = this.type instanceof PokemonHeldItemModifierType && this.type.id === "QUICK_CLAW";
|
const hasQuickClaw = this.type instanceof PokemonHeldItemModifierType && this.type.id === "QUICK_CLAW";
|
||||||
|
|
||||||
if (isCommandFight && hasQuickClaw) {
|
if (isCommandFight && hasQuickClaw) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("modifier:bypassSpeedChanceApply", {
|
i18next.t("modifier:bypassSpeedChanceApply", {
|
||||||
pokemonName: getPokemonNameWithAffix(pokemon),
|
pokemonName: getPokemonNameWithAffix(pokemon),
|
||||||
itemName: i18next.t("modifierType:ModifierType.QUICK_CLAW.name"),
|
itemName: i18next.t("modifierType:ModifierType.QUICK_CLAW.name"),
|
||||||
@ -1693,16 +1681,15 @@ export class TurnHealModifier extends PokemonHeldItemModifier {
|
|||||||
*/
|
*/
|
||||||
override apply(pokemon: Pokemon): boolean {
|
override apply(pokemon: Pokemon): boolean {
|
||||||
if (!pokemon.isFullHp()) {
|
if (!pokemon.isFullHp()) {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new PokemonHealPhase(
|
"PokemonHealPhase",
|
||||||
pokemon.getBattlerIndex(),
|
pokemon.getBattlerIndex(),
|
||||||
toDmgValue(pokemon.getMaxHp() / 16) * this.stackCount,
|
toDmgValue(pokemon.getMaxHp() / 16) * this.stackCount,
|
||||||
i18next.t("modifier:turnHealApply", {
|
i18next.t("modifier:turnHealApply", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
typeName: this.type.name,
|
typeName: this.type.name,
|
||||||
}),
|
}),
|
||||||
true,
|
true,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1791,16 +1778,15 @@ export class HitHealModifier extends PokemonHeldItemModifier {
|
|||||||
override apply(pokemon: Pokemon): boolean {
|
override apply(pokemon: Pokemon): boolean {
|
||||||
if (pokemon.turnData.totalDamageDealt && !pokemon.isFullHp()) {
|
if (pokemon.turnData.totalDamageDealt && !pokemon.isFullHp()) {
|
||||||
// TODO: this shouldn't be undefined AFAIK
|
// TODO: this shouldn't be undefined AFAIK
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new PokemonHealPhase(
|
"PokemonHealPhase",
|
||||||
pokemon.getBattlerIndex(),
|
pokemon.getBattlerIndex(),
|
||||||
toDmgValue(pokemon.turnData.totalDamageDealt / 8) * this.stackCount,
|
toDmgValue(pokemon.turnData.totalDamageDealt / 8) * this.stackCount,
|
||||||
i18next.t("modifier:hitHealApply", {
|
i18next.t("modifier:hitHealApply", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
typeName: this.type.name,
|
typeName: this.type.name,
|
||||||
}),
|
}),
|
||||||
true,
|
true,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1959,18 +1945,17 @@ export class PokemonInstantReviveModifier extends PokemonHeldItemModifier {
|
|||||||
*/
|
*/
|
||||||
override apply(pokemon: Pokemon): boolean {
|
override apply(pokemon: Pokemon): boolean {
|
||||||
// Restore the Pokemon to half HP
|
// Restore the Pokemon to half HP
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new PokemonHealPhase(
|
"PokemonHealPhase",
|
||||||
pokemon.getBattlerIndex(),
|
pokemon.getBattlerIndex(),
|
||||||
toDmgValue(pokemon.getMaxHp() / 2),
|
toDmgValue(pokemon.getMaxHp() / 2),
|
||||||
i18next.t("modifier:pokemonInstantReviveApply", {
|
i18next.t("modifier:pokemonInstantReviveApply", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
typeName: this.type.name,
|
typeName: this.type.name,
|
||||||
}),
|
}),
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Remove the Pokemon's FAINT status
|
// Remove the Pokemon's FAINT status
|
||||||
@ -2021,7 +2006,7 @@ export class ResetNegativeStatStageModifier extends PokemonHeldItemModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (statRestored) {
|
if (statRestored) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("modifier:resetNegativeStatStageApply", {
|
i18next.t("modifier:resetNegativeStatStageApply", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
typeName: this.type.name,
|
typeName: this.type.name,
|
||||||
@ -2332,12 +2317,11 @@ export class PokemonLevelIncrementModifier extends ConsumablePokemonModifier {
|
|||||||
|
|
||||||
playerPokemon.addFriendship(FRIENDSHIP_GAIN_FROM_RARE_CANDY);
|
playerPokemon.addFriendship(FRIENDSHIP_GAIN_FROM_RARE_CANDY);
|
||||||
|
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new LevelUpPhase(
|
"LevelUpPhase",
|
||||||
globalScene.getPlayerParty().indexOf(playerPokemon),
|
globalScene.getPlayerParty().indexOf(playerPokemon),
|
||||||
playerPokemon.level - levelCount.value,
|
playerPokemon.level - levelCount.value,
|
||||||
playerPokemon.level,
|
playerPokemon.level,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2353,8 +2337,11 @@ export class TmModifier extends ConsumablePokemonModifier {
|
|||||||
* @returns always `true`
|
* @returns always `true`
|
||||||
*/
|
*/
|
||||||
override apply(playerPokemon: PlayerPokemon): boolean {
|
override apply(playerPokemon: PlayerPokemon): boolean {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new LearnMovePhase(globalScene.getPlayerParty().indexOf(playerPokemon), this.type.moveId, LearnMoveType.TM),
|
"LearnMovePhase",
|
||||||
|
globalScene.getPlayerParty().indexOf(playerPokemon),
|
||||||
|
this.type.moveId,
|
||||||
|
LearnMoveType.TM,
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2376,13 +2363,12 @@ export class RememberMoveModifier extends ConsumablePokemonModifier {
|
|||||||
* @returns always `true`
|
* @returns always `true`
|
||||||
*/
|
*/
|
||||||
override apply(playerPokemon: PlayerPokemon, cost?: number): boolean {
|
override apply(playerPokemon: PlayerPokemon, cost?: number): boolean {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new LearnMovePhase(
|
"LearnMovePhase",
|
||||||
globalScene.getPlayerParty().indexOf(playerPokemon),
|
globalScene.getPlayerParty().indexOf(playerPokemon),
|
||||||
playerPokemon.getLearnableLevelMoves()[this.levelMoveIndex],
|
playerPokemon.getLearnableLevelMoves()[this.levelMoveIndex],
|
||||||
LearnMoveType.MEMORY,
|
LearnMoveType.MEMORY,
|
||||||
cost,
|
cost,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2419,7 +2405,7 @@ export class EvolutionItemModifier extends ConsumablePokemonModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (matchingEvolution) {
|
if (matchingEvolution) {
|
||||||
globalScene.unshiftPhase(new EvolutionPhase(playerPokemon, matchingEvolution, playerPokemon.level - 1));
|
globalScene.phaseManager.unshiftNew("EvolutionPhase", playerPokemon, matchingEvolution, playerPokemon.level - 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3017,7 +3003,7 @@ export class MoneyInterestModifier extends PersistentModifier {
|
|||||||
moneyAmount: formattedMoneyAmount,
|
moneyAmount: formattedMoneyAmount,
|
||||||
typeName: this.type.name,
|
typeName: this.type.name,
|
||||||
});
|
});
|
||||||
globalScene.queueMessage(message, undefined, true);
|
globalScene.phaseManager.queueMessage(message, undefined, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3232,8 +3218,7 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Steals an item from a set of target Pokemon.
|
* Steals an item, chosen randomly, from a set of target Pokemon.
|
||||||
* This prioritizes high-tier held items when selecting the item to steal.
|
|
||||||
* @param pokemon The {@linkcode Pokemon} holding this item
|
* @param pokemon The {@linkcode Pokemon} holding this item
|
||||||
* @param target The {@linkcode Pokemon} to steal from (optional)
|
* @param target The {@linkcode Pokemon} to steal from (optional)
|
||||||
* @param _args N/A
|
* @param _args N/A
|
||||||
@ -3253,30 +3238,15 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const poolType = pokemon.isPlayer()
|
|
||||||
? ModifierPoolType.PLAYER
|
|
||||||
: pokemon.hasTrainer()
|
|
||||||
? ModifierPoolType.TRAINER
|
|
||||||
: ModifierPoolType.WILD;
|
|
||||||
|
|
||||||
const transferredModifierTypes: ModifierType[] = [];
|
const transferredModifierTypes: ModifierType[] = [];
|
||||||
const itemModifiers = globalScene.findModifiers(
|
const itemModifiers = globalScene.findModifiers(
|
||||||
m => m instanceof PokemonHeldItemModifier && m.pokemonId === targetPokemon.id && m.isTransferable,
|
m => m instanceof PokemonHeldItemModifier && m.pokemonId === targetPokemon.id && m.isTransferable,
|
||||||
targetPokemon.isPlayer(),
|
targetPokemon.isPlayer(),
|
||||||
) as PokemonHeldItemModifier[];
|
) as PokemonHeldItemModifier[];
|
||||||
let highestItemTier = itemModifiers
|
|
||||||
.map(m => m.type.getOrInferTier(poolType))
|
|
||||||
.reduce((highestTier, tier) => Math.max(tier!, highestTier), 0); // TODO: is this bang correct?
|
|
||||||
let tierItemModifiers = itemModifiers.filter(m => m.type.getOrInferTier(poolType) === highestItemTier);
|
|
||||||
|
|
||||||
for (let i = 0; i < transferredItemCount; i++) {
|
for (let i = 0; i < transferredItemCount; i++) {
|
||||||
if (!tierItemModifiers.length) {
|
if (!itemModifiers.length) {
|
||||||
while (highestItemTier-- && !tierItemModifiers.length) {
|
break;
|
||||||
tierItemModifiers = itemModifiers.filter(m => m.type.tier === highestItemTier);
|
|
||||||
}
|
|
||||||
if (!tierItemModifiers.length) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const randItemIndex = pokemon.randBattleSeedInt(itemModifiers.length);
|
const randItemIndex = pokemon.randBattleSeedInt(itemModifiers.length);
|
||||||
const randItem = itemModifiers[randItemIndex];
|
const randItem = itemModifiers[randItemIndex];
|
||||||
@ -3287,7 +3257,7 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const mt of transferredModifierTypes) {
|
for (const mt of transferredModifierTypes) {
|
||||||
globalScene.queueMessage(this.getTransferMessage(pokemon, targetPokemon, mt));
|
globalScene.phaseManager.queueMessage(this.getTransferMessage(pokemon, targetPokemon, mt));
|
||||||
}
|
}
|
||||||
|
|
||||||
return !!transferredModifierTypes.length;
|
return !!transferredModifierTypes.length;
|
||||||
@ -3374,7 +3344,7 @@ export class ContactHeldItemTransferChanceModifier extends HeldItemTransferModif
|
|||||||
}
|
}
|
||||||
|
|
||||||
getTransferredItemCount(): number {
|
getTransferredItemCount(): number {
|
||||||
return Phaser.Math.RND.realInRange(0, 1) < this.chance * this.getStackCount() ? 1 : 0;
|
return randSeedFloat() <= this.chance * this.getStackCount() ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTransferMessage(pokemon: Pokemon, targetPokemon: Pokemon, item: ModifierType): string {
|
getTransferMessage(pokemon: Pokemon, targetPokemon: Pokemon, item: ModifierType): string {
|
||||||
@ -3597,19 +3567,18 @@ export class EnemyTurnHealModifier extends EnemyPersistentModifier {
|
|||||||
*/
|
*/
|
||||||
override apply(enemyPokemon: Pokemon): boolean {
|
override apply(enemyPokemon: Pokemon): boolean {
|
||||||
if (!enemyPokemon.isFullHp()) {
|
if (!enemyPokemon.isFullHp()) {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new PokemonHealPhase(
|
"PokemonHealPhase",
|
||||||
enemyPokemon.getBattlerIndex(),
|
enemyPokemon.getBattlerIndex(),
|
||||||
Math.max(Math.floor(enemyPokemon.getMaxHp() / (100 / this.healPercent)) * this.stackCount, 1),
|
Math.max(Math.floor(enemyPokemon.getMaxHp() / (100 / this.healPercent)) * this.stackCount, 1),
|
||||||
i18next.t("modifier:enemyTurnHealApply", {
|
i18next.t("modifier:enemyTurnHealApply", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(enemyPokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(enemyPokemon),
|
||||||
}),
|
}),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3652,7 +3621,7 @@ export class EnemyAttackStatusEffectChanceModifier extends EnemyPersistentModifi
|
|||||||
* @returns `true` if the {@linkcode Pokemon} was affected
|
* @returns `true` if the {@linkcode Pokemon} was affected
|
||||||
*/
|
*/
|
||||||
override apply(enemyPokemon: Pokemon): boolean {
|
override apply(enemyPokemon: Pokemon): boolean {
|
||||||
if (Phaser.Math.RND.realInRange(0, 1) < this.chance * this.getStackCount()) {
|
if (randSeedFloat() <= this.chance * this.getStackCount()) {
|
||||||
return enemyPokemon.trySetStatus(this.effect, true);
|
return enemyPokemon.trySetStatus(this.effect, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3687,21 +3656,21 @@ export class EnemyStatusEffectHealChanceModifier extends EnemyPersistentModifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies {@linkcode EnemyStatusEffectHealChanceModifier}
|
* Applies {@linkcode EnemyStatusEffectHealChanceModifier} to randomly heal status.
|
||||||
* @param enemyPokemon The {@linkcode Pokemon} to heal
|
* @param enemyPokemon - The {@linkcode Pokemon} to heal
|
||||||
* @returns `true` if the {@linkcode Pokemon} was healed
|
* @returns `true` if the {@linkcode Pokemon} was healed
|
||||||
*/
|
*/
|
||||||
override apply(enemyPokemon: Pokemon): boolean {
|
override apply(enemyPokemon: Pokemon): boolean {
|
||||||
if (enemyPokemon.status && Phaser.Math.RND.realInRange(0, 1) < this.chance * this.getStackCount()) {
|
if (!enemyPokemon.status || randSeedFloat() > this.chance * this.getStackCount()) {
|
||||||
globalScene.queueMessage(
|
return false;
|
||||||
getStatusEffectHealText(enemyPokemon.status.effect, getPokemonNameWithAffix(enemyPokemon)),
|
|
||||||
);
|
|
||||||
enemyPokemon.resetStatus();
|
|
||||||
enemyPokemon.updateInfo();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
globalScene.phaseManager.queueMessage(
|
||||||
|
getStatusEffectHealText(enemyPokemon.status.effect, getPokemonNameWithAffix(enemyPokemon)),
|
||||||
|
);
|
||||||
|
enemyPokemon.resetStatus();
|
||||||
|
enemyPokemon.updateInfo();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMaxStackCount(): number {
|
getMaxStackCount(): number {
|
||||||
@ -3780,7 +3749,7 @@ export class EnemyFusionChanceModifier extends EnemyPersistentModifier {
|
|||||||
* @returns `true` if the {@linkcode EnemyPokemon} is a fusion
|
* @returns `true` if the {@linkcode EnemyPokemon} is a fusion
|
||||||
*/
|
*/
|
||||||
override apply(isFusion: BooleanHolder): boolean {
|
override apply(isFusion: BooleanHolder): boolean {
|
||||||
if (Phaser.Math.RND.realInRange(0, 1) >= this.chance * this.getStackCount()) {
|
if (randSeedFloat() > this.chance * this.getStackCount()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
581
src/phase-manager.ts
Normal file
581
src/phase-manager.ts
Normal file
@ -0,0 +1,581 @@
|
|||||||
|
import type { Phase } from "#app/phase";
|
||||||
|
import type { default as Pokemon } from "#app/field/pokemon";
|
||||||
|
import type { PhaseMap, PhaseString } from "./@types/phase-types";
|
||||||
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import { AddEnemyBuffModifierPhase } from "#app/phases/add-enemy-buff-modifier-phase";
|
||||||
|
import { AttemptCapturePhase } from "#app/phases/attempt-capture-phase";
|
||||||
|
import { AttemptRunPhase } from "#app/phases/attempt-run-phase";
|
||||||
|
import { BattleEndPhase } from "#app/phases/battle-end-phase";
|
||||||
|
import { BerryPhase } from "#app/phases/berry-phase";
|
||||||
|
import { CheckStatusEffectPhase } from "#app/phases/check-status-effect-phase";
|
||||||
|
import { CheckSwitchPhase } from "#app/phases/check-switch-phase";
|
||||||
|
import { CommandPhase } from "#app/phases/command-phase";
|
||||||
|
import { CommonAnimPhase } from "#app/phases/common-anim-phase";
|
||||||
|
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
|
||||||
|
import { EggHatchPhase } from "#app/phases/egg-hatch-phase";
|
||||||
|
import { EggLapsePhase } from "#app/phases/egg-lapse-phase";
|
||||||
|
import { EggSummaryPhase } from "#app/phases/egg-summary-phase";
|
||||||
|
import { EncounterPhase } from "#app/phases/encounter-phase";
|
||||||
|
import { EndCardPhase } from "#app/phases/end-card-phase";
|
||||||
|
import { EndEvolutionPhase } from "#app/phases/end-evolution-phase";
|
||||||
|
import { EnemyCommandPhase } from "#app/phases/enemy-command-phase";
|
||||||
|
import { EvolutionPhase } from "#app/phases/evolution-phase";
|
||||||
|
import { ExpPhase } from "#app/phases/exp-phase";
|
||||||
|
import { FaintPhase } from "#app/phases/faint-phase";
|
||||||
|
import { FormChangePhase } from "#app/phases/form-change-phase";
|
||||||
|
import { GameOverModifierRewardPhase } from "#app/phases/game-over-modifier-reward-phase";
|
||||||
|
import { GameOverPhase } from "#app/phases/game-over-phase";
|
||||||
|
import { HideAbilityPhase } from "#app/phases/hide-ability-phase";
|
||||||
|
import { HidePartyExpBarPhase } from "#app/phases/hide-party-exp-bar-phase";
|
||||||
|
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
||||||
|
import { LevelCapPhase } from "#app/phases/level-cap-phase";
|
||||||
|
import { LevelUpPhase } from "#app/phases/level-up-phase";
|
||||||
|
import { LoadMoveAnimPhase } from "#app/phases/load-move-anim-phase";
|
||||||
|
import { LoginPhase } from "#app/phases/login-phase";
|
||||||
|
import { MessagePhase } from "#app/phases/message-phase";
|
||||||
|
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
||||||
|
import { MoneyRewardPhase } from "#app/phases/money-reward-phase";
|
||||||
|
import { MoveAnimPhase } from "#app/phases/move-anim-phase";
|
||||||
|
import { MoveChargePhase } from "#app/phases/move-charge-phase";
|
||||||
|
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
||||||
|
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
||||||
|
import { MoveHeaderPhase } from "#app/phases/move-header-phase";
|
||||||
|
import { MovePhase } from "#app/phases/move-phase";
|
||||||
|
import {
|
||||||
|
MysteryEncounterPhase,
|
||||||
|
MysteryEncounterOptionSelectedPhase,
|
||||||
|
MysteryEncounterBattlePhase,
|
||||||
|
MysteryEncounterRewardsPhase,
|
||||||
|
PostMysteryEncounterPhase,
|
||||||
|
MysteryEncounterBattleStartCleanupPhase,
|
||||||
|
} from "#app/phases/mystery-encounter-phases";
|
||||||
|
import { NewBattlePhase } from "#app/phases/new-battle-phase";
|
||||||
|
import { NewBiomeEncounterPhase } from "#app/phases/new-biome-encounter-phase";
|
||||||
|
import { NextEncounterPhase } from "#app/phases/next-encounter-phase";
|
||||||
|
import { ObtainStatusEffectPhase } from "#app/phases/obtain-status-effect-phase";
|
||||||
|
import { PartyExpPhase } from "#app/phases/party-exp-phase";
|
||||||
|
import { PartyHealPhase } from "#app/phases/party-heal-phase";
|
||||||
|
import { PokemonAnimPhase } from "#app/phases/pokemon-anim-phase";
|
||||||
|
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
||||||
|
import { PokemonTransformPhase } from "#app/phases/pokemon-transform-phase";
|
||||||
|
import { PostGameOverPhase } from "#app/phases/post-game-over-phase";
|
||||||
|
import { PostSummonPhase } from "#app/phases/post-summon-phase";
|
||||||
|
import { PostTurnStatusEffectPhase } from "#app/phases/post-turn-status-effect-phase";
|
||||||
|
import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase";
|
||||||
|
import { ReloadSessionPhase } from "#app/phases/reload-session-phase";
|
||||||
|
import { ResetStatusPhase } from "#app/phases/reset-status-phase";
|
||||||
|
import { ReturnPhase } from "#app/phases/return-phase";
|
||||||
|
import { RevivalBlessingPhase } from "#app/phases/revival-blessing-phase";
|
||||||
|
import { RibbonModifierRewardPhase } from "#app/phases/ribbon-modifier-reward-phase";
|
||||||
|
import { ScanIvsPhase } from "#app/phases/scan-ivs-phase";
|
||||||
|
import { SelectBiomePhase } from "#app/phases/select-biome-phase";
|
||||||
|
import { SelectChallengePhase } from "#app/phases/select-challenge-phase";
|
||||||
|
import { SelectGenderPhase } from "#app/phases/select-gender-phase";
|
||||||
|
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
||||||
|
import { SelectStarterPhase } from "#app/phases/select-starter-phase";
|
||||||
|
import { SelectTargetPhase } from "#app/phases/select-target-phase";
|
||||||
|
import { ShinySparklePhase } from "#app/phases/shiny-sparkle-phase";
|
||||||
|
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
||||||
|
import { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase";
|
||||||
|
import { ShowTrainerPhase } from "#app/phases/show-trainer-phase";
|
||||||
|
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||||
|
import { SummonMissingPhase } from "#app/phases/summon-missing-phase";
|
||||||
|
import { SummonPhase } from "#app/phases/summon-phase";
|
||||||
|
import { SwitchBiomePhase } from "#app/phases/switch-biome-phase";
|
||||||
|
import { SwitchPhase } from "#app/phases/switch-phase";
|
||||||
|
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
|
||||||
|
import { TeraPhase } from "#app/phases/tera-phase";
|
||||||
|
import { TitlePhase } from "#app/phases/title-phase";
|
||||||
|
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
|
||||||
|
import { TrainerVictoryPhase } from "#app/phases/trainer-victory-phase";
|
||||||
|
import { TurnEndPhase } from "#app/phases/turn-end-phase";
|
||||||
|
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
||||||
|
import { TurnStartPhase } from "#app/phases/turn-start-phase";
|
||||||
|
import { UnavailablePhase } from "#app/phases/unavailable-phase";
|
||||||
|
import { UnlockPhase } from "#app/phases/unlock-phase";
|
||||||
|
import { VictoryPhase } from "#app/phases/victory-phase";
|
||||||
|
import { WeatherEffectPhase } from "#app/phases/weather-effect-phase";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manager for phases used by battle scene.
|
||||||
|
*
|
||||||
|
* *This file must not be imported or used directly. The manager is exclusively used by the battle scene and is not intended for external use.*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object that holds all of the phase constructors.
|
||||||
|
* This is used to create new phases dynamically using the `newPhase` method in the `PhaseManager`.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* The keys of this object are the names of the phases, and the values are the constructors of the phases.
|
||||||
|
* This allows for easy creation of new phases without needing to import each phase individually.
|
||||||
|
*/
|
||||||
|
const PHASES = Object.freeze({
|
||||||
|
AddEnemyBuffModifierPhase,
|
||||||
|
AttemptCapturePhase,
|
||||||
|
AttemptRunPhase,
|
||||||
|
BattleEndPhase,
|
||||||
|
BerryPhase,
|
||||||
|
CheckStatusEffectPhase,
|
||||||
|
CheckSwitchPhase,
|
||||||
|
CommandPhase,
|
||||||
|
CommonAnimPhase,
|
||||||
|
DamageAnimPhase,
|
||||||
|
EggHatchPhase,
|
||||||
|
EggLapsePhase,
|
||||||
|
EggSummaryPhase,
|
||||||
|
EncounterPhase,
|
||||||
|
EndCardPhase,
|
||||||
|
EndEvolutionPhase,
|
||||||
|
EnemyCommandPhase,
|
||||||
|
EvolutionPhase,
|
||||||
|
ExpPhase,
|
||||||
|
FaintPhase,
|
||||||
|
FormChangePhase,
|
||||||
|
GameOverPhase,
|
||||||
|
GameOverModifierRewardPhase,
|
||||||
|
HideAbilityPhase,
|
||||||
|
HidePartyExpBarPhase,
|
||||||
|
LearnMovePhase,
|
||||||
|
LevelCapPhase,
|
||||||
|
LevelUpPhase,
|
||||||
|
LoadMoveAnimPhase,
|
||||||
|
LoginPhase,
|
||||||
|
MessagePhase,
|
||||||
|
ModifierRewardPhase,
|
||||||
|
MoneyRewardPhase,
|
||||||
|
MoveAnimPhase,
|
||||||
|
MoveChargePhase,
|
||||||
|
MoveEffectPhase,
|
||||||
|
MoveEndPhase,
|
||||||
|
MoveHeaderPhase,
|
||||||
|
MovePhase,
|
||||||
|
MysteryEncounterPhase,
|
||||||
|
MysteryEncounterOptionSelectedPhase,
|
||||||
|
MysteryEncounterBattlePhase,
|
||||||
|
MysteryEncounterBattleStartCleanupPhase,
|
||||||
|
MysteryEncounterRewardsPhase,
|
||||||
|
PostMysteryEncounterPhase,
|
||||||
|
NewBattlePhase,
|
||||||
|
NewBiomeEncounterPhase,
|
||||||
|
NextEncounterPhase,
|
||||||
|
ObtainStatusEffectPhase,
|
||||||
|
PartyExpPhase,
|
||||||
|
PartyHealPhase,
|
||||||
|
PokemonAnimPhase,
|
||||||
|
PokemonHealPhase,
|
||||||
|
PokemonTransformPhase,
|
||||||
|
PostGameOverPhase,
|
||||||
|
PostSummonPhase,
|
||||||
|
PostTurnStatusEffectPhase,
|
||||||
|
QuietFormChangePhase,
|
||||||
|
ReloadSessionPhase,
|
||||||
|
ResetStatusPhase,
|
||||||
|
ReturnPhase,
|
||||||
|
RevivalBlessingPhase,
|
||||||
|
RibbonModifierRewardPhase,
|
||||||
|
ScanIvsPhase,
|
||||||
|
SelectBiomePhase,
|
||||||
|
SelectChallengePhase,
|
||||||
|
SelectGenderPhase,
|
||||||
|
SelectModifierPhase,
|
||||||
|
SelectStarterPhase,
|
||||||
|
SelectTargetPhase,
|
||||||
|
ShinySparklePhase,
|
||||||
|
ShowAbilityPhase,
|
||||||
|
ShowPartyExpBarPhase,
|
||||||
|
ShowTrainerPhase,
|
||||||
|
StatStageChangePhase,
|
||||||
|
SummonMissingPhase,
|
||||||
|
SummonPhase,
|
||||||
|
SwitchBiomePhase,
|
||||||
|
SwitchPhase,
|
||||||
|
SwitchSummonPhase,
|
||||||
|
TeraPhase,
|
||||||
|
TitlePhase,
|
||||||
|
ToggleDoublePositionPhase,
|
||||||
|
TrainerVictoryPhase,
|
||||||
|
TurnEndPhase,
|
||||||
|
TurnInitPhase,
|
||||||
|
TurnStartPhase,
|
||||||
|
UnavailablePhase,
|
||||||
|
UnlockPhase,
|
||||||
|
VictoryPhase,
|
||||||
|
WeatherEffectPhase,
|
||||||
|
});
|
||||||
|
|
||||||
|
// This type export cannot be moved to `@types`, as `Phases` is intentionally private to this file
|
||||||
|
/** Maps Phase strings to their constructors */
|
||||||
|
export type PhaseConstructorMap = typeof PHASES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PhaseManager is responsible for managing the phases in the battle scene
|
||||||
|
*/
|
||||||
|
export class PhaseManager {
|
||||||
|
/** PhaseQueue: dequeue/remove the first element to get the next phase */
|
||||||
|
public phaseQueue: Phase[] = [];
|
||||||
|
public conditionalQueue: Array<[() => boolean, Phase]> = [];
|
||||||
|
/** PhaseQueuePrepend: is a temp storage of what will be added to PhaseQueue */
|
||||||
|
private phaseQueuePrepend: Phase[] = [];
|
||||||
|
|
||||||
|
/** overrides default of inserting phases to end of phaseQueuePrepend array. Useful for inserting Phases "out of order" */
|
||||||
|
private phaseQueuePrependSpliceIndex = -1;
|
||||||
|
private nextCommandPhaseQueue: Phase[] = [];
|
||||||
|
|
||||||
|
private currentPhase: Phase | null = null;
|
||||||
|
private standbyPhase: Phase | null = null;
|
||||||
|
|
||||||
|
/* Phase Functions */
|
||||||
|
getCurrentPhase(): Phase | null {
|
||||||
|
return this.currentPhase;
|
||||||
|
}
|
||||||
|
|
||||||
|
getStandbyPhase(): Phase | null {
|
||||||
|
return this.standbyPhase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a phase to the conditional queue and ensures it is executed only when the specified condition is met.
|
||||||
|
*
|
||||||
|
* This method allows deferring the execution of a phase until certain conditions are met, which is useful for handling
|
||||||
|
* situations like abilities and entry hazards that depend on specific game states.
|
||||||
|
*
|
||||||
|
* @param phase - The phase to be added to the conditional queue.
|
||||||
|
* @param condition - A function that returns a boolean indicating whether the phase should be executed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
pushConditionalPhase(phase: Phase, condition: () => boolean): void {
|
||||||
|
this.conditionalQueue.push([condition, phase]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a phase to nextCommandPhaseQueue, as long as boolean passed in is false
|
||||||
|
* @param phase {@linkcode Phase} the phase to add
|
||||||
|
* @param defer boolean on which queue to add to, defaults to false, and adds to phaseQueue
|
||||||
|
*/
|
||||||
|
pushPhase(phase: Phase, defer = false): void {
|
||||||
|
(!defer ? this.phaseQueue : this.nextCommandPhaseQueue).push(phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds Phase(s) to the end of phaseQueuePrepend, or at phaseQueuePrependSpliceIndex
|
||||||
|
* @param phases {@linkcode Phase} the phase(s) to add
|
||||||
|
*/
|
||||||
|
unshiftPhase(...phases: Phase[]): void {
|
||||||
|
if (this.phaseQueuePrependSpliceIndex === -1) {
|
||||||
|
this.phaseQueuePrepend.push(...phases);
|
||||||
|
} else {
|
||||||
|
this.phaseQueuePrepend.splice(this.phaseQueuePrependSpliceIndex, 0, ...phases);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the phaseQueue
|
||||||
|
*/
|
||||||
|
clearPhaseQueue(): void {
|
||||||
|
this.phaseQueue.splice(0, this.phaseQueue.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all phase-related stuff, including all phase queues, the current and standby phases, and a splice index
|
||||||
|
*/
|
||||||
|
clearAllPhases(): void {
|
||||||
|
for (const queue of [this.phaseQueue, this.phaseQueuePrepend, this.conditionalQueue, this.nextCommandPhaseQueue]) {
|
||||||
|
queue.splice(0, queue.length);
|
||||||
|
}
|
||||||
|
this.currentPhase = null;
|
||||||
|
this.standbyPhase = null;
|
||||||
|
this.clearPhaseQueueSplice();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by function unshiftPhase(), sets index to start inserting at current length instead of the end of the array, useful if phaseQueuePrepend gets longer with Phases
|
||||||
|
*/
|
||||||
|
setPhaseQueueSplice(): void {
|
||||||
|
this.phaseQueuePrependSpliceIndex = this.phaseQueuePrepend.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets phaseQueuePrependSpliceIndex to -1, implies that calls to unshiftPhase will insert at end of phaseQueuePrepend
|
||||||
|
*/
|
||||||
|
clearPhaseQueueSplice(): void {
|
||||||
|
this.phaseQueuePrependSpliceIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is called by each Phase implementations "end()" by default
|
||||||
|
* We dump everything from phaseQueuePrepend to the start of of phaseQueue
|
||||||
|
* then removes first Phase and starts it
|
||||||
|
*/
|
||||||
|
shiftPhase(): void {
|
||||||
|
if (this.standbyPhase) {
|
||||||
|
this.currentPhase = this.standbyPhase;
|
||||||
|
this.standbyPhase = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.phaseQueuePrependSpliceIndex > -1) {
|
||||||
|
this.clearPhaseQueueSplice();
|
||||||
|
}
|
||||||
|
if (this.phaseQueuePrepend.length) {
|
||||||
|
while (this.phaseQueuePrepend.length) {
|
||||||
|
const poppedPhase = this.phaseQueuePrepend.pop();
|
||||||
|
if (poppedPhase) {
|
||||||
|
this.phaseQueue.unshift(poppedPhase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.phaseQueue.length) {
|
||||||
|
this.populatePhaseQueue();
|
||||||
|
// Clear the conditionalQueue if there are no phases left in the phaseQueue
|
||||||
|
this.conditionalQueue = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentPhase = this.phaseQueue.shift() ?? null;
|
||||||
|
|
||||||
|
// Check if there are any conditional phases queued
|
||||||
|
if (this.conditionalQueue?.length) {
|
||||||
|
// Retrieve the first conditional phase from the queue
|
||||||
|
const conditionalPhase = this.conditionalQueue.shift();
|
||||||
|
// Evaluate the condition associated with the phase
|
||||||
|
if (conditionalPhase?.[0]()) {
|
||||||
|
// If the condition is met, add the phase to the phase queue
|
||||||
|
this.pushPhase(conditionalPhase[1]);
|
||||||
|
} else if (conditionalPhase) {
|
||||||
|
// If the condition is not met, re-add the phase back to the front of the conditional queue
|
||||||
|
this.conditionalQueue.unshift(conditionalPhase);
|
||||||
|
} else {
|
||||||
|
console.warn("condition phase is undefined/null!", conditionalPhase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentPhase) {
|
||||||
|
console.log(`%cStart Phase ${this.currentPhase.constructor.name}`, "color:green;");
|
||||||
|
this.currentPhase.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
overridePhase(phase: Phase): boolean {
|
||||||
|
if (this.standbyPhase) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.standbyPhase = this.currentPhase;
|
||||||
|
this.currentPhase = phase;
|
||||||
|
console.log(`%cStart Phase ${phase.constructor.name}`, "color:green;");
|
||||||
|
phase.start();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a specific {@linkcode Phase} in the phase queue.
|
||||||
|
*
|
||||||
|
* @param phaseFilter filter function to use to find the wanted phase
|
||||||
|
* @returns the found phase or undefined if none found
|
||||||
|
*/
|
||||||
|
findPhase<P extends Phase = Phase>(phaseFilter: (phase: P) => boolean): P | undefined {
|
||||||
|
return this.phaseQueue.find(phaseFilter) as P;
|
||||||
|
}
|
||||||
|
|
||||||
|
tryReplacePhase(phaseFilter: (phase: Phase) => boolean, phase: Phase): boolean {
|
||||||
|
const phaseIndex = this.phaseQueue.findIndex(phaseFilter);
|
||||||
|
if (phaseIndex > -1) {
|
||||||
|
this.phaseQueue[phaseIndex] = phase;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tryRemovePhase(phaseFilter: (phase: Phase) => boolean): boolean {
|
||||||
|
const phaseIndex = this.phaseQueue.findIndex(phaseFilter);
|
||||||
|
if (phaseIndex > -1) {
|
||||||
|
this.phaseQueue.splice(phaseIndex, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will search for a specific phase in {@linkcode phaseQueuePrepend} via filter, and remove the first result if a match is found.
|
||||||
|
* @param phaseFilter filter function
|
||||||
|
*/
|
||||||
|
tryRemoveUnshiftedPhase(phaseFilter: (phase: Phase) => boolean): boolean {
|
||||||
|
const phaseIndex = this.phaseQueuePrepend.findIndex(phaseFilter);
|
||||||
|
if (phaseIndex > -1) {
|
||||||
|
this.phaseQueuePrepend.splice(phaseIndex, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to add the input phase to index before target phase in the phaseQueue, else simply calls unshiftPhase()
|
||||||
|
* @param phase - The phase to be added
|
||||||
|
* @param targetPhase - The phase to search for in phaseQueue
|
||||||
|
* @returns boolean if a targetPhase was found and added
|
||||||
|
*/
|
||||||
|
prependToPhase(phase: Phase | Phase[], targetPhase: PhaseString): boolean {
|
||||||
|
if (!Array.isArray(phase)) {
|
||||||
|
phase = [phase];
|
||||||
|
}
|
||||||
|
const target = PHASES[targetPhase];
|
||||||
|
const targetIndex = this.phaseQueue.findIndex(ph => ph instanceof target);
|
||||||
|
|
||||||
|
if (targetIndex !== -1) {
|
||||||
|
this.phaseQueue.splice(targetIndex, 0, ...phase);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
this.unshiftPhase(...phase);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to add the input phase(s) to index after target phase in the {@linkcode phaseQueue}, else simply calls {@linkcode unshiftPhase()}
|
||||||
|
* @param phase - The phase(s) to be added
|
||||||
|
* @param targetPhase - The phase to search for in phaseQueue
|
||||||
|
* @returns `true` if a `targetPhase` was found to append to
|
||||||
|
*/
|
||||||
|
appendToPhase(phase: Phase | Phase[], targetPhase: PhaseString): boolean {
|
||||||
|
if (!Array.isArray(phase)) {
|
||||||
|
phase = [phase];
|
||||||
|
}
|
||||||
|
const target = PHASES[targetPhase];
|
||||||
|
const targetIndex = this.phaseQueue.findIndex(ph => ph instanceof target);
|
||||||
|
|
||||||
|
if (targetIndex !== -1 && this.phaseQueue.length > targetIndex) {
|
||||||
|
this.phaseQueue.splice(targetIndex + 1, 0, ...phase);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
this.unshiftPhase(...phase);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a MessagePhase, either to PhaseQueuePrepend or nextCommandPhaseQueue
|
||||||
|
* @param message - string for MessagePhase
|
||||||
|
* @param callbackDelay - optional param for MessagePhase constructor
|
||||||
|
* @param prompt - optional param for MessagePhase constructor
|
||||||
|
* @param promptDelay - optional param for MessagePhase constructor
|
||||||
|
* @param defer - Whether to allow the phase to be deferred
|
||||||
|
*
|
||||||
|
* @see {@linkcode MessagePhase} for more details on the parameters
|
||||||
|
*/
|
||||||
|
queueMessage(
|
||||||
|
message: string,
|
||||||
|
callbackDelay?: number | null,
|
||||||
|
prompt?: boolean | null,
|
||||||
|
promptDelay?: number | null,
|
||||||
|
defer?: boolean | null,
|
||||||
|
) {
|
||||||
|
const phase = new MessagePhase(message, callbackDelay, prompt, promptDelay);
|
||||||
|
if (!defer) {
|
||||||
|
// adds to the end of PhaseQueuePrepend
|
||||||
|
this.unshiftPhase(phase);
|
||||||
|
} else {
|
||||||
|
//remember that pushPhase adds it to nextCommandPhaseQueue
|
||||||
|
this.pushPhase(phase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queues an ability bar flyout phase
|
||||||
|
* @param pokemon The pokemon who has the ability
|
||||||
|
* @param passive Whether the ability is a passive
|
||||||
|
* @param show Whether to show or hide the bar
|
||||||
|
*/
|
||||||
|
public queueAbilityDisplay(pokemon: Pokemon, passive: boolean, show: boolean): void {
|
||||||
|
this.unshiftPhase(show ? new ShowAbilityPhase(pokemon.getBattlerIndex(), passive) : new HideAbilityPhase());
|
||||||
|
this.clearPhaseQueueSplice();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides the ability bar if it is currently visible
|
||||||
|
*/
|
||||||
|
public hideAbilityBar(): void {
|
||||||
|
if (globalScene.abilityBar.isVisible()) {
|
||||||
|
this.unshiftPhase(new HideAbilityPhase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves everything from nextCommandPhaseQueue to phaseQueue (keeping order)
|
||||||
|
*/
|
||||||
|
private populatePhaseQueue(): void {
|
||||||
|
if (this.nextCommandPhaseQueue.length) {
|
||||||
|
this.phaseQueue.push(...this.nextCommandPhaseQueue);
|
||||||
|
this.nextCommandPhaseQueue.splice(0, this.nextCommandPhaseQueue.length);
|
||||||
|
}
|
||||||
|
this.phaseQueue.push(new TurnInitPhase());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamically create the named phase from the provided arguments
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* Used to avoid importing each phase individually, allowing for dynamic creation of phases.
|
||||||
|
* @param phase - The name of the phase to create.
|
||||||
|
* @param args - The arguments to pass to the phase constructor.
|
||||||
|
* @returns The requested phase instance
|
||||||
|
*/
|
||||||
|
public create<T extends PhaseString>(phase: T, ...args: ConstructorParameters<PhaseConstructorMap[T]>): PhaseMap[T] {
|
||||||
|
const PhaseClass = PHASES[phase];
|
||||||
|
|
||||||
|
if (!PhaseClass) {
|
||||||
|
throw new Error(`Phase ${phase} does not exist in PhaseMap.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error: Typescript does not support narrowing the type of operands in generic methods (see https://stackoverflow.com/a/72891234)
|
||||||
|
return new PhaseClass(...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new phase and immediately push it to the phase queue. Equivalent to calling {@linkcode create} followed by {@linkcode pushPhase}.
|
||||||
|
* @param phase - The name of the phase to create
|
||||||
|
* @param args - The arguments to pass to the phase constructor
|
||||||
|
*/
|
||||||
|
public pushNew<T extends PhaseString>(phase: T, ...args: ConstructorParameters<PhaseConstructorMap[T]>): void {
|
||||||
|
this.pushPhase(this.create(phase, ...args));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new phase and immediately unshift it to the phase queue. Equivalent to calling {@linkcode create} followed by {@linkcode unshiftPhase}.
|
||||||
|
* @param phase - The name of the phase to create
|
||||||
|
* @param args - The arguments to pass to the phase constructor
|
||||||
|
*/
|
||||||
|
public unshiftNew<T extends PhaseString>(phase: T, ...args: ConstructorParameters<PhaseConstructorMap[T]>): void {
|
||||||
|
this.unshiftPhase(this.create(phase, ...args));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new phase and immediately prepend it to an existing phase in the phase queue.
|
||||||
|
* Equivalent to calling {@linkcode create} followed by {@linkcode prependToPhase}.
|
||||||
|
* @param targetPhase - The phase to search for in phaseQueue
|
||||||
|
* @param phase - The name of the phase to create
|
||||||
|
* @param args - The arguments to pass to the phase constructor
|
||||||
|
* @returns `true` if a `targetPhase` was found to prepend to
|
||||||
|
*/
|
||||||
|
public prependNewToPhase<T extends PhaseString>(
|
||||||
|
targetPhase: PhaseString,
|
||||||
|
phase: T,
|
||||||
|
...args: ConstructorParameters<PhaseConstructorMap[T]>
|
||||||
|
): boolean {
|
||||||
|
return this.prependToPhase(this.create(phase, ...args), targetPhase);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new phase and immediately append it to an existing phase the phase queue.
|
||||||
|
* Equivalent to calling {@linkcode create} followed by {@linkcode appendToPhase}.
|
||||||
|
* @param targetPhase - The phase to search for in phaseQueue
|
||||||
|
* @param phase - The name of the phase to create
|
||||||
|
* @param args - The arguments to pass to the phase constructor
|
||||||
|
* @returns `true` if a `targetPhase` was found to append to
|
||||||
|
*/
|
||||||
|
public appendNewToPhase<T extends PhaseString>(
|
||||||
|
targetPhase: PhaseString,
|
||||||
|
phase: T,
|
||||||
|
...args: ConstructorParameters<PhaseConstructorMap[T]>
|
||||||
|
): boolean {
|
||||||
|
return this.appendToPhase(this.create(phase, ...args), targetPhase);
|
||||||
|
}
|
||||||
|
}
|
28
src/phase.ts
28
src/phase.ts
@ -1,9 +1,33 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import type { PhaseMap, PhaseString } from "./@types/phase-types";
|
||||||
|
|
||||||
export class Phase {
|
export abstract class Phase {
|
||||||
start() {}
|
start() {}
|
||||||
|
|
||||||
end() {
|
end() {
|
||||||
globalScene.shiftPhase();
|
globalScene.phaseManager.shiftPhase();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string name of the phase, used to identify the phase type for {@linkcode is}
|
||||||
|
*
|
||||||
|
* @privateremarks
|
||||||
|
*
|
||||||
|
* When implementing a phase, you must set the `phaseName` property to the name of the phase.
|
||||||
|
*/
|
||||||
|
public abstract readonly phaseName: PhaseString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the phase is of the given type without requiring `instanceof`.
|
||||||
|
*
|
||||||
|
* @param phase - The string name of the phase to check.
|
||||||
|
* @returns Whether this phase is of the provided type.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* This does not check for subclasses! It only checks if the phase is *exactly* the given type.
|
||||||
|
* This method exists to avoid circular import issues, as using `instanceof` would require importing each phase.
|
||||||
|
*/
|
||||||
|
is<K extends keyof PhaseMap>(phase: K): this is PhaseMap[K] {
|
||||||
|
return this.phaseName === phase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import { Phase } from "#app/phase";
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
|
||||||
export class AddEnemyBuffModifierPhase extends Phase {
|
export class AddEnemyBuffModifierPhase extends Phase {
|
||||||
|
public readonly phaseName = "AddEnemyBuffModifierPhase";
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ import type { EnemyPokemon } from "#app/field/pokemon";
|
|||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||||
import { PokemonPhase } from "#app/phases/pokemon-phase";
|
import { PokemonPhase } from "#app/phases/pokemon-phase";
|
||||||
import { VictoryPhase } from "#app/phases/victory-phase";
|
|
||||||
import { achvs } from "#app/system/achv";
|
import { achvs } from "#app/system/achv";
|
||||||
import type { PartyOption } from "#app/ui/party-ui-handler";
|
import type { PartyOption } from "#app/ui/party-ui-handler";
|
||||||
import { PartyUiMode } from "#app/ui/party-ui-handler";
|
import { PartyUiMode } from "#app/ui/party-ui-handler";
|
||||||
@ -27,6 +26,7 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { Gender } from "#app/data/gender";
|
import { Gender } from "#app/data/gender";
|
||||||
|
|
||||||
export class AttemptCapturePhase extends PokemonPhase {
|
export class AttemptCapturePhase extends PokemonPhase {
|
||||||
|
public readonly phaseName = "AttemptCapturePhase";
|
||||||
private pokeballType: PokeballType;
|
private pokeballType: PokeballType;
|
||||||
private pokeball: Phaser.GameObjects.Sprite;
|
private pokeball: Phaser.GameObjects.Sprite;
|
||||||
private originalY: number;
|
private originalY: number;
|
||||||
@ -256,7 +256,7 @@ export class AttemptCapturePhase extends PokemonPhase {
|
|||||||
null,
|
null,
|
||||||
() => {
|
() => {
|
||||||
const end = () => {
|
const end = () => {
|
||||||
globalScene.unshiftPhase(new VictoryPhase(this.battlerIndex));
|
globalScene.phaseManager.unshiftNew("VictoryPhase", this.battlerIndex);
|
||||||
globalScene.pokemonInfoContainer.hide();
|
globalScene.pokemonInfoContainer.hide();
|
||||||
this.removePb();
|
this.removePb();
|
||||||
this.end();
|
this.end();
|
||||||
|
@ -10,13 +10,11 @@ import type { PlayerPokemon, EnemyPokemon } from "#app/field/pokemon";
|
|||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { NumberHolder } from "#app/utils/common";
|
import { NumberHolder } from "#app/utils/common";
|
||||||
import { BattleEndPhase } from "./battle-end-phase";
|
|
||||||
import { NewBattlePhase } from "./new-battle-phase";
|
|
||||||
import { PokemonPhase } from "./pokemon-phase";
|
import { PokemonPhase } from "./pokemon-phase";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { SelectBiomePhase } from "./select-biome-phase";
|
|
||||||
|
|
||||||
export class AttemptRunPhase extends PokemonPhase {
|
export class AttemptRunPhase extends PokemonPhase {
|
||||||
|
public readonly phaseName = "AttemptRunPhase";
|
||||||
/** For testing purposes: this is to force the pokemon to fail and escape */
|
/** For testing purposes: this is to force the pokemon to fail and escape */
|
||||||
public forceFailEscape = false;
|
public forceFailEscape = false;
|
||||||
|
|
||||||
@ -38,7 +36,7 @@ export class AttemptRunPhase extends PokemonPhase {
|
|||||||
enemyField.forEach(enemyPokemon => applyPreLeaveFieldAbAttrs(PreLeaveFieldAbAttr, enemyPokemon));
|
enemyField.forEach(enemyPokemon => applyPreLeaveFieldAbAttrs(PreLeaveFieldAbAttr, enemyPokemon));
|
||||||
|
|
||||||
globalScene.playSound("se/flee");
|
globalScene.playSound("se/flee");
|
||||||
globalScene.queueMessage(i18next.t("battle:runAwaySuccess"), null, true, 500);
|
globalScene.phaseManager.queueMessage(i18next.t("battle:runAwaySuccess"), null, true, 500);
|
||||||
|
|
||||||
globalScene.tweens.add({
|
globalScene.tweens.add({
|
||||||
targets: [globalScene.arenaEnemy, enemyField].flat(),
|
targets: [globalScene.arenaEnemy, enemyField].flat(),
|
||||||
@ -59,16 +57,16 @@ export class AttemptRunPhase extends PokemonPhase {
|
|||||||
enemyPokemon.trySetStatus(StatusEffect.FAINT);
|
enemyPokemon.trySetStatus(StatusEffect.FAINT);
|
||||||
});
|
});
|
||||||
|
|
||||||
globalScene.pushPhase(new BattleEndPhase(false));
|
globalScene.phaseManager.pushNew("BattleEndPhase", false);
|
||||||
|
|
||||||
if (globalScene.gameMode.hasRandomBiomes || globalScene.isNewBiome()) {
|
if (globalScene.gameMode.hasRandomBiomes || globalScene.isNewBiome()) {
|
||||||
globalScene.pushPhase(new SelectBiomePhase());
|
globalScene.phaseManager.pushNew("SelectBiomePhase");
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.pushPhase(new NewBattlePhase());
|
globalScene.phaseManager.pushNew("NewBattlePhase");
|
||||||
} else {
|
} else {
|
||||||
playerPokemon.turnData.failedRunAway = true;
|
playerPokemon.turnData.failedRunAway = true;
|
||||||
globalScene.queueMessage(i18next.t("battle:runAwayCannotEscape"), null, true, 500);
|
globalScene.phaseManager.queueMessage(i18next.t("battle:runAwayCannotEscape"), null, true, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.end();
|
this.end();
|
||||||
|
@ -2,9 +2,9 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { applyPostBattleAbAttrs, PostBattleAbAttr } from "#app/data/abilities/ability";
|
import { applyPostBattleAbAttrs, PostBattleAbAttr } from "#app/data/abilities/ability";
|
||||||
import { LapsingPersistentModifier, LapsingPokemonHeldItemModifier } from "#app/modifier/modifier";
|
import { LapsingPersistentModifier, LapsingPokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||||
import { BattlePhase } from "./battle-phase";
|
import { BattlePhase } from "./battle-phase";
|
||||||
import { GameOverPhase } from "./game-over-phase";
|
|
||||||
|
|
||||||
export class BattleEndPhase extends BattlePhase {
|
export class BattleEndPhase extends BattlePhase {
|
||||||
|
public readonly phaseName = "BattleEndPhase";
|
||||||
/** If true, will increment battles won */
|
/** If true, will increment battles won */
|
||||||
isVictory: boolean;
|
isVictory: boolean;
|
||||||
|
|
||||||
@ -18,8 +18,8 @@ export class BattleEndPhase extends BattlePhase {
|
|||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
// cull any extra `BattleEnd` phases from the queue.
|
// cull any extra `BattleEnd` phases from the queue.
|
||||||
globalScene.phaseQueue = globalScene.phaseQueue.filter(phase => {
|
globalScene.phaseManager.phaseQueue = globalScene.phaseManager.phaseQueue.filter(phase => {
|
||||||
if (phase instanceof BattleEndPhase) {
|
if (phase.is("BattleEndPhase")) {
|
||||||
this.isVictory ||= phase.isVictory;
|
this.isVictory ||= phase.isVictory;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -27,8 +27,8 @@ export class BattleEndPhase extends BattlePhase {
|
|||||||
});
|
});
|
||||||
// `phaseQueuePrepend` is private, so we have to use this inefficient loop.
|
// `phaseQueuePrepend` is private, so we have to use this inefficient loop.
|
||||||
while (
|
while (
|
||||||
globalScene.tryRemoveUnshiftedPhase(phase => {
|
globalScene.phaseManager.tryRemoveUnshiftedPhase(phase => {
|
||||||
if (phase instanceof BattleEndPhase) {
|
if (phase.is("BattleEndPhase")) {
|
||||||
this.isVictory ||= phase.isVictory;
|
this.isVictory ||= phase.isVictory;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -54,8 +54,8 @@ export class BattleEndPhase extends BattlePhase {
|
|||||||
|
|
||||||
// Endless graceful end
|
// Endless graceful end
|
||||||
if (globalScene.gameMode.isEndless && globalScene.currentBattle.waveIndex >= 5850) {
|
if (globalScene.gameMode.isEndless && globalScene.currentBattle.waveIndex >= 5850) {
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.unshiftPhase(new GameOverPhase(true));
|
globalScene.phaseManager.unshiftNew("GameOverPhase", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const pokemon of globalScene.getField()) {
|
for (const pokemon of globalScene.getField()) {
|
||||||
|
@ -2,7 +2,7 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { TrainerSlot } from "#enums/trainer-slot";
|
import { TrainerSlot } from "#enums/trainer-slot";
|
||||||
import { Phase } from "#app/phase";
|
import { Phase } from "#app/phase";
|
||||||
|
|
||||||
export class BattlePhase extends Phase {
|
export abstract class BattlePhase extends Phase {
|
||||||
showEnemyTrainer(trainerSlot: TrainerSlot = TrainerSlot.NONE): void {
|
showEnemyTrainer(trainerSlot: TrainerSlot = TrainerSlot.NONE): void {
|
||||||
if (!globalScene.currentBattle.trainer) {
|
if (!globalScene.currentBattle.trainer) {
|
||||||
console.warn("Enemy trainer is missing!");
|
console.warn("Enemy trainer is missing!");
|
||||||
|
@ -11,7 +11,6 @@ import { BerryModifier } from "#app/modifier/modifier";
|
|||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { BooleanHolder } from "#app/utils/common";
|
import { BooleanHolder } from "#app/utils/common";
|
||||||
import { FieldPhase } from "./field-phase";
|
import { FieldPhase } from "./field-phase";
|
||||||
import { CommonAnimPhase } from "./common-anim-phase";
|
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
|
|
||||||
@ -20,6 +19,7 @@ import type Pokemon from "#app/field/pokemon";
|
|||||||
* Also triggers Cud Chew's "repeat berry use" effects
|
* Also triggers Cud Chew's "repeat berry use" effects
|
||||||
*/
|
*/
|
||||||
export class BerryPhase extends FieldPhase {
|
export class BerryPhase extends FieldPhase {
|
||||||
|
public readonly phaseName = "BerryPhase";
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ export class BerryPhase extends FieldPhase {
|
|||||||
const cancelled = new BooleanHolder(false);
|
const cancelled = new BooleanHolder(false);
|
||||||
pokemon.getOpponents().forEach(opp => applyAbAttrs(PreventBerryUseAbAttr, opp, cancelled));
|
pokemon.getOpponents().forEach(opp => applyAbAttrs(PreventBerryUseAbAttr, opp, cancelled));
|
||||||
if (cancelled.value) {
|
if (cancelled.value) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("abilityTriggers:preventBerryUse", {
|
i18next.t("abilityTriggers:preventBerryUse", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
}),
|
}),
|
||||||
@ -57,8 +57,11 @@ export class BerryPhase extends FieldPhase {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new CommonAnimPhase(pokemon.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.USE_ITEM),
|
"CommonAnimPhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
CommonAnim.USE_ITEM,
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const berryModifier of globalScene.applyModifiers(BerryModifier, pokemon.isPlayer(), pokemon)) {
|
for (const berryModifier of globalScene.applyModifiers(BerryModifier, pokemon.isPlayer(), pokemon)) {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { PostTurnStatusEffectPhase } from "#app/phases/post-turn-status-effect-phase";
|
|
||||||
import { Phase } from "#app/phase";
|
import { Phase } from "#app/phase";
|
||||||
import type { BattlerIndex } from "#app/battle";
|
import type { BattlerIndex } from "#app/battle";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
|
||||||
export class CheckStatusEffectPhase extends Phase {
|
export class CheckStatusEffectPhase extends Phase {
|
||||||
|
public readonly phaseName = "CheckStatusEffectPhase";
|
||||||
private order: BattlerIndex[];
|
private order: BattlerIndex[];
|
||||||
constructor(order: BattlerIndex[]) {
|
constructor(order: BattlerIndex[]) {
|
||||||
super();
|
super();
|
||||||
@ -14,7 +14,7 @@ export class CheckStatusEffectPhase extends Phase {
|
|||||||
const field = globalScene.getField();
|
const field = globalScene.getField();
|
||||||
for (const o of this.order) {
|
for (const o of this.order) {
|
||||||
if (field[o].status?.isPostTurn()) {
|
if (field[o].status?.isPostTurn()) {
|
||||||
globalScene.unshiftPhase(new PostTurnStatusEffectPhase(o));
|
globalScene.phaseManager.unshiftNew("PostTurnStatusEffectPhase", o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.end();
|
this.end();
|
||||||
|
@ -5,11 +5,10 @@ import { getPokemonNameWithAffix } from "#app/messages";
|
|||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { BattlePhase } from "./battle-phase";
|
import { BattlePhase } from "./battle-phase";
|
||||||
import { SummonMissingPhase } from "./summon-missing-phase";
|
|
||||||
import { SwitchPhase } from "./switch-phase";
|
|
||||||
import { SwitchType } from "#enums/switch-type";
|
import { SwitchType } from "#enums/switch-type";
|
||||||
|
|
||||||
export class CheckSwitchPhase extends BattlePhase {
|
export class CheckSwitchPhase extends BattlePhase {
|
||||||
|
public readonly phaseName = "CheckSwitchPhase";
|
||||||
protected fieldIndex: number;
|
protected fieldIndex: number;
|
||||||
protected useName: boolean;
|
protected useName: boolean;
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ export class CheckSwitchPhase extends BattlePhase {
|
|||||||
|
|
||||||
// ...if the checked Pokemon is somehow not on the field
|
// ...if the checked Pokemon is somehow not on the field
|
||||||
if (globalScene.field.getAll().indexOf(pokemon) === -1) {
|
if (globalScene.field.getAll().indexOf(pokemon) === -1) {
|
||||||
globalScene.unshiftPhase(new SummonMissingPhase(this.fieldIndex));
|
globalScene.phaseManager.unshiftNew("SummonMissingPhase", this.fieldIndex);
|
||||||
return super.end();
|
return super.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +66,7 @@ export class CheckSwitchPhase extends BattlePhase {
|
|||||||
UiMode.CONFIRM,
|
UiMode.CONFIRM,
|
||||||
() => {
|
() => {
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
globalScene.ui.setMode(UiMode.MESSAGE);
|
||||||
globalScene.unshiftPhase(new SwitchPhase(SwitchType.INITIAL_SWITCH, this.fieldIndex, false, true));
|
globalScene.phaseManager.unshiftNew("SwitchPhase", SwitchType.INITIAL_SWITCH, this.fieldIndex, false, true);
|
||||||
this.end();
|
this.end();
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
|
@ -18,13 +18,13 @@ import { Command } from "#app/ui/command-ui-handler";
|
|||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { FieldPhase } from "./field-phase";
|
import { FieldPhase } from "./field-phase";
|
||||||
import { SelectTargetPhase } from "./select-target-phase";
|
|
||||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
import { isNullOrUndefined } from "#app/utils/common";
|
import { isNullOrUndefined } from "#app/utils/common";
|
||||||
import { ArenaTagSide } from "#app/data/arena-tag";
|
import { ArenaTagSide } from "#app/data/arena-tag";
|
||||||
import { ArenaTagType } from "#app/enums/arena-tag-type";
|
import { ArenaTagType } from "#app/enums/arena-tag-type";
|
||||||
|
|
||||||
export class CommandPhase extends FieldPhase {
|
export class CommandPhase extends FieldPhase {
|
||||||
|
public readonly phaseName = "CommandPhase";
|
||||||
protected fieldIndex: number;
|
protected fieldIndex: number;
|
||||||
|
|
||||||
constructor(fieldIndex: number) {
|
constructor(fieldIndex: number) {
|
||||||
@ -191,7 +191,7 @@ export class CommandPhase extends FieldPhase {
|
|||||||
}
|
}
|
||||||
console.log(moveTargets, getPokemonNameWithAffix(playerPokemon));
|
console.log(moveTargets, getPokemonNameWithAffix(playerPokemon));
|
||||||
if (moveTargets.targets.length > 1 && moveTargets.multiple) {
|
if (moveTargets.targets.length > 1 && moveTargets.multiple) {
|
||||||
globalScene.unshiftPhase(new SelectTargetPhase(this.fieldIndex));
|
globalScene.phaseManager.unshiftNew("SelectTargetPhase", this.fieldIndex);
|
||||||
}
|
}
|
||||||
if (turnCommand.move && (moveTargets.targets.length <= 1 || moveTargets.multiple)) {
|
if (turnCommand.move && (moveTargets.targets.length <= 1 || moveTargets.multiple)) {
|
||||||
turnCommand.move.targets = moveTargets.targets;
|
turnCommand.move.targets = moveTargets.targets;
|
||||||
@ -202,7 +202,7 @@ export class CommandPhase extends FieldPhase {
|
|||||||
) {
|
) {
|
||||||
turnCommand.move.targets = playerPokemon.getMoveQueue()[0].targets;
|
turnCommand.move.targets = playerPokemon.getMoveQueue()[0].targets;
|
||||||
} else {
|
} else {
|
||||||
globalScene.unshiftPhase(new SelectTargetPhase(this.fieldIndex));
|
globalScene.phaseManager.unshiftNew("SelectTargetPhase", this.fieldIndex);
|
||||||
}
|
}
|
||||||
globalScene.currentBattle.preTurnCommands[this.fieldIndex] = preTurnCommand;
|
globalScene.currentBattle.preTurnCommands[this.fieldIndex] = preTurnCommand;
|
||||||
globalScene.currentBattle.turnCommands[this.fieldIndex] = turnCommand;
|
globalScene.currentBattle.turnCommands[this.fieldIndex] = turnCommand;
|
||||||
@ -456,8 +456,8 @@ export class CommandPhase extends FieldPhase {
|
|||||||
|
|
||||||
cancel() {
|
cancel() {
|
||||||
if (this.fieldIndex) {
|
if (this.fieldIndex) {
|
||||||
globalScene.unshiftPhase(new CommandPhase(0));
|
globalScene.phaseManager.unshiftNew("CommandPhase", 0);
|
||||||
globalScene.unshiftPhase(new CommandPhase(1));
|
globalScene.phaseManager.unshiftNew("CommandPhase", 1);
|
||||||
this.end();
|
this.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,9 @@ import { CommonBattleAnim } from "#app/data/battle-anims";
|
|||||||
import { PokemonPhase } from "./pokemon-phase";
|
import { PokemonPhase } from "./pokemon-phase";
|
||||||
|
|
||||||
export class CommonAnimPhase extends PokemonPhase {
|
export class CommonAnimPhase extends PokemonPhase {
|
||||||
|
// PokemonHealPhase extends CommonAnimPhase, and to make typescript happy,
|
||||||
|
// we need to allow phaseName to be a union of the two
|
||||||
|
public readonly phaseName: "CommonAnimPhase" | "PokemonHealPhase" | "WeatherEffectPhase" = "CommonAnimPhase";
|
||||||
private anim: CommonAnim | null;
|
private anim: CommonAnim | null;
|
||||||
private targetIndex?: BattlerIndex;
|
private targetIndex?: BattlerIndex;
|
||||||
private playOnEmptyField: boolean;
|
private playOnEmptyField: boolean;
|
||||||
|
@ -6,6 +6,7 @@ import { fixedInt } from "#app/utils/common";
|
|||||||
import { PokemonPhase } from "#app/phases/pokemon-phase";
|
import { PokemonPhase } from "#app/phases/pokemon-phase";
|
||||||
|
|
||||||
export class DamageAnimPhase extends PokemonPhase {
|
export class DamageAnimPhase extends PokemonPhase {
|
||||||
|
public readonly phaseName = "DamageAnimPhase";
|
||||||
private amount: number;
|
private amount: number;
|
||||||
private damageResult: DamageResult;
|
private damageResult: DamageResult;
|
||||||
private critical: boolean;
|
private critical: boolean;
|
||||||
|
@ -20,6 +20,7 @@ import { doShinySparkleAnim } from "#app/field/anims";
|
|||||||
* Class that represents egg hatching
|
* Class that represents egg hatching
|
||||||
*/
|
*/
|
||||||
export class EggHatchPhase extends Phase {
|
export class EggHatchPhase extends Phase {
|
||||||
|
public readonly phaseName = "EggHatchPhase";
|
||||||
/** The egg that is hatching */
|
/** The egg that is hatching */
|
||||||
private egg: Egg;
|
private egg: Egg;
|
||||||
/** The new EggHatchData for the egg/pokemon that hatches */
|
/** The new EggHatchData for the egg/pokemon that hatches */
|
||||||
@ -224,7 +225,7 @@ export class EggHatchPhase extends Phase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
end() {
|
end() {
|
||||||
if (globalScene.findPhase(p => p instanceof EggHatchPhase)) {
|
if (globalScene.phaseManager.findPhase(p => p.is("EggHatchPhase"))) {
|
||||||
this.eggHatchHandler.clear();
|
this.eggHatchHandler.clear();
|
||||||
} else {
|
} else {
|
||||||
globalScene.time.delayedCall(250, () => globalScene.setModifiersVisible(true));
|
globalScene.time.delayedCall(250, () => globalScene.setModifiersVisible(true));
|
||||||
|
@ -4,11 +4,9 @@ import { EGG_SEED } from "#app/data/egg";
|
|||||||
import { Phase } from "#app/phase";
|
import { Phase } from "#app/phase";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import Overrides from "#app/overrides";
|
import Overrides from "#app/overrides";
|
||||||
import { EggHatchPhase } from "./egg-hatch-phase";
|
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { achvs } from "#app/system/achv";
|
import { achvs } from "#app/system/achv";
|
||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import { EggSummaryPhase } from "./egg-summary-phase";
|
|
||||||
import { EggHatchData } from "#app/data/egg-hatch-data";
|
import { EggHatchData } from "#app/data/egg-hatch-data";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,6 +14,7 @@ import { EggHatchData } from "#app/data/egg-hatch-data";
|
|||||||
* Also handles prompts for skipping animation, and calling the egg summary phase
|
* Also handles prompts for skipping animation, and calling the egg summary phase
|
||||||
*/
|
*/
|
||||||
export class EggLapsePhase extends Phase {
|
export class EggLapsePhase extends Phase {
|
||||||
|
public readonly phaseName = "EggLapsePhase";
|
||||||
private eggHatchData: EggHatchData[] = [];
|
private eggHatchData: EggHatchData[] = [];
|
||||||
private readonly minEggsToSkip: number = 2;
|
private readonly minEggsToSkip: number = 2;
|
||||||
|
|
||||||
@ -61,12 +60,12 @@ export class EggLapsePhase extends Phase {
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
} else if (eggsToHatchCount >= this.minEggsToSkip && globalScene.eggSkipPreference === 2) {
|
} else if (eggsToHatchCount >= this.minEggsToSkip && globalScene.eggSkipPreference === 2) {
|
||||||
globalScene.queueMessage(i18next.t("battle:eggHatching"));
|
globalScene.phaseManager.queueMessage(i18next.t("battle:eggHatching"));
|
||||||
this.hatchEggsSkipped(eggsToHatch);
|
this.hatchEggsSkipped(eggsToHatch);
|
||||||
this.showSummary();
|
this.showSummary();
|
||||||
} else {
|
} else {
|
||||||
// regular hatches, no summary
|
// regular hatches, no summary
|
||||||
globalScene.queueMessage(i18next.t("battle:eggHatching"));
|
globalScene.phaseManager.queueMessage(i18next.t("battle:eggHatching"));
|
||||||
this.hatchEggsRegular(eggsToHatch);
|
this.hatchEggsRegular(eggsToHatch);
|
||||||
this.end();
|
this.end();
|
||||||
}
|
}
|
||||||
@ -82,7 +81,7 @@ export class EggLapsePhase extends Phase {
|
|||||||
hatchEggsRegular(eggsToHatch: Egg[]) {
|
hatchEggsRegular(eggsToHatch: Egg[]) {
|
||||||
let eggsToHatchCount: number = eggsToHatch.length;
|
let eggsToHatchCount: number = eggsToHatch.length;
|
||||||
for (const egg of eggsToHatch) {
|
for (const egg of eggsToHatch) {
|
||||||
globalScene.unshiftPhase(new EggHatchPhase(this, egg, eggsToHatchCount));
|
globalScene.phaseManager.unshiftNew("EggHatchPhase", this, egg, eggsToHatchCount);
|
||||||
eggsToHatchCount--;
|
eggsToHatchCount--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,7 +97,7 @@ export class EggLapsePhase extends Phase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showSummary() {
|
showSummary() {
|
||||||
globalScene.unshiftPhase(new EggSummaryPhase(this.eggHatchData));
|
globalScene.phaseManager.unshiftNew("EggSummaryPhase", this.eggHatchData);
|
||||||
this.end();
|
this.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import type { EggHatchData } from "#app/data/egg-hatch-data";
|
|||||||
* Phase is handled mostly by the egg-hatch-scene-handler UI
|
* Phase is handled mostly by the egg-hatch-scene-handler UI
|
||||||
*/
|
*/
|
||||||
export class EggSummaryPhase extends Phase {
|
export class EggSummaryPhase extends Phase {
|
||||||
|
public readonly phaseName = "EggSummaryPhase";
|
||||||
private eggHatchData: EggHatchData[];
|
private eggHatchData: EggHatchData[];
|
||||||
|
|
||||||
constructor(eggHatchData: EggHatchData[]) {
|
constructor(eggHatchData: EggHatchData[]) {
|
||||||
|
@ -23,15 +23,6 @@ import { BoostBugSpawnModifier, IvScannerModifier, TurnHeldItemTransferModifier
|
|||||||
import { ModifierPoolType, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
import { ModifierPoolType, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
||||||
import Overrides from "#app/overrides";
|
import Overrides from "#app/overrides";
|
||||||
import { BattlePhase } from "#app/phases/battle-phase";
|
import { BattlePhase } from "#app/phases/battle-phase";
|
||||||
import { CheckSwitchPhase } from "#app/phases/check-switch-phase";
|
|
||||||
import { GameOverPhase } from "#app/phases/game-over-phase";
|
|
||||||
import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases";
|
|
||||||
import { PostSummonPhase } from "#app/phases/post-summon-phase";
|
|
||||||
import { ReturnPhase } from "#app/phases/return-phase";
|
|
||||||
import { ScanIvsPhase } from "#app/phases/scan-ivs-phase";
|
|
||||||
import { ShinySparklePhase } from "#app/phases/shiny-sparkle-phase";
|
|
||||||
import { SummonPhase } from "#app/phases/summon-phase";
|
|
||||||
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
|
|
||||||
import { achvs } from "#app/system/achv";
|
import { achvs } from "#app/system/achv";
|
||||||
import { handleTutorial, Tutorial } from "#app/tutorial";
|
import { handleTutorial, Tutorial } from "#app/tutorial";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
@ -47,6 +38,8 @@ import { WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mys
|
|||||||
import { getNatureName } from "#app/data/nature";
|
import { getNatureName } from "#app/data/nature";
|
||||||
|
|
||||||
export class EncounterPhase extends BattlePhase {
|
export class EncounterPhase extends BattlePhase {
|
||||||
|
// Union type is necessary as this is subclassed, and typescript will otherwise complain
|
||||||
|
public readonly phaseName: "EncounterPhase" | "NextEncounterPhase" | "NewBiomeEncounterPhase" = "EncounterPhase";
|
||||||
private loaded: boolean;
|
private loaded: boolean;
|
||||||
|
|
||||||
constructor(loaded = false) {
|
constructor(loaded = false) {
|
||||||
@ -66,7 +59,7 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
|
|
||||||
// Failsafe if players somehow skip floor 200 in classic mode
|
// Failsafe if players somehow skip floor 200 in classic mode
|
||||||
if (globalScene.gameMode.isClassic && globalScene.currentBattle.waveIndex > 200) {
|
if (globalScene.gameMode.isClassic && globalScene.currentBattle.waveIndex > 200) {
|
||||||
globalScene.unshiftPhase(new GameOverPhase());
|
globalScene.phaseManager.unshiftNew("GameOverPhase");
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadEnemyAssets: Promise<void>[] = [];
|
const loadEnemyAssets: Promise<void>[] = [];
|
||||||
@ -436,9 +429,9 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
const doTrainerSummon = () => {
|
const doTrainerSummon = () => {
|
||||||
this.hideEnemyTrainer();
|
this.hideEnemyTrainer();
|
||||||
const availablePartyMembers = globalScene.getEnemyParty().filter(p => !p.isFainted()).length;
|
const availablePartyMembers = globalScene.getEnemyParty().filter(p => !p.isFainted()).length;
|
||||||
globalScene.unshiftPhase(new SummonPhase(0, false));
|
globalScene.phaseManager.unshiftNew("SummonPhase", 0, false);
|
||||||
if (globalScene.currentBattle.double && availablePartyMembers > 1) {
|
if (globalScene.currentBattle.double && availablePartyMembers > 1) {
|
||||||
globalScene.unshiftPhase(new SummonPhase(1, false));
|
globalScene.phaseManager.unshiftNew("SummonPhase", 1, false);
|
||||||
}
|
}
|
||||||
this.end();
|
this.end();
|
||||||
};
|
};
|
||||||
@ -494,7 +487,7 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
globalScene.ui.clearText();
|
globalScene.ui.clearText();
|
||||||
globalScene.ui.getMessageHandler().hideNameText();
|
globalScene.ui.getMessageHandler().hideNameText();
|
||||||
|
|
||||||
globalScene.unshiftPhase(new MysteryEncounterPhase());
|
globalScene.phaseManager.unshiftNew("MysteryEncounterPhase");
|
||||||
this.end();
|
this.end();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -552,7 +545,7 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
|
|
||||||
enemyField.forEach((enemyPokemon, e) => {
|
enemyField.forEach((enemyPokemon, e) => {
|
||||||
if (enemyPokemon.isShiny(true)) {
|
if (enemyPokemon.isShiny(true)) {
|
||||||
globalScene.unshiftPhase(new ShinySparklePhase(BattlerIndex.ENEMY + e));
|
globalScene.phaseManager.unshiftNew("ShinySparklePhase", BattlerIndex.ENEMY + e);
|
||||||
}
|
}
|
||||||
/** This sets Eternatus' held item to be untransferrable, preventing it from being stolen */
|
/** This sets Eternatus' held item to be untransferrable, preventing it from being stolen */
|
||||||
if (
|
if (
|
||||||
@ -574,25 +567,31 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
|
|
||||||
if (![BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(globalScene.currentBattle.battleType)) {
|
if (![BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(globalScene.currentBattle.battleType)) {
|
||||||
enemyField.map(p =>
|
enemyField.map(p =>
|
||||||
globalScene.pushConditionalPhase(new PostSummonPhase(p.getBattlerIndex()), () => {
|
globalScene.phaseManager.pushConditionalPhase(
|
||||||
// if there is not a player party, we can't continue
|
globalScene.phaseManager.create("PostSummonPhase", p.getBattlerIndex()),
|
||||||
if (!globalScene.getPlayerParty().length) {
|
() => {
|
||||||
return false;
|
// if there is not a player party, we can't continue
|
||||||
}
|
if (!globalScene.getPlayerParty().length) {
|
||||||
// how many player pokemon are on the field ?
|
return false;
|
||||||
const pokemonsOnFieldCount = globalScene.getPlayerParty().filter(p => p.isOnField()).length;
|
}
|
||||||
// if it's a 2vs1, there will never be a 2nd pokemon on our field even
|
// how many player pokemon are on the field ?
|
||||||
const requiredPokemonsOnField = Math.min(globalScene.getPlayerParty().filter(p => !p.isFainted()).length, 2);
|
const pokemonsOnFieldCount = globalScene.getPlayerParty().filter(p => p.isOnField()).length;
|
||||||
// if it's a double, there should be 2, otherwise 1
|
// if it's a 2vs1, there will never be a 2nd pokemon on our field even
|
||||||
if (globalScene.currentBattle.double) {
|
const requiredPokemonsOnField = Math.min(
|
||||||
return pokemonsOnFieldCount === requiredPokemonsOnField;
|
globalScene.getPlayerParty().filter(p => !p.isFainted()).length,
|
||||||
}
|
2,
|
||||||
return pokemonsOnFieldCount === 1;
|
);
|
||||||
}),
|
// if it's a double, there should be 2, otherwise 1
|
||||||
|
if (globalScene.currentBattle.double) {
|
||||||
|
return pokemonsOnFieldCount === requiredPokemonsOnField;
|
||||||
|
}
|
||||||
|
return pokemonsOnFieldCount === 1;
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier);
|
const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier);
|
||||||
if (ivScannerModifier) {
|
if (ivScannerModifier) {
|
||||||
enemyField.map(p => globalScene.pushPhase(new ScanIvsPhase(p.getBattlerIndex())));
|
enemyField.map(p => globalScene.phaseManager.pushNew("ScanIvsPhase", p.getBattlerIndex()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,21 +599,21 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
const availablePartyMembers = globalScene.getPokemonAllowedInBattle();
|
const availablePartyMembers = globalScene.getPokemonAllowedInBattle();
|
||||||
|
|
||||||
if (!availablePartyMembers[0].isOnField()) {
|
if (!availablePartyMembers[0].isOnField()) {
|
||||||
globalScene.pushPhase(new SummonPhase(0));
|
globalScene.phaseManager.pushNew("SummonPhase", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (globalScene.currentBattle.double) {
|
if (globalScene.currentBattle.double) {
|
||||||
if (availablePartyMembers.length > 1) {
|
if (availablePartyMembers.length > 1) {
|
||||||
globalScene.pushPhase(new ToggleDoublePositionPhase(true));
|
globalScene.phaseManager.pushNew("ToggleDoublePositionPhase", true);
|
||||||
if (!availablePartyMembers[1].isOnField()) {
|
if (!availablePartyMembers[1].isOnField()) {
|
||||||
globalScene.pushPhase(new SummonPhase(1));
|
globalScene.phaseManager.pushNew("SummonPhase", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (availablePartyMembers.length > 1 && availablePartyMembers[1].isOnField()) {
|
if (availablePartyMembers.length > 1 && availablePartyMembers[1].isOnField()) {
|
||||||
globalScene.pushPhase(new ReturnPhase(1));
|
globalScene.phaseManager.pushNew("ReturnPhase", 1);
|
||||||
}
|
}
|
||||||
globalScene.pushPhase(new ToggleDoublePositionPhase(false));
|
globalScene.phaseManager.pushNew("ToggleDoublePositionPhase", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -623,9 +622,9 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
) {
|
) {
|
||||||
const minPartySize = globalScene.currentBattle.double ? 2 : 1;
|
const minPartySize = globalScene.currentBattle.double ? 2 : 1;
|
||||||
if (availablePartyMembers.length > minPartySize) {
|
if (availablePartyMembers.length > minPartySize) {
|
||||||
globalScene.pushPhase(new CheckSwitchPhase(0, globalScene.currentBattle.double));
|
globalScene.phaseManager.pushNew("CheckSwitchPhase", 0, globalScene.currentBattle.double);
|
||||||
if (globalScene.currentBattle.double) {
|
if (globalScene.currentBattle.double) {
|
||||||
globalScene.pushPhase(new CheckSwitchPhase(1, globalScene.currentBattle.double));
|
globalScene.phaseManager.pushNew("CheckSwitchPhase", 1, globalScene.currentBattle.double);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import { addTextObject, TextStyle } from "#app/ui/text";
|
|||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class EndCardPhase extends Phase {
|
export class EndCardPhase extends Phase {
|
||||||
|
public readonly phaseName = "EndCardPhase";
|
||||||
public endCard: Phaser.GameObjects.Image;
|
public endCard: Phaser.GameObjects.Image;
|
||||||
public text: Phaser.GameObjects.Text;
|
public text: Phaser.GameObjects.Text;
|
||||||
start(): void {
|
start(): void {
|
||||||
|
@ -3,6 +3,7 @@ import { Phase } from "#app/phase";
|
|||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
|
|
||||||
export class EndEvolutionPhase extends Phase {
|
export class EndEvolutionPhase extends Phase {
|
||||||
|
public readonly phaseName = "EndEvolutionPhase";
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import { BattlerTagType } from "#enums/battler-tag-type";
|
|||||||
* @see {@linkcode EnemyPokemon.getNextMove}
|
* @see {@linkcode EnemyPokemon.getNextMove}
|
||||||
*/
|
*/
|
||||||
export class EnemyCommandPhase extends FieldPhase {
|
export class EnemyCommandPhase extends FieldPhase {
|
||||||
|
public readonly phaseName = "EnemyCommandPhase";
|
||||||
protected fieldIndex: number;
|
protected fieldIndex: number;
|
||||||
protected skipTurn = false;
|
protected skipTurn = false;
|
||||||
|
|
||||||
|
@ -14,11 +14,12 @@ import { LearnMoveSituation } from "#app/field/pokemon";
|
|||||||
import { getTypeRgb } from "#app/data/type";
|
import { getTypeRgb } from "#app/data/type";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
|
||||||
import { EndEvolutionPhase } from "#app/phases/end-evolution-phase";
|
|
||||||
import { EVOLVE_MOVE } from "#app/data/balance/pokemon-level-moves";
|
import { EVOLVE_MOVE } from "#app/data/balance/pokemon-level-moves";
|
||||||
|
|
||||||
export class EvolutionPhase extends Phase {
|
export class EvolutionPhase extends Phase {
|
||||||
|
// FormChangePhase inherits from this, but EvolutionPhase is not abstract.
|
||||||
|
// We have to use the union here
|
||||||
|
public readonly phaseName: "EvolutionPhase" | "FormChangePhase" = "EvolutionPhase";
|
||||||
protected pokemon: PlayerPokemon;
|
protected pokemon: PlayerPokemon;
|
||||||
protected lastLevel: number;
|
protected lastLevel: number;
|
||||||
|
|
||||||
@ -259,7 +260,7 @@ export class EvolutionPhase extends Phase {
|
|||||||
|
|
||||||
SoundFade.fadeOut(globalScene, this.evolutionBgm, 100);
|
SoundFade.fadeOut(globalScene, this.evolutionBgm, 100);
|
||||||
|
|
||||||
globalScene.unshiftPhase(new EndEvolutionPhase());
|
globalScene.phaseManager.unshiftNew("EndEvolutionPhase");
|
||||||
|
|
||||||
globalScene.ui.showText(
|
globalScene.ui.showText(
|
||||||
i18next.t("menu:stoppedEvolving", {
|
i18next.t("menu:stoppedEvolving", {
|
||||||
@ -352,9 +353,13 @@ export class EvolutionPhase extends Phase {
|
|||||||
.getLevelMoves(this.lastLevel + 1, true, false, false, learnSituation)
|
.getLevelMoves(this.lastLevel + 1, true, false, false, learnSituation)
|
||||||
.filter(lm => lm[0] === EVOLVE_MOVE);
|
.filter(lm => lm[0] === EVOLVE_MOVE);
|
||||||
for (const lm of levelMoves) {
|
for (const lm of levelMoves) {
|
||||||
globalScene.unshiftPhase(new LearnMovePhase(globalScene.getPlayerParty().indexOf(this.pokemon), lm[1]));
|
globalScene.phaseManager.unshiftNew(
|
||||||
|
"LearnMovePhase",
|
||||||
|
globalScene.getPlayerParty().indexOf(this.pokemon),
|
||||||
|
lm[1],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
globalScene.unshiftPhase(new EndEvolutionPhase());
|
globalScene.phaseManager.unshiftNew("EndEvolutionPhase");
|
||||||
|
|
||||||
globalScene.playSound("se/shine");
|
globalScene.playSound("se/shine");
|
||||||
this.doSpray();
|
this.doSpray();
|
||||||
|
@ -4,9 +4,9 @@ import { ExpBoosterModifier } from "#app/modifier/modifier";
|
|||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { NumberHolder } from "#app/utils/common";
|
import { NumberHolder } from "#app/utils/common";
|
||||||
import { PlayerPartyMemberPokemonPhase } from "./player-party-member-pokemon-phase";
|
import { PlayerPartyMemberPokemonPhase } from "./player-party-member-pokemon-phase";
|
||||||
import { LevelUpPhase } from "./level-up-phase";
|
|
||||||
|
|
||||||
export class ExpPhase extends PlayerPartyMemberPokemonPhase {
|
export class ExpPhase extends PlayerPartyMemberPokemonPhase {
|
||||||
|
public readonly phaseName = "ExpPhase";
|
||||||
private expValue: number;
|
private expValue: number;
|
||||||
|
|
||||||
constructor(partyMemberIndex: number, expValue: number) {
|
constructor(partyMemberIndex: number, expValue: number) {
|
||||||
@ -33,7 +33,7 @@ export class ExpPhase extends PlayerPartyMemberPokemonPhase {
|
|||||||
pokemon.addExp(exp.value);
|
pokemon.addExp(exp.value);
|
||||||
const newLevel = pokemon.level;
|
const newLevel = pokemon.level;
|
||||||
if (newLevel > lastLevel) {
|
if (newLevel > lastLevel) {
|
||||||
globalScene.unshiftPhase(new LevelUpPhase(this.partyMemberIndex, lastLevel, newLevel));
|
globalScene.phaseManager.unshiftNew("LevelUpPhase", this.partyMemberIndex, lastLevel, newLevel);
|
||||||
}
|
}
|
||||||
pokemon.updateInfo().then(() => this.end());
|
pokemon.updateInfo().then(() => this.end());
|
||||||
},
|
},
|
||||||
|
@ -18,23 +18,19 @@ import { BattleSpec } from "#app/enums/battle-spec";
|
|||||||
import { StatusEffect } from "#app/enums/status-effect";
|
import { StatusEffect } from "#app/enums/status-effect";
|
||||||
import type { EnemyPokemon } from "#app/field/pokemon";
|
import type { EnemyPokemon } from "#app/field/pokemon";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { HitResult, PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
import { HitResult, PokemonMove } from "#app/field/pokemon";
|
||||||
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { PokemonInstantReviveModifier } from "#app/modifier/modifier";
|
import { PokemonInstantReviveModifier } from "#app/modifier/modifier";
|
||||||
import { SwitchType } from "#enums/switch-type";
|
import { SwitchType } from "#enums/switch-type";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { DamageAnimPhase } from "./damage-anim-phase";
|
|
||||||
import { GameOverPhase } from "./game-over-phase";
|
|
||||||
import { PokemonPhase } from "./pokemon-phase";
|
import { PokemonPhase } from "./pokemon-phase";
|
||||||
import { SwitchPhase } from "./switch-phase";
|
|
||||||
import { SwitchSummonPhase } from "./switch-summon-phase";
|
|
||||||
import { ToggleDoublePositionPhase } from "./toggle-double-position-phase";
|
|
||||||
import { VictoryPhase } from "./victory-phase";
|
|
||||||
import { isNullOrUndefined } from "#app/utils/common";
|
import { isNullOrUndefined } from "#app/utils/common";
|
||||||
import { FRIENDSHIP_LOSS_FROM_FAINT } from "#app/data/balance/starters";
|
import { FRIENDSHIP_LOSS_FROM_FAINT } from "#app/data/balance/starters";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
|
|
||||||
export class FaintPhase extends PokemonPhase {
|
export class FaintPhase extends PokemonPhase {
|
||||||
|
public readonly phaseName = "FaintPhase";
|
||||||
/**
|
/**
|
||||||
* Whether or not instant revive should be prevented
|
* Whether or not instant revive should be prevented
|
||||||
*/
|
*/
|
||||||
@ -78,10 +74,15 @@ export class FaintPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** In case the current pokemon was just switched in, make sure it is counted as participating in the combat */
|
/**
|
||||||
|
* In case the current pokemon was just switched in, make sure it is counted as participating in the combat.
|
||||||
|
* For EXP_SHARE purposes, if the current pokemon faints as the combat ends and it was the ONLY player pokemon
|
||||||
|
* involved in combat, it needs to be counted as a participant so the other party pokemon can get their EXP,
|
||||||
|
* so the fainted pokemon has been included.
|
||||||
|
*/
|
||||||
for (const pokemon of globalScene.getPlayerField()) {
|
for (const pokemon of globalScene.getPlayerField()) {
|
||||||
if (pokemon?.isActive(true) && pokemon.isPlayer()) {
|
if (pokemon?.isActive() || pokemon?.isFainted()) {
|
||||||
globalScene.currentBattle.addParticipant(pokemon as PlayerPokemon);
|
globalScene.currentBattle.addParticipant(pokemon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +109,7 @@ export class FaintPhase extends PokemonPhase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("battle:fainted", {
|
i18next.t("battle:fainted", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
}),
|
}),
|
||||||
@ -159,7 +160,7 @@ export class FaintPhase extends PokemonPhase {
|
|||||||
const legalPlayerPartyPokemon = legalPlayerPokemon.filter(p => !p.isActive(true));
|
const legalPlayerPartyPokemon = legalPlayerPokemon.filter(p => !p.isActive(true));
|
||||||
if (!legalPlayerPokemon.length) {
|
if (!legalPlayerPokemon.length) {
|
||||||
/** If the player doesn't have any legal Pokemon, end the game */
|
/** If the player doesn't have any legal Pokemon, end the game */
|
||||||
globalScene.unshiftPhase(new GameOverPhase());
|
globalScene.phaseManager.unshiftNew("GameOverPhase");
|
||||||
} else if (
|
} else if (
|
||||||
globalScene.currentBattle.double &&
|
globalScene.currentBattle.double &&
|
||||||
legalPlayerPokemon.length === 1 &&
|
legalPlayerPokemon.length === 1 &&
|
||||||
@ -169,23 +170,23 @@ export class FaintPhase extends PokemonPhase {
|
|||||||
* If the player has exactly one Pokemon in total at this point in a double battle, and that Pokemon
|
* If the player has exactly one Pokemon in total at this point in a double battle, and that Pokemon
|
||||||
* is already on the field, unshift a phase that moves that Pokemon to center position.
|
* is already on the field, unshift a phase that moves that Pokemon to center position.
|
||||||
*/
|
*/
|
||||||
globalScene.unshiftPhase(new ToggleDoublePositionPhase(true));
|
globalScene.phaseManager.unshiftNew("ToggleDoublePositionPhase", true);
|
||||||
} else if (legalPlayerPartyPokemon.length > 0) {
|
} else if (legalPlayerPartyPokemon.length > 0) {
|
||||||
/**
|
/**
|
||||||
* If previous conditions weren't met, and the player has at least 1 legal Pokemon off the field,
|
* If previous conditions weren't met, and the player has at least 1 legal Pokemon off the field,
|
||||||
* push a phase that prompts the player to summon a Pokemon from their party.
|
* push a phase that prompts the player to summon a Pokemon from their party.
|
||||||
*/
|
*/
|
||||||
globalScene.pushPhase(new SwitchPhase(SwitchType.SWITCH, this.fieldIndex, true, false));
|
globalScene.phaseManager.pushNew("SwitchPhase", SwitchType.SWITCH, this.fieldIndex, true, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
globalScene.unshiftPhase(new VictoryPhase(this.battlerIndex));
|
globalScene.phaseManager.unshiftNew("VictoryPhase", this.battlerIndex);
|
||||||
if ([BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(globalScene.currentBattle.battleType)) {
|
if ([BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(globalScene.currentBattle.battleType)) {
|
||||||
const hasReservePartyMember = !!globalScene
|
const hasReservePartyMember = !!globalScene
|
||||||
.getEnemyParty()
|
.getEnemyParty()
|
||||||
.filter(p => p.isActive() && !p.isOnField() && p.trainerSlot === (pokemon as EnemyPokemon).trainerSlot)
|
.filter(p => p.isActive() && !p.isOnField() && p.trainerSlot === (pokemon as EnemyPokemon).trainerSlot)
|
||||||
.length;
|
.length;
|
||||||
if (hasReservePartyMember) {
|
if (hasReservePartyMember) {
|
||||||
globalScene.pushPhase(new SwitchSummonPhase(SwitchType.SWITCH, this.fieldIndex, -1, false, false));
|
globalScene.phaseManager.pushNew("SwitchSummonPhase", SwitchType.SWITCH, this.fieldIndex, -1, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,7 +198,7 @@ export class FaintPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pokemon.faintCry(() => {
|
pokemon.faintCry(() => {
|
||||||
if (pokemon instanceof PlayerPokemon) {
|
if (pokemon.isPlayer()) {
|
||||||
pokemon.addFriendship(-FRIENDSHIP_LOSS_FROM_FAINT);
|
pokemon.addFriendship(-FRIENDSHIP_LOSS_FROM_FAINT);
|
||||||
}
|
}
|
||||||
pokemon.hideInfo();
|
pokemon.hideInfo();
|
||||||
@ -240,7 +241,7 @@ export class FaintPhase extends PokemonPhase {
|
|||||||
} else {
|
} else {
|
||||||
// Final boss' HP threshold has been bypassed; cancel faint and force check for 2nd phase
|
// Final boss' HP threshold has been bypassed; cancel faint and force check for 2nd phase
|
||||||
enemy.hp++;
|
enemy.hp++;
|
||||||
globalScene.unshiftPhase(new DamageAnimPhase(enemy.getBattlerIndex(), 0, HitResult.INDIRECT));
|
globalScene.phaseManager.unshiftNew("DamageAnimPhase", enemy.getBattlerIndex(), 0, HitResult.INDIRECT);
|
||||||
this.end();
|
this.end();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -7,12 +7,12 @@ import type { PlayerPokemon } from "../field/pokemon";
|
|||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type PartyUiHandler from "../ui/party-ui-handler";
|
import type PartyUiHandler from "../ui/party-ui-handler";
|
||||||
import { getPokemonNameWithAffix } from "../messages";
|
import { getPokemonNameWithAffix } from "../messages";
|
||||||
import { EndEvolutionPhase } from "./end-evolution-phase";
|
|
||||||
import { EvolutionPhase } from "./evolution-phase";
|
import { EvolutionPhase } from "./evolution-phase";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||||
|
|
||||||
export class FormChangePhase extends EvolutionPhase {
|
export class FormChangePhase extends EvolutionPhase {
|
||||||
|
public readonly phaseName = "FormChangePhase";
|
||||||
private formChange: SpeciesFormChange;
|
private formChange: SpeciesFormChange;
|
||||||
private modal: boolean;
|
private modal: boolean;
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ export class FormChangePhase extends EvolutionPhase {
|
|||||||
globalScene.time.delayedCall(900, () => {
|
globalScene.time.delayedCall(900, () => {
|
||||||
this.pokemon.changeForm(this.formChange).then(() => {
|
this.pokemon.changeForm(this.formChange).then(() => {
|
||||||
if (!this.modal) {
|
if (!this.modal) {
|
||||||
globalScene.unshiftPhase(new EndEvolutionPhase());
|
globalScene.phaseManager.unshiftNew("EndEvolutionPhase");
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.playSound("se/shine");
|
globalScene.playSound("se/shine");
|
||||||
|
@ -4,6 +4,7 @@ import i18next from "i18next";
|
|||||||
import { ModifierRewardPhase } from "./modifier-reward-phase";
|
import { ModifierRewardPhase } from "./modifier-reward-phase";
|
||||||
|
|
||||||
export class GameOverModifierRewardPhase extends ModifierRewardPhase {
|
export class GameOverModifierRewardPhase extends ModifierRewardPhase {
|
||||||
|
public readonly phaseName = "GameOverModifierRewardPhase";
|
||||||
doReward(): Promise<void> {
|
doReward(): Promise<void> {
|
||||||
return new Promise<void>(resolve => {
|
return new Promise<void>(resolve => {
|
||||||
const newModifier = this.modifierType.newModifier();
|
const newModifier = this.modifierType.newModifier();
|
||||||
|
@ -9,14 +9,7 @@ import { trainerConfigs } from "#app/data/trainers/trainer-config";
|
|||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { BattlePhase } from "#app/phases/battle-phase";
|
import { BattlePhase } from "#app/phases/battle-phase";
|
||||||
import { CheckSwitchPhase } from "#app/phases/check-switch-phase";
|
import type { EndCardPhase } from "#app/phases/end-card-phase";
|
||||||
import { EncounterPhase } from "#app/phases/encounter-phase";
|
|
||||||
import { EndCardPhase } from "#app/phases/end-card-phase";
|
|
||||||
import { GameOverModifierRewardPhase } from "#app/phases/game-over-modifier-reward-phase";
|
|
||||||
import { PostGameOverPhase } from "#app/phases/post-game-over-phase";
|
|
||||||
import { RibbonModifierRewardPhase } from "#app/phases/ribbon-modifier-reward-phase";
|
|
||||||
import { SummonPhase } from "#app/phases/summon-phase";
|
|
||||||
import { UnlockPhase } from "#app/phases/unlock-phase";
|
|
||||||
import { achvs, ChallengeAchv } from "#app/system/achv";
|
import { achvs, ChallengeAchv } from "#app/system/achv";
|
||||||
import { Unlockables } from "#app/system/unlockables";
|
import { Unlockables } from "#app/system/unlockables";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
@ -31,9 +24,9 @@ import ChallengeData from "#app/system/challenge-data";
|
|||||||
import TrainerData from "#app/system/trainer-data";
|
import TrainerData from "#app/system/trainer-data";
|
||||||
import ArenaData from "#app/system/arena-data";
|
import ArenaData from "#app/system/arena-data";
|
||||||
import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
|
import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
|
||||||
import { MessagePhase } from "./message-phase";
|
|
||||||
|
|
||||||
export class GameOverPhase extends BattlePhase {
|
export class GameOverPhase extends BattlePhase {
|
||||||
|
public readonly phaseName = "GameOverPhase";
|
||||||
private isVictory: boolean;
|
private isVictory: boolean;
|
||||||
private firstRibbons: PokemonSpecies[] = [];
|
private firstRibbons: PokemonSpecies[] = [];
|
||||||
|
|
||||||
@ -46,7 +39,7 @@ export class GameOverPhase extends BattlePhase {
|
|||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
globalScene.hideAbilityBar();
|
globalScene.phaseManager.hideAbilityBar();
|
||||||
|
|
||||||
// Failsafe if players somehow skip floor 200 in classic mode
|
// Failsafe if players somehow skip floor 200 in classic mode
|
||||||
if (globalScene.gameMode.isClassic && globalScene.currentBattle.waveIndex > 200) {
|
if (globalScene.gameMode.isClassic && globalScene.currentBattle.waveIndex > 200) {
|
||||||
@ -83,23 +76,23 @@ export class GameOverPhase extends BattlePhase {
|
|||||||
() => {
|
() => {
|
||||||
globalScene.ui.fadeOut(1250).then(() => {
|
globalScene.ui.fadeOut(1250).then(() => {
|
||||||
globalScene.reset();
|
globalScene.reset();
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.gameData.loadSession(globalScene.sessionSlotId).then(() => {
|
globalScene.gameData.loadSession(globalScene.sessionSlotId).then(() => {
|
||||||
globalScene.pushPhase(new EncounterPhase(true));
|
globalScene.phaseManager.pushNew("EncounterPhase", true);
|
||||||
|
|
||||||
const availablePartyMembers = globalScene.getPokemonAllowedInBattle().length;
|
const availablePartyMembers = globalScene.getPokemonAllowedInBattle().length;
|
||||||
|
|
||||||
globalScene.pushPhase(new SummonPhase(0));
|
globalScene.phaseManager.pushNew("SummonPhase", 0);
|
||||||
if (globalScene.currentBattle.double && availablePartyMembers > 1) {
|
if (globalScene.currentBattle.double && availablePartyMembers > 1) {
|
||||||
globalScene.pushPhase(new SummonPhase(1));
|
globalScene.phaseManager.pushNew("SummonPhase", 1);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
globalScene.currentBattle.waveIndex > 1 &&
|
globalScene.currentBattle.waveIndex > 1 &&
|
||||||
globalScene.currentBattle.battleType !== BattleType.TRAINER
|
globalScene.currentBattle.battleType !== BattleType.TRAINER
|
||||||
) {
|
) {
|
||||||
globalScene.pushPhase(new CheckSwitchPhase(0, globalScene.currentBattle.double));
|
globalScene.phaseManager.pushNew("CheckSwitchPhase", 0, globalScene.currentBattle.double);
|
||||||
if (globalScene.currentBattle.double && availablePartyMembers > 1) {
|
if (globalScene.currentBattle.double && availablePartyMembers > 1) {
|
||||||
globalScene.pushPhase(new CheckSwitchPhase(1, globalScene.currentBattle.double));
|
globalScene.phaseManager.pushNew("CheckSwitchPhase", 1, globalScene.currentBattle.double);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +140,7 @@ export class GameOverPhase extends BattlePhase {
|
|||||||
globalScene.ui.fadeOut(fadeDuration).then(() => {
|
globalScene.ui.fadeOut(fadeDuration).then(() => {
|
||||||
activeBattlers.map(a => a.setVisible(false));
|
activeBattlers.map(a => a.setVisible(false));
|
||||||
globalScene.setFieldScale(1, true);
|
globalScene.setFieldScale(1, true);
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.ui.clearText();
|
globalScene.ui.clearText();
|
||||||
|
|
||||||
if (this.isVictory && globalScene.gameMode.isChallenge) {
|
if (this.isVictory && globalScene.gameMode.isChallenge) {
|
||||||
@ -159,15 +152,15 @@ export class GameOverPhase extends BattlePhase {
|
|||||||
this.handleUnlocks();
|
this.handleUnlocks();
|
||||||
|
|
||||||
for (const species of this.firstRibbons) {
|
for (const species of this.firstRibbons) {
|
||||||
globalScene.unshiftPhase(new RibbonModifierRewardPhase(modifierTypes.VOUCHER_PLUS, species));
|
globalScene.phaseManager.unshiftNew("RibbonModifierRewardPhase", modifierTypes.VOUCHER_PLUS, species);
|
||||||
}
|
}
|
||||||
if (!firstClear) {
|
if (!firstClear) {
|
||||||
globalScene.unshiftPhase(new GameOverModifierRewardPhase(modifierTypes.VOUCHER_PREMIUM));
|
globalScene.phaseManager.unshiftNew("GameOverModifierRewardPhase", modifierTypes.VOUCHER_PREMIUM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.getRunHistoryEntry().then(runHistoryEntry => {
|
this.getRunHistoryEntry().then(runHistoryEntry => {
|
||||||
globalScene.gameData.saveRunHistory(runHistoryEntry, this.isVictory);
|
globalScene.gameData.saveRunHistory(runHistoryEntry, this.isVictory);
|
||||||
globalScene.pushPhase(new PostGameOverPhase(endCardPhase));
|
globalScene.phaseManager.pushNew("PostGameOverPhase", endCardPhase);
|
||||||
this.end();
|
this.end();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -196,8 +189,8 @@ export class GameOverPhase extends BattlePhase {
|
|||||||
() => {
|
() => {
|
||||||
globalScene.ui.fadeOut(500).then(() => {
|
globalScene.ui.fadeOut(500).then(() => {
|
||||||
globalScene.charSprite.hide().then(() => {
|
globalScene.charSprite.hide().then(() => {
|
||||||
const endCardPhase = new EndCardPhase();
|
const endCardPhase = globalScene.phaseManager.create("EndCardPhase");
|
||||||
globalScene.unshiftPhase(endCardPhase);
|
globalScene.phaseManager.unshiftPhase(endCardPhase);
|
||||||
clear(endCardPhase);
|
clear(endCardPhase);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -206,8 +199,8 @@ export class GameOverPhase extends BattlePhase {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const endCardPhase = new EndCardPhase();
|
const endCardPhase = globalScene.phaseManager.create("EndCardPhase");
|
||||||
globalScene.unshiftPhase(endCardPhase);
|
globalScene.phaseManager.unshiftPhase(endCardPhase);
|
||||||
clear(endCardPhase);
|
clear(endCardPhase);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -229,9 +222,9 @@ export class GameOverPhase extends BattlePhase {
|
|||||||
})
|
})
|
||||||
.then(success => doGameOver(!globalScene.gameMode.isDaily || !!success))
|
.then(success => doGameOver(!globalScene.gameMode.isDaily || !!success))
|
||||||
.catch(_err => {
|
.catch(_err => {
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.clearPhaseQueueSplice();
|
globalScene.phaseManager.clearPhaseQueueSplice();
|
||||||
globalScene.unshiftPhase(new MessagePhase(i18next.t("menu:serverCommunicationFailed"), 2500));
|
globalScene.phaseManager.unshiftNew("MessagePhase", i18next.t("menu:serverCommunicationFailed"), 2500);
|
||||||
// force the game to reload after 2 seconds.
|
// force the game to reload after 2 seconds.
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
@ -250,22 +243,22 @@ export class GameOverPhase extends BattlePhase {
|
|||||||
handleUnlocks(): void {
|
handleUnlocks(): void {
|
||||||
if (this.isVictory && globalScene.gameMode.isClassic) {
|
if (this.isVictory && globalScene.gameMode.isClassic) {
|
||||||
if (!globalScene.gameData.unlocks[Unlockables.ENDLESS_MODE]) {
|
if (!globalScene.gameData.unlocks[Unlockables.ENDLESS_MODE]) {
|
||||||
globalScene.unshiftPhase(new UnlockPhase(Unlockables.ENDLESS_MODE));
|
globalScene.phaseManager.unshiftNew("UnlockPhase", Unlockables.ENDLESS_MODE);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
globalScene.getPlayerParty().filter(p => p.fusionSpecies).length &&
|
globalScene.getPlayerParty().filter(p => p.fusionSpecies).length &&
|
||||||
!globalScene.gameData.unlocks[Unlockables.SPLICED_ENDLESS_MODE]
|
!globalScene.gameData.unlocks[Unlockables.SPLICED_ENDLESS_MODE]
|
||||||
) {
|
) {
|
||||||
globalScene.unshiftPhase(new UnlockPhase(Unlockables.SPLICED_ENDLESS_MODE));
|
globalScene.phaseManager.unshiftNew("UnlockPhase", Unlockables.SPLICED_ENDLESS_MODE);
|
||||||
}
|
}
|
||||||
if (!globalScene.gameData.unlocks[Unlockables.MINI_BLACK_HOLE]) {
|
if (!globalScene.gameData.unlocks[Unlockables.MINI_BLACK_HOLE]) {
|
||||||
globalScene.unshiftPhase(new UnlockPhase(Unlockables.MINI_BLACK_HOLE));
|
globalScene.phaseManager.unshiftNew("UnlockPhase", Unlockables.MINI_BLACK_HOLE);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
!globalScene.gameData.unlocks[Unlockables.EVIOLITE] &&
|
!globalScene.gameData.unlocks[Unlockables.EVIOLITE] &&
|
||||||
globalScene.getPlayerParty().some(p => p.getSpeciesForm(true).speciesId in pokemonEvolutions)
|
globalScene.getPlayerParty().some(p => p.getSpeciesForm(true).speciesId in pokemonEvolutions)
|
||||||
) {
|
) {
|
||||||
globalScene.unshiftPhase(new UnlockPhase(Unlockables.EVIOLITE));
|
globalScene.phaseManager.unshiftNew("UnlockPhase", Unlockables.EVIOLITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { Phase } from "#app/phase";
|
import { Phase } from "#app/phase";
|
||||||
|
|
||||||
export class HideAbilityPhase extends Phase {
|
export class HideAbilityPhase extends Phase {
|
||||||
|
public readonly phaseName = "HideAbilityPhase";
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { BattlePhase } from "./battle-phase";
|
import { BattlePhase } from "./battle-phase";
|
||||||
|
|
||||||
export class HidePartyExpBarPhase extends BattlePhase {
|
export class HidePartyExpBarPhase extends BattlePhase {
|
||||||
|
public readonly phaseName = "HidePartyExpBarPhase";
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ import { UiMode } from "#enums/ui-mode";
|
|||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase";
|
import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
|
||||||
|
|
||||||
export enum LearnMoveType {
|
export enum LearnMoveType {
|
||||||
/** For learning a move via level-up, evolution, or other non-item-based event */
|
/** For learning a move via level-up, evolution, or other non-item-based event */
|
||||||
@ -24,6 +23,7 @@ export enum LearnMoveType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
||||||
|
public readonly phaseName = "LearnMovePhase";
|
||||||
private moveId: MoveId;
|
private moveId: MoveId;
|
||||||
private messageMode: UiMode;
|
private messageMode: UiMode;
|
||||||
private learnMoveType: LearnMoveType;
|
private learnMoveType: LearnMoveType;
|
||||||
@ -195,7 +195,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
|||||||
pokemon.usedTMs = [];
|
pokemon.usedTMs = [];
|
||||||
}
|
}
|
||||||
pokemon.usedTMs.push(this.moveId);
|
pokemon.usedTMs.push(this.moveId);
|
||||||
globalScene.tryRemovePhase(phase => phase instanceof SelectModifierPhase);
|
globalScene.phaseManager.tryRemovePhase(phase => phase.is("SelectModifierPhase"));
|
||||||
} else if (this.learnMoveType === LearnMoveType.MEMORY) {
|
} else if (this.learnMoveType === LearnMoveType.MEMORY) {
|
||||||
if (this.cost !== -1) {
|
if (this.cost !== -1) {
|
||||||
if (!Overrides.WAIVE_ROLL_FEE_OVERRIDE) {
|
if (!Overrides.WAIVE_ROLL_FEE_OVERRIDE) {
|
||||||
@ -205,7 +205,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
|||||||
}
|
}
|
||||||
globalScene.playSound("se/buy");
|
globalScene.playSound("se/buy");
|
||||||
} else {
|
} else {
|
||||||
globalScene.tryRemovePhase(phase => phase instanceof SelectModifierPhase);
|
globalScene.phaseManager.tryRemovePhase(phase => phase.is("SelectModifierPhase"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pokemon.setMove(index, this.moveId);
|
pokemon.setMove(index, this.moveId);
|
||||||
|
@ -4,6 +4,7 @@ import i18next from "i18next";
|
|||||||
import { FieldPhase } from "./field-phase";
|
import { FieldPhase } from "./field-phase";
|
||||||
|
|
||||||
export class LevelCapPhase extends FieldPhase {
|
export class LevelCapPhase extends FieldPhase {
|
||||||
|
public readonly phaseName = "LevelCapPhase";
|
||||||
start(): void {
|
start(): void {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
|
@ -2,14 +2,13 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { ExpNotification } from "#app/enums/exp-notification";
|
import { ExpNotification } from "#app/enums/exp-notification";
|
||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { EvolutionPhase } from "#app/phases/evolution-phase";
|
|
||||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
|
||||||
import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase";
|
import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase";
|
||||||
import { LevelAchv } from "#app/system/achv";
|
import { LevelAchv } from "#app/system/achv";
|
||||||
import { NumberHolder } from "#app/utils/common";
|
import { NumberHolder } from "#app/utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class LevelUpPhase extends PlayerPartyMemberPokemonPhase {
|
export class LevelUpPhase extends PlayerPartyMemberPokemonPhase {
|
||||||
|
public readonly phaseName = "LevelUpPhase";
|
||||||
protected lastLevel: number;
|
protected lastLevel: number;
|
||||||
protected level: number;
|
protected level: number;
|
||||||
protected pokemon: PlayerPokemon = this.getPlayerPokemon();
|
protected pokemon: PlayerPokemon = this.getPlayerPokemon();
|
||||||
@ -65,14 +64,14 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase {
|
|||||||
// this feels like an unnecessary optimization
|
// this feels like an unnecessary optimization
|
||||||
const levelMoves = this.getPokemon().getLevelMoves(this.lastLevel + 1);
|
const levelMoves = this.getPokemon().getLevelMoves(this.lastLevel + 1);
|
||||||
for (const lm of levelMoves) {
|
for (const lm of levelMoves) {
|
||||||
globalScene.unshiftPhase(new LearnMovePhase(this.partyMemberIndex, lm[1]));
|
globalScene.phaseManager.unshiftNew("LearnMovePhase", this.partyMemberIndex, lm[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!this.pokemon.pauseEvolutions) {
|
if (!this.pokemon.pauseEvolutions) {
|
||||||
const evolution = this.pokemon.getEvolution();
|
const evolution = this.pokemon.getEvolution();
|
||||||
if (evolution) {
|
if (evolution) {
|
||||||
this.pokemon.breakIllusion();
|
this.pokemon.breakIllusion();
|
||||||
globalScene.unshiftPhase(new EvolutionPhase(this.pokemon, evolution, this.lastLevel));
|
globalScene.phaseManager.unshiftNew("EvolutionPhase", this.pokemon, evolution, this.lastLevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.end();
|
return super.end();
|
||||||
|
@ -8,6 +8,7 @@ import { Phase } from "#app/phase";
|
|||||||
* isn't already loaded (e.g. for Metronome)
|
* isn't already loaded (e.g. for Metronome)
|
||||||
*/
|
*/
|
||||||
export class LoadMoveAnimPhase extends Phase {
|
export class LoadMoveAnimPhase extends Phase {
|
||||||
|
public readonly phaseName = "LoadMoveAnimPhase";
|
||||||
constructor(protected moveId: MoveId) {
|
constructor(protected moveId: MoveId) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,9 @@ import { UiMode } from "#enums/ui-mode";
|
|||||||
import i18next, { t } from "i18next";
|
import i18next, { t } from "i18next";
|
||||||
import { sessionIdKey, executeIf } from "#app/utils/common";
|
import { sessionIdKey, executeIf } from "#app/utils/common";
|
||||||
import { getCookie, removeCookie } from "#app/utils/cookies";
|
import { getCookie, removeCookie } from "#app/utils/cookies";
|
||||||
import { SelectGenderPhase } from "./select-gender-phase";
|
|
||||||
import { UnavailablePhase } from "./unavailable-phase";
|
|
||||||
|
|
||||||
export class LoginPhase extends Phase {
|
export class LoginPhase extends Phase {
|
||||||
|
public readonly phaseName = "LoginPhase";
|
||||||
private showText: boolean;
|
private showText: boolean;
|
||||||
|
|
||||||
constructor(showText = true) {
|
constructor(showText = true) {
|
||||||
@ -69,7 +68,7 @@ export class LoginPhase extends Phase {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
globalScene.unshiftPhase(new LoginPhase(false));
|
globalScene.phaseManager.unshiftNew("LoginPhase", false);
|
||||||
this.end();
|
this.end();
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -93,7 +92,7 @@ export class LoginPhase extends Phase {
|
|||||||
removeCookie(sessionIdKey);
|
removeCookie(sessionIdKey);
|
||||||
globalScene.reset(true, true);
|
globalScene.reset(true, true);
|
||||||
} else {
|
} else {
|
||||||
globalScene.unshiftPhase(new UnavailablePhase());
|
globalScene.phaseManager.unshiftNew("UnavailablePhase");
|
||||||
super.end();
|
super.end();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -113,7 +112,7 @@ export class LoginPhase extends Phase {
|
|||||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
globalScene.ui.setMode(UiMode.MESSAGE);
|
||||||
|
|
||||||
if (!globalScene.gameData.gender) {
|
if (!globalScene.gameData.gender) {
|
||||||
globalScene.unshiftPhase(new SelectGenderPhase());
|
globalScene.phaseManager.unshiftNew("SelectGenderPhase");
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTutorial(Tutorial.Intro).then(() => super.end());
|
handleTutorial(Tutorial.Intro).then(() => super.end());
|
||||||
|
@ -2,6 +2,7 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { Phase } from "#app/phase";
|
import { Phase } from "#app/phase";
|
||||||
|
|
||||||
export class MessagePhase extends Phase {
|
export class MessagePhase extends Phase {
|
||||||
|
public readonly phaseName = "MessagePhase";
|
||||||
private text: string;
|
private text: string;
|
||||||
private callbackDelay?: number | null;
|
private callbackDelay?: number | null;
|
||||||
private prompt?: boolean | null;
|
private prompt?: boolean | null;
|
||||||
@ -43,8 +44,13 @@ export class MessagePhase extends Phase {
|
|||||||
page0 = page0.split(repname[p]).join(pokename[p]);
|
page0 = page0.split(repname[p]).join(pokename[p]);
|
||||||
page1 = page1.split(repname[p]).join(pokename[p]);
|
page1 = page1.split(repname[p]).join(pokename[p]);
|
||||||
}
|
}
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new MessagePhase(page1, this.callbackDelay, this.prompt, this.promptDelay, this.speaker),
|
"MessagePhase",
|
||||||
|
page1,
|
||||||
|
this.callbackDelay,
|
||||||
|
this.prompt,
|
||||||
|
this.promptDelay,
|
||||||
|
this.speaker,
|
||||||
);
|
);
|
||||||
this.text = page0.trim();
|
this.text = page0.trim();
|
||||||
} else {
|
} else {
|
||||||
|
@ -5,6 +5,10 @@ import i18next from "i18next";
|
|||||||
import { BattlePhase } from "./battle-phase";
|
import { BattlePhase } from "./battle-phase";
|
||||||
|
|
||||||
export class ModifierRewardPhase extends BattlePhase {
|
export class ModifierRewardPhase extends BattlePhase {
|
||||||
|
// RibbonModifierRewardPhase extends ModifierRewardPhase and to make typescript happy
|
||||||
|
// we need to use a union type here
|
||||||
|
public readonly phaseName: "ModifierRewardPhase" | "RibbonModifierRewardPhase" | "GameOverModifierRewardPhase" =
|
||||||
|
"ModifierRewardPhase";
|
||||||
protected modifierType: ModifierType;
|
protected modifierType: ModifierType;
|
||||||
|
|
||||||
constructor(modifierTypeFunc: ModifierTypeFunc) {
|
constructor(modifierTypeFunc: ModifierTypeFunc) {
|
||||||
|
@ -6,6 +6,7 @@ import { NumberHolder } from "#app/utils/common";
|
|||||||
import { BattlePhase } from "./battle-phase";
|
import { BattlePhase } from "./battle-phase";
|
||||||
|
|
||||||
export class MoneyRewardPhase extends BattlePhase {
|
export class MoneyRewardPhase extends BattlePhase {
|
||||||
|
public readonly phaseName = "MoneyRewardPhase";
|
||||||
private moneyMultiplier: number;
|
private moneyMultiplier: number;
|
||||||
|
|
||||||
constructor(moneyMultiplier: number) {
|
constructor(moneyMultiplier: number) {
|
||||||
|
@ -5,6 +5,8 @@ import { Phase } from "#app/phase";
|
|||||||
* Plays the given {@linkcode MoveAnim} sequentially.
|
* Plays the given {@linkcode MoveAnim} sequentially.
|
||||||
*/
|
*/
|
||||||
export class MoveAnimPhase<Anim extends MoveAnim> extends Phase {
|
export class MoveAnimPhase<Anim extends MoveAnim> extends Phase {
|
||||||
|
public readonly phaseName = "MoveAnimPhase";
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected anim: Anim,
|
protected anim: Anim,
|
||||||
protected onSubstitute = false,
|
protected onSubstitute = false,
|
||||||
|
@ -6,16 +6,15 @@ import type { PokemonMove } from "#app/field/pokemon";
|
|||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { MoveResult } from "#app/field/pokemon";
|
import { MoveResult } from "#app/field/pokemon";
|
||||||
import { BooleanHolder } from "#app/utils/common";
|
import { BooleanHolder } from "#app/utils/common";
|
||||||
import { MovePhase } from "#app/phases/move-phase";
|
|
||||||
import { PokemonPhase } from "#app/phases/pokemon-phase";
|
import { PokemonPhase } from "#app/phases/pokemon-phase";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Phase for the "charging turn" of two-turn moves (e.g. Dig).
|
* Phase for the "charging turn" of two-turn moves (e.g. Dig).
|
||||||
* @extends {@linkcode PokemonPhase}
|
* @extends {@linkcode PokemonPhase}
|
||||||
*/
|
*/
|
||||||
export class MoveChargePhase extends PokemonPhase {
|
export class MoveChargePhase extends PokemonPhase {
|
||||||
|
public readonly phaseName = "MoveChargePhase";
|
||||||
/** The move instance that this phase applies */
|
/** The move instance that this phase applies */
|
||||||
public move: PokemonMove;
|
public move: PokemonMove;
|
||||||
/** The field index targeted by the move (Charging moves assume single target) */
|
/** The field index targeted by the move (Charging moves assume single target) */
|
||||||
@ -62,9 +61,9 @@ export class MoveChargePhase extends PokemonPhase {
|
|||||||
|
|
||||||
if (instantCharge.value) {
|
if (instantCharge.value) {
|
||||||
// this MoveEndPhase will be duplicated by the queued MovePhase if not removed
|
// this MoveEndPhase will be duplicated by the queued MovePhase if not removed
|
||||||
globalScene.tryRemovePhase(phase => phase instanceof MoveEndPhase && phase.getPokemon() === user);
|
globalScene.phaseManager.tryRemovePhase(phase => phase.is("MoveEndPhase") && phase.getPokemon() === user);
|
||||||
// queue a new MovePhase for this move's attack phase
|
// queue a new MovePhase for this move's attack phase
|
||||||
globalScene.unshiftPhase(new MovePhase(user, [this.targetIndex], this.move, false));
|
globalScene.phaseManager.unshiftNew("MovePhase", user, [this.targetIndex], this.move, false);
|
||||||
} else {
|
} else {
|
||||||
user.getMoveQueue().push({ move: move.id, targets: [this.targetIndex] });
|
user.getMoveQueue().push({ move: move.id, targets: [this.targetIndex] });
|
||||||
}
|
}
|
||||||
|
@ -68,20 +68,16 @@ import { BattlerTagType } from "#enums/battler-tag-type";
|
|||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import type { Phase } from "#app/phase";
|
import type { Phase } from "#app/phase";
|
||||||
import { ShowAbilityPhase } from "./show-ability-phase";
|
|
||||||
import { MovePhase } from "./move-phase";
|
|
||||||
import { MoveEndPhase } from "./move-end-phase";
|
|
||||||
import { HideAbilityPhase } from "#app/phases/hide-ability-phase";
|
|
||||||
import type { TypeDamageMultiplier } from "#app/data/type";
|
import type { TypeDamageMultiplier } from "#app/data/type";
|
||||||
import { HitCheckResult } from "#enums/hit-check-result";
|
import { HitCheckResult } from "#enums/hit-check-result";
|
||||||
import type Move from "#app/data/moves/move";
|
import type Move from "#app/data/moves/move";
|
||||||
import { isFieldTargeted } from "#app/data/moves/move-utils";
|
import { isFieldTargeted } from "#app/data/moves/move-utils";
|
||||||
import { FaintPhase } from "./faint-phase";
|
|
||||||
import { DamageAchv } from "#app/system/achv";
|
import { DamageAchv } from "#app/system/achv";
|
||||||
|
|
||||||
type HitCheckEntry = [HitCheckResult, TypeDamageMultiplier];
|
type HitCheckEntry = [HitCheckResult, TypeDamageMultiplier];
|
||||||
|
|
||||||
export class MoveEffectPhase extends PokemonPhase {
|
export class MoveEffectPhase extends PokemonPhase {
|
||||||
|
public readonly phaseName = "MoveEffectPhase";
|
||||||
public move: Move;
|
public move: Move;
|
||||||
private virtual = false;
|
private virtual = false;
|
||||||
protected targets: BattlerIndex[];
|
protected targets: BattlerIndex[];
|
||||||
@ -190,13 +186,25 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
// TODO: ability displays should be handled by the ability
|
// TODO: ability displays should be handled by the ability
|
||||||
if (!target.getTag(BattlerTagType.MAGIC_COAT)) {
|
if (!target.getTag(BattlerTagType.MAGIC_COAT)) {
|
||||||
this.queuedPhases.push(
|
this.queuedPhases.push(
|
||||||
new ShowAbilityPhase(target.getBattlerIndex(), target.getPassiveAbility().hasAttr(ReflectStatusMoveAbAttr)),
|
globalScene.phaseManager.create(
|
||||||
|
"ShowAbilityPhase",
|
||||||
|
target.getBattlerIndex(),
|
||||||
|
target.getPassiveAbility().hasAttr(ReflectStatusMoveAbAttr),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
this.queuedPhases.push(new HideAbilityPhase());
|
this.queuedPhases.push(globalScene.phaseManager.create("HideAbilityPhase"));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.queuedPhases.push(
|
this.queuedPhases.push(
|
||||||
new MovePhase(target, newTargets, new PokemonMove(this.move.id, 0, 0, true), true, true, true),
|
globalScene.phaseManager.create(
|
||||||
|
"MovePhase",
|
||||||
|
target,
|
||||||
|
newTargets,
|
||||||
|
new PokemonMove(this.move.id, 0, 0, true),
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,8 +226,9 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
// biome-ignore lint/suspicious/noFallthroughSwitchClause: The fallthrough is intentional
|
||||||
case HitCheckResult.NO_EFFECT:
|
case HitCheckResult.NO_EFFECT:
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(this.move.id === MoveId.SHEER_COLD ? "battle:hitResultImmune" : "battle:hitResultNoEffect", {
|
i18next.t(this.move.id === MoveId.SHEER_COLD ? "battle:hitResultImmune" : "battle:hitResultNoEffect", {
|
||||||
pokemonName: getPokemonNameWithAffix(target),
|
pokemonName: getPokemonNameWithAffix(target),
|
||||||
}),
|
}),
|
||||||
@ -230,7 +239,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
applyMoveAttrs(NoEffectAttr, user, target, this.move);
|
applyMoveAttrs(NoEffectAttr, user, target, this.move);
|
||||||
break;
|
break;
|
||||||
case HitCheckResult.MISS:
|
case HitCheckResult.MISS:
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("battle:attackMissed", { pokemonNameWithAffix: getPokemonNameWithAffix(target) }),
|
i18next.t("battle:attackMissed", { pokemonNameWithAffix: getPokemonNameWithAffix(target) }),
|
||||||
);
|
);
|
||||||
applyMoveAttrs(MissEffectAttr, user, target, this.move);
|
applyMoveAttrs(MissEffectAttr, user, target, this.move);
|
||||||
@ -293,7 +302,8 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
|
|
||||||
// If other effects were overriden, stop this phase before they can be applied
|
// If other effects were overriden, stop this phase before they can be applied
|
||||||
if (overridden.value) {
|
if (overridden.value) {
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lapse `MOVE_EFFECT` effects (i.e. semi-invulnerability) when applicable
|
// Lapse `MOVE_EFFECT` effects (i.e. semi-invulnerability) when applicable
|
||||||
@ -381,7 +391,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.queuedPhases.length) {
|
if (this.queuedPhases.length) {
|
||||||
globalScene.appendToPhase(this.queuedPhases, MoveEndPhase);
|
globalScene.phaseManager.appendToPhase(this.queuedPhases, "MoveEndPhase");
|
||||||
}
|
}
|
||||||
const moveType = user.getMoveType(this.move, true);
|
const moveType = user.getMoveType(this.move, true);
|
||||||
if (this.move.category !== MoveCategory.STATUS && !user.stellarTypesBoosted.includes(moveType)) {
|
if (this.move.category !== MoveCategory.STATUS && !user.stellarTypesBoosted.includes(moveType)) {
|
||||||
@ -407,14 +417,14 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
*/
|
*/
|
||||||
if (user) {
|
if (user) {
|
||||||
if (user.turnData.hitsLeft && --user.turnData.hitsLeft >= 1 && this.getFirstTarget()?.isActive()) {
|
if (user.turnData.hitsLeft && --user.turnData.hitsLeft >= 1 && this.getFirstTarget()?.isActive()) {
|
||||||
globalScene.unshiftPhase(this.getNewHitPhase());
|
globalScene.phaseManager.unshiftPhase(this.getNewHitPhase());
|
||||||
} else {
|
} else {
|
||||||
// Queue message for number of hits made by multi-move
|
// Queue message for number of hits made by multi-move
|
||||||
// If multi-hit attack only hits once, still want to render a message
|
// If multi-hit attack only hits once, still want to render a message
|
||||||
const hitsTotal = user.turnData.hitCount - Math.max(user.turnData.hitsLeft, 0);
|
const hitsTotal = user.turnData.hitCount - Math.max(user.turnData.hitsLeft, 0);
|
||||||
if (hitsTotal > 1 || (user.turnData.hitsLeft && user.turnData.hitsLeft > 0)) {
|
if (hitsTotal > 1 || (user.turnData.hitsLeft && user.turnData.hitsLeft > 0)) {
|
||||||
// If there are multiple hits, or if there are hits of the multi-hit move left
|
// If there are multiple hits, or if there are hits of the multi-hit move left
|
||||||
globalScene.queueMessage(i18next.t("battle:attackHitsCount", { count: hitsTotal }));
|
globalScene.phaseManager.queueMessage(i18next.t("battle:attackHitsCount", { count: hitsTotal }));
|
||||||
}
|
}
|
||||||
globalScene.applyModifiers(HitHealModifier, this.player, user);
|
globalScene.applyModifiers(HitHealModifier, this.player, user);
|
||||||
this.getTargets().forEach(target => (target.turnData.moveEffectiveness = null));
|
this.getTargets().forEach(target => (target.turnData.moveEffectiveness = null));
|
||||||
@ -742,7 +752,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
firstTarget?: boolean | null,
|
firstTarget?: boolean | null,
|
||||||
selfTarget?: boolean,
|
selfTarget?: boolean,
|
||||||
): void {
|
): void {
|
||||||
return applyFilteredMoveAttrs(
|
applyFilteredMoveAttrs(
|
||||||
(attr: MoveAttr) =>
|
(attr: MoveAttr) =>
|
||||||
attr instanceof MoveEffectAttr &&
|
attr instanceof MoveEffectAttr &&
|
||||||
attr.trigger === triggerType &&
|
attr.trigger === triggerType &&
|
||||||
@ -855,7 +865,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (isCritical) {
|
if (isCritical) {
|
||||||
globalScene.queueMessage(i18next.t("battle:hitResultCriticalHit"));
|
globalScene.phaseManager.queueMessage(i18next.t("battle:hitResultCriticalHit"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (damage <= 0) {
|
if (damage <= 0) {
|
||||||
@ -884,7 +894,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
sourceBattlerIndex: user.getBattlerIndex(),
|
sourceBattlerIndex: user.getBattlerIndex(),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (user.isPlayer() && !target.isPlayer()) {
|
if (user.isPlayer() && target.isEnemy()) {
|
||||||
globalScene.applyModifiers(DamageMoneyRewardModifier, true, user, new NumberHolder(damage));
|
globalScene.applyModifiers(DamageMoneyRewardModifier, true, user, new NumberHolder(damage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -898,9 +908,9 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
*/
|
*/
|
||||||
protected onFaintTarget(user: Pokemon, target: Pokemon): void {
|
protected onFaintTarget(user: Pokemon, target: Pokemon): void {
|
||||||
// set splice index here, so future scene queues happen before FaintedPhase
|
// set splice index here, so future scene queues happen before FaintedPhase
|
||||||
globalScene.setPhaseQueueSplice();
|
globalScene.phaseManager.setPhaseQueueSplice();
|
||||||
|
|
||||||
globalScene.unshiftPhase(new FaintPhase(target.getBattlerIndex(), false, user));
|
globalScene.phaseManager.unshiftNew("FaintPhase", target.getBattlerIndex(), false, user);
|
||||||
|
|
||||||
target.destroySubstitute();
|
target.destroySubstitute();
|
||||||
target.lapseTag(BattlerTagType.COMMANDED);
|
target.lapseTag(BattlerTagType.COMMANDED);
|
||||||
@ -933,7 +943,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (msg) {
|
if (msg) {
|
||||||
globalScene.queueMessage(msg);
|
globalScene.phaseManager.queueMessage(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import { applyPostSummonAbAttrs, PostSummonRemoveEffectAbAttr } from "#app/data/
|
|||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
|
|
||||||
export class MoveEndPhase extends PokemonPhase {
|
export class MoveEndPhase extends PokemonPhase {
|
||||||
|
public readonly phaseName = "MoveEndPhase";
|
||||||
private wasFollowUp: boolean;
|
private wasFollowUp: boolean;
|
||||||
|
|
||||||
/** Targets from the preceding MovePhase */
|
/** Targets from the preceding MovePhase */
|
||||||
|
@ -4,6 +4,7 @@ import type Pokemon from "#app/field/pokemon";
|
|||||||
import { BattlePhase } from "./battle-phase";
|
import { BattlePhase } from "./battle-phase";
|
||||||
|
|
||||||
export class MoveHeaderPhase extends BattlePhase {
|
export class MoveHeaderPhase extends BattlePhase {
|
||||||
|
public readonly phaseName = "MoveHeaderPhase";
|
||||||
public pokemon: Pokemon;
|
public pokemon: Pokemon;
|
||||||
public move: PokemonMove;
|
public move: PokemonMove;
|
||||||
|
|
||||||
|
@ -39,10 +39,6 @@ import { MoveResult } from "#app/field/pokemon";
|
|||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import Overrides from "#app/overrides";
|
import Overrides from "#app/overrides";
|
||||||
import { BattlePhase } from "#app/phases/battle-phase";
|
import { BattlePhase } from "#app/phases/battle-phase";
|
||||||
import { CommonAnimPhase } from "#app/phases/common-anim-phase";
|
|
||||||
import { MoveChargePhase } from "#app/phases/move-charge-phase";
|
|
||||||
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
|
||||||
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
|
||||||
import { NumberHolder } from "#app/utils/common";
|
import { NumberHolder } from "#app/utils/common";
|
||||||
import { AbilityId } from "#enums/ability-id";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||||
@ -52,6 +48,7 @@ import { StatusEffect } from "#enums/status-effect";
|
|||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class MovePhase extends BattlePhase {
|
export class MovePhase extends BattlePhase {
|
||||||
|
public readonly phaseName = "MovePhase";
|
||||||
protected _pokemon: Pokemon;
|
protected _pokemon: Pokemon;
|
||||||
protected _move: PokemonMove;
|
protected _move: PokemonMove;
|
||||||
protected _targets: BattlerIndex[];
|
protected _targets: BattlerIndex[];
|
||||||
@ -267,18 +264,17 @@ export class MovePhase extends BattlePhase {
|
|||||||
|
|
||||||
if (activated) {
|
if (activated) {
|
||||||
this.cancel();
|
this.cancel();
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
getStatusEffectActivationText(this.pokemon.status.effect, getPokemonNameWithAffix(this.pokemon)),
|
getStatusEffectActivationText(this.pokemon.status.effect, getPokemonNameWithAffix(this.pokemon)),
|
||||||
);
|
);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new CommonAnimPhase(
|
"CommonAnimPhase",
|
||||||
this.pokemon.getBattlerIndex(),
|
this.pokemon.getBattlerIndex(),
|
||||||
undefined,
|
undefined,
|
||||||
CommonAnim.POISON + (this.pokemon.status.effect - 1),
|
CommonAnim.POISON + (this.pokemon.status.effect - 1),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
} else if (healed) {
|
} else if (healed) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
getStatusEffectHealText(this.pokemon.status.effect, getPokemonNameWithAffix(this.pokemon)),
|
getStatusEffectHealText(this.pokemon.status.effect, getPokemonNameWithAffix(this.pokemon)),
|
||||||
);
|
);
|
||||||
this.pokemon.resetStatus();
|
this.pokemon.resetStatus();
|
||||||
@ -406,8 +402,13 @@ export class MovePhase extends BattlePhase {
|
|||||||
if (success) {
|
if (success) {
|
||||||
const move = this.move.getMove();
|
const move = this.move.getMove();
|
||||||
applyPreAttackAbAttrs(PokemonTypeChangeAbAttr, this.pokemon, null, move);
|
applyPreAttackAbAttrs(PokemonTypeChangeAbAttr, this.pokemon, null, move);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new MoveEffectPhase(this.pokemon.getBattlerIndex(), this.targets, move, this.reflected, this.move.virtual),
|
"MoveEffectPhase",
|
||||||
|
this.pokemon.getBattlerIndex(),
|
||||||
|
this.targets,
|
||||||
|
move,
|
||||||
|
this.reflected,
|
||||||
|
this.move.virtual,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if ([MoveId.ROAR, MoveId.WHIRLWIND, MoveId.TRICK_OR_TREAT, MoveId.FORESTS_CURSE].includes(this.move.moveId)) {
|
if ([MoveId.ROAR, MoveId.WHIRLWIND, MoveId.TRICK_OR_TREAT, MoveId.FORESTS_CURSE].includes(this.move.moveId)) {
|
||||||
@ -456,7 +457,12 @@ export class MovePhase extends BattlePhase {
|
|||||||
applyPreAttackAbAttrs(PokemonTypeChangeAbAttr, this.pokemon, null, this.move.getMove());
|
applyPreAttackAbAttrs(PokemonTypeChangeAbAttr, this.pokemon, null, this.move.getMove());
|
||||||
|
|
||||||
this.showMoveText();
|
this.showMoveText();
|
||||||
globalScene.unshiftPhase(new MoveChargePhase(this.pokemon.getBattlerIndex(), this.targets[0], this.move));
|
globalScene.phaseManager.unshiftNew(
|
||||||
|
"MoveChargePhase",
|
||||||
|
this.pokemon.getBattlerIndex(),
|
||||||
|
this.targets[0],
|
||||||
|
this.move,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.pokemon.pushMoveHistory({
|
this.pokemon.pushMoveHistory({
|
||||||
move: this.move.moveId,
|
move: this.move.moveId,
|
||||||
@ -478,8 +484,11 @@ export class MovePhase extends BattlePhase {
|
|||||||
* Queues a {@linkcode MoveEndPhase} and then ends the phase
|
* Queues a {@linkcode MoveEndPhase} and then ends the phase
|
||||||
*/
|
*/
|
||||||
public end(): void {
|
public end(): void {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new MoveEndPhase(this.pokemon.getBattlerIndex(), this.getActiveTargetPokemon(), this.followUp),
|
"MoveEndPhase",
|
||||||
|
this.pokemon.getBattlerIndex(),
|
||||||
|
this.getActiveTargetPokemon(),
|
||||||
|
this.followUp,
|
||||||
);
|
);
|
||||||
|
|
||||||
super.end();
|
super.end();
|
||||||
@ -544,12 +553,12 @@ export class MovePhase extends BattlePhase {
|
|||||||
if (this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr)) {
|
if (this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr)) {
|
||||||
redirectTarget.value = currentTarget;
|
redirectTarget.value = currentTarget;
|
||||||
// TODO: Ability displays should be handled by the ability
|
// TODO: Ability displays should be handled by the ability
|
||||||
globalScene.queueAbilityDisplay(
|
globalScene.phaseManager.queueAbilityDisplay(
|
||||||
this.pokemon,
|
this.pokemon,
|
||||||
this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr),
|
this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
globalScene.queueAbilityDisplay(
|
globalScene.phaseManager.queueAbilityDisplay(
|
||||||
this.pokemon,
|
this.pokemon,
|
||||||
this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr),
|
this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr),
|
||||||
false,
|
false,
|
||||||
@ -648,7 +657,7 @@ export class MovePhase extends BattlePhase {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(this.reflected ? "battle:magicCoatActivated" : "battle:useMove", {
|
i18next.t(this.reflected ? "battle:magicCoatActivated" : "battle:useMove", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(this.pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(this.pokemon),
|
||||||
moveName: this.move.getName(),
|
moveName: this.move.getName(),
|
||||||
@ -659,6 +668,6 @@ export class MovePhase extends BattlePhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public showFailedText(failedText: string = i18next.t("battle:attackFailed")): void {
|
public showFailedText(failedText: string = i18next.t("battle:attackFailed")): void {
|
||||||
globalScene.queueMessage(failedText);
|
globalScene.phaseManager.queueMessage(failedText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,16 +3,6 @@ import type { OptionPhaseCallback } from "#app/data/mystery-encounters/mystery-e
|
|||||||
import type MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option";
|
import type MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { SeenEncounterData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
import { SeenEncounterData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
||||||
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { CheckSwitchPhase } from "#app/phases/check-switch-phase";
|
|
||||||
import { GameOverPhase } from "#app/phases/game-over-phase";
|
|
||||||
import { NewBattlePhase } from "#app/phases/new-battle-phase";
|
|
||||||
import { PostTurnStatusEffectPhase } from "#app/phases/post-turn-status-effect-phase";
|
|
||||||
import { ReturnPhase } from "#app/phases/return-phase";
|
|
||||||
import { ScanIvsPhase } from "#app/phases/scan-ivs-phase";
|
|
||||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
|
||||||
import { SummonPhase } from "#app/phases/summon-phase";
|
|
||||||
import { SwitchPhase } from "#app/phases/switch-phase";
|
|
||||||
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
|
|
||||||
import { BattleSpec } from "#enums/battle-spec";
|
import { BattleSpec } from "#enums/battle-spec";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
@ -27,7 +17,6 @@ import { IvScannerModifier } from "../modifier/modifier";
|
|||||||
import { Phase } from "../phase";
|
import { Phase } from "../phase";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { isNullOrUndefined, randSeedItem } from "#app/utils/common";
|
import { isNullOrUndefined, randSeedItem } from "#app/utils/common";
|
||||||
import { SelectBiomePhase } from "./select-biome-phase";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will handle (in order):
|
* Will handle (in order):
|
||||||
@ -39,6 +28,7 @@ import { SelectBiomePhase } from "./select-biome-phase";
|
|||||||
* - Queuing of the {@linkcode MysteryEncounterOptionSelectedPhase}
|
* - Queuing of the {@linkcode MysteryEncounterOptionSelectedPhase}
|
||||||
*/
|
*/
|
||||||
export class MysteryEncounterPhase extends Phase {
|
export class MysteryEncounterPhase extends Phase {
|
||||||
|
public readonly phaseName = "MysteryEncounterPhase";
|
||||||
private readonly FIRST_DIALOGUE_PROMPT_DELAY = 300;
|
private readonly FIRST_DIALOGUE_PROMPT_DELAY = 300;
|
||||||
optionSelectSettings?: OptionSelectSettings;
|
optionSelectSettings?: OptionSelectSettings;
|
||||||
|
|
||||||
@ -58,8 +48,8 @@ export class MysteryEncounterPhase extends Phase {
|
|||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
// Clears out queued phases that are part of standard battle
|
// Clears out queued phases that are part of standard battle
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.clearPhaseQueueSplice();
|
globalScene.phaseManager.clearPhaseQueueSplice();
|
||||||
|
|
||||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||||
encounter.updateSeedOffset();
|
encounter.updateSeedOffset();
|
||||||
@ -124,7 +114,7 @@ export class MysteryEncounterPhase extends Phase {
|
|||||||
*/
|
*/
|
||||||
continueEncounter() {
|
continueEncounter() {
|
||||||
const endDialogueAndContinueEncounter = () => {
|
const endDialogueAndContinueEncounter = () => {
|
||||||
globalScene.pushPhase(new MysteryEncounterOptionSelectedPhase());
|
globalScene.phaseManager.pushNew("MysteryEncounterOptionSelectedPhase");
|
||||||
this.end();
|
this.end();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -180,6 +170,7 @@ export class MysteryEncounterPhase extends Phase {
|
|||||||
* Any phase that is meant to follow this one MUST be queued via the onOptionSelect() logic of the selected option
|
* Any phase that is meant to follow this one MUST be queued via the onOptionSelect() logic of the selected option
|
||||||
*/
|
*/
|
||||||
export class MysteryEncounterOptionSelectedPhase extends Phase {
|
export class MysteryEncounterOptionSelectedPhase extends Phase {
|
||||||
|
public readonly phaseName = "MysteryEncounterOptionSelectedPhase";
|
||||||
onOptionSelect: OptionPhaseCallback;
|
onOptionSelect: OptionPhaseCallback;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -221,6 +212,7 @@ export class MysteryEncounterOptionSelectedPhase extends Phase {
|
|||||||
* See {@linkcode TurnEndPhase} for more details
|
* See {@linkcode TurnEndPhase} for more details
|
||||||
*/
|
*/
|
||||||
export class MysteryEncounterBattleStartCleanupPhase extends Phase {
|
export class MysteryEncounterBattleStartCleanupPhase extends Phase {
|
||||||
|
public readonly phaseName = "MysteryEncounterBattleStartCleanupPhase";
|
||||||
/**
|
/**
|
||||||
* Cleans up `TURN_END` tags, any {@linkcode PostTurnStatusEffectPhase}s, checks for Pokemon switches, then continues
|
* Cleans up `TURN_END` tags, any {@linkcode PostTurnStatusEffectPhase}s, checks for Pokemon switches, then continues
|
||||||
*/
|
*/
|
||||||
@ -245,8 +237,8 @@ export class MysteryEncounterBattleStartCleanupPhase extends Phase {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Remove any status tick phases
|
// Remove any status tick phases
|
||||||
while (globalScene.findPhase(p => p instanceof PostTurnStatusEffectPhase)) {
|
while (globalScene.phaseManager.findPhase(p => p.is("PostTurnStatusEffectPhase"))) {
|
||||||
globalScene.tryRemovePhase(p => p instanceof PostTurnStatusEffectPhase);
|
globalScene.phaseManager.tryRemovePhase(p => p.is("PostTurnStatusEffectPhase"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The total number of Pokemon in the player's party that can legally fight
|
// The total number of Pokemon in the player's party that can legally fight
|
||||||
@ -254,7 +246,7 @@ export class MysteryEncounterBattleStartCleanupPhase extends Phase {
|
|||||||
// The total number of legal player Pokemon that aren't currently on the field
|
// The total number of legal player Pokemon that aren't currently on the field
|
||||||
const legalPlayerPartyPokemon = legalPlayerPokemon.filter(p => !p.isActive(true));
|
const legalPlayerPartyPokemon = legalPlayerPokemon.filter(p => !p.isActive(true));
|
||||||
if (!legalPlayerPokemon.length) {
|
if (!legalPlayerPokemon.length) {
|
||||||
globalScene.unshiftPhase(new GameOverPhase());
|
globalScene.phaseManager.unshiftNew("GameOverPhase");
|
||||||
return this.end();
|
return this.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,13 +255,13 @@ export class MysteryEncounterBattleStartCleanupPhase extends Phase {
|
|||||||
const playerField = globalScene.getPlayerField();
|
const playerField = globalScene.getPlayerField();
|
||||||
playerField.forEach((pokemon, i) => {
|
playerField.forEach((pokemon, i) => {
|
||||||
if (!pokemon.isAllowedInBattle() && legalPlayerPartyPokemon.length > i) {
|
if (!pokemon.isAllowedInBattle() && legalPlayerPartyPokemon.length > i) {
|
||||||
globalScene.unshiftPhase(new SwitchPhase(SwitchType.SWITCH, i, true, false));
|
globalScene.phaseManager.unshiftNew("SwitchPhase", SwitchType.SWITCH, i, true, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// THEN, if is a double battle, and player only has 1 summoned pokemon, center pokemon on field
|
// THEN, if is a double battle, and player only has 1 summoned pokemon, center pokemon on field
|
||||||
if (globalScene.currentBattle.double && legalPlayerPokemon.length === 1 && legalPlayerPartyPokemon.length === 0) {
|
if (globalScene.currentBattle.double && legalPlayerPokemon.length === 1 && legalPlayerPartyPokemon.length === 0) {
|
||||||
globalScene.unshiftPhase(new ToggleDoublePositionPhase(true));
|
globalScene.phaseManager.unshiftNew("ToggleDoublePositionPhase", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.end();
|
this.end();
|
||||||
@ -284,6 +276,7 @@ export class MysteryEncounterBattleStartCleanupPhase extends Phase {
|
|||||||
* - Queue the {@linkcode SummonPhase}s, {@linkcode PostSummonPhase}s, etc., required to initialize the phase queue for a battle
|
* - Queue the {@linkcode SummonPhase}s, {@linkcode PostSummonPhase}s, etc., required to initialize the phase queue for a battle
|
||||||
*/
|
*/
|
||||||
export class MysteryEncounterBattlePhase extends Phase {
|
export class MysteryEncounterBattlePhase extends Phase {
|
||||||
|
public readonly phaseName = "MysteryEncounterBattlePhase";
|
||||||
disableSwitch: boolean;
|
disableSwitch: boolean;
|
||||||
|
|
||||||
constructor(disableSwitch = false) {
|
constructor(disableSwitch = false) {
|
||||||
@ -345,9 +338,9 @@ export class MysteryEncounterBattlePhase extends Phase {
|
|||||||
globalScene.playBgm();
|
globalScene.playBgm();
|
||||||
}
|
}
|
||||||
const availablePartyMembers = globalScene.getEnemyParty().filter(p => !p.isFainted()).length;
|
const availablePartyMembers = globalScene.getEnemyParty().filter(p => !p.isFainted()).length;
|
||||||
globalScene.unshiftPhase(new SummonPhase(0, false));
|
globalScene.phaseManager.unshiftNew("SummonPhase", 0, false);
|
||||||
if (globalScene.currentBattle.double && availablePartyMembers > 1) {
|
if (globalScene.currentBattle.double && availablePartyMembers > 1) {
|
||||||
globalScene.unshiftPhase(new SummonPhase(1, false));
|
globalScene.phaseManager.unshiftNew("SummonPhase", 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!globalScene.currentBattle.mysteryEncounter?.hideBattleIntroMessage) {
|
if (!globalScene.currentBattle.mysteryEncounter?.hideBattleIntroMessage) {
|
||||||
@ -365,9 +358,9 @@ export class MysteryEncounterBattlePhase extends Phase {
|
|||||||
const doTrainerSummon = () => {
|
const doTrainerSummon = () => {
|
||||||
this.hideEnemyTrainer();
|
this.hideEnemyTrainer();
|
||||||
const availablePartyMembers = globalScene.getEnemyParty().filter(p => !p.isFainted()).length;
|
const availablePartyMembers = globalScene.getEnemyParty().filter(p => !p.isFainted()).length;
|
||||||
globalScene.unshiftPhase(new SummonPhase(0, false));
|
globalScene.phaseManager.unshiftNew("SummonPhase", 0, false);
|
||||||
if (globalScene.currentBattle.double && availablePartyMembers > 1) {
|
if (globalScene.currentBattle.double && availablePartyMembers > 1) {
|
||||||
globalScene.unshiftPhase(new SummonPhase(1, false));
|
globalScene.phaseManager.unshiftNew("SummonPhase", 1, false);
|
||||||
}
|
}
|
||||||
this.endBattleSetup();
|
this.endBattleSetup();
|
||||||
};
|
};
|
||||||
@ -423,37 +416,37 @@ export class MysteryEncounterBattlePhase extends Phase {
|
|||||||
if (encounterMode !== MysteryEncounterMode.TRAINER_BATTLE) {
|
if (encounterMode !== MysteryEncounterMode.TRAINER_BATTLE) {
|
||||||
const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier);
|
const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier);
|
||||||
if (ivScannerModifier) {
|
if (ivScannerModifier) {
|
||||||
enemyField.map(p => globalScene.pushPhase(new ScanIvsPhase(p.getBattlerIndex())));
|
enemyField.map(p => globalScene.phaseManager.pushNew("ScanIvsPhase", p.getBattlerIndex()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const availablePartyMembers = globalScene.getPlayerParty().filter(p => p.isAllowedInBattle());
|
const availablePartyMembers = globalScene.getPlayerParty().filter(p => p.isAllowedInBattle());
|
||||||
|
|
||||||
if (!availablePartyMembers[0].isOnField()) {
|
if (!availablePartyMembers[0].isOnField()) {
|
||||||
globalScene.pushPhase(new SummonPhase(0));
|
globalScene.phaseManager.pushNew("SummonPhase", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (globalScene.currentBattle.double) {
|
if (globalScene.currentBattle.double) {
|
||||||
if (availablePartyMembers.length > 1) {
|
if (availablePartyMembers.length > 1) {
|
||||||
globalScene.pushPhase(new ToggleDoublePositionPhase(true));
|
globalScene.phaseManager.pushNew("ToggleDoublePositionPhase", true);
|
||||||
if (!availablePartyMembers[1].isOnField()) {
|
if (!availablePartyMembers[1].isOnField()) {
|
||||||
globalScene.pushPhase(new SummonPhase(1));
|
globalScene.phaseManager.pushNew("SummonPhase", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (availablePartyMembers.length > 1 && availablePartyMembers[1].isOnField()) {
|
if (availablePartyMembers.length > 1 && availablePartyMembers[1].isOnField()) {
|
||||||
globalScene.getPlayerField().forEach(pokemon => pokemon.lapseTag(BattlerTagType.COMMANDED));
|
globalScene.getPlayerField().forEach(pokemon => pokemon.lapseTag(BattlerTagType.COMMANDED));
|
||||||
globalScene.pushPhase(new ReturnPhase(1));
|
globalScene.phaseManager.pushNew("ReturnPhase", 1);
|
||||||
}
|
}
|
||||||
globalScene.pushPhase(new ToggleDoublePositionPhase(false));
|
globalScene.phaseManager.pushNew("ToggleDoublePositionPhase", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encounterMode !== MysteryEncounterMode.TRAINER_BATTLE && !this.disableSwitch) {
|
if (encounterMode !== MysteryEncounterMode.TRAINER_BATTLE && !this.disableSwitch) {
|
||||||
const minPartySize = globalScene.currentBattle.double ? 2 : 1;
|
const minPartySize = globalScene.currentBattle.double ? 2 : 1;
|
||||||
if (availablePartyMembers.length > minPartySize) {
|
if (availablePartyMembers.length > minPartySize) {
|
||||||
globalScene.pushPhase(new CheckSwitchPhase(0, globalScene.currentBattle.double));
|
globalScene.phaseManager.pushNew("CheckSwitchPhase", 0, globalScene.currentBattle.double);
|
||||||
if (globalScene.currentBattle.double) {
|
if (globalScene.currentBattle.double) {
|
||||||
globalScene.pushPhase(new CheckSwitchPhase(1, globalScene.currentBattle.double));
|
globalScene.phaseManager.pushNew("CheckSwitchPhase", 1, globalScene.currentBattle.double);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -513,6 +506,7 @@ export class MysteryEncounterBattlePhase extends Phase {
|
|||||||
* - Queuing of the {@linkcode PostMysteryEncounterPhase}
|
* - Queuing of the {@linkcode PostMysteryEncounterPhase}
|
||||||
*/
|
*/
|
||||||
export class MysteryEncounterRewardsPhase extends Phase {
|
export class MysteryEncounterRewardsPhase extends Phase {
|
||||||
|
public readonly phaseName = "MysteryEncounterRewardsPhase";
|
||||||
addHealPhase: boolean;
|
addHealPhase: boolean;
|
||||||
|
|
||||||
constructor(addHealPhase = false) {
|
constructor(addHealPhase = false) {
|
||||||
@ -558,16 +552,14 @@ export class MysteryEncounterRewardsPhase extends Phase {
|
|||||||
if (encounter.doEncounterRewards) {
|
if (encounter.doEncounterRewards) {
|
||||||
encounter.doEncounterRewards();
|
encounter.doEncounterRewards();
|
||||||
} else if (this.addHealPhase) {
|
} else if (this.addHealPhase) {
|
||||||
globalScene.tryRemovePhase(p => p instanceof SelectModifierPhase);
|
globalScene.phaseManager.tryRemovePhase(p => p.is("SelectModifierPhase"));
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew("SelectModifierPhase", 0, undefined, {
|
||||||
new SelectModifierPhase(0, undefined, {
|
fillRemaining: false,
|
||||||
fillRemaining: false,
|
rerollMultiplier: -1,
|
||||||
rerollMultiplier: -1,
|
});
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.pushPhase(new PostMysteryEncounterPhase());
|
globalScene.phaseManager.pushNew("PostMysteryEncounterPhase");
|
||||||
this.end();
|
this.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -580,6 +572,7 @@ export class MysteryEncounterRewardsPhase extends Phase {
|
|||||||
* - Queuing of the next wave
|
* - Queuing of the next wave
|
||||||
*/
|
*/
|
||||||
export class PostMysteryEncounterPhase extends Phase {
|
export class PostMysteryEncounterPhase extends Phase {
|
||||||
|
public readonly phaseName = "PostMysteryEncounterPhase";
|
||||||
private readonly FIRST_DIALOGUE_PROMPT_DELAY = 750;
|
private readonly FIRST_DIALOGUE_PROMPT_DELAY = 750;
|
||||||
onPostOptionSelect?: OptionPhaseCallback;
|
onPostOptionSelect?: OptionPhaseCallback;
|
||||||
|
|
||||||
@ -613,10 +606,10 @@ export class PostMysteryEncounterPhase extends Phase {
|
|||||||
continueEncounter() {
|
continueEncounter() {
|
||||||
const endPhase = () => {
|
const endPhase = () => {
|
||||||
if (globalScene.gameMode.hasRandomBiomes || globalScene.isNewBiome()) {
|
if (globalScene.gameMode.hasRandomBiomes || globalScene.isNewBiome()) {
|
||||||
globalScene.pushPhase(new SelectBiomePhase());
|
globalScene.phaseManager.pushNew("SelectBiomePhase");
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.pushPhase(new NewBattlePhase());
|
globalScene.phaseManager.pushNew("NewBattlePhase");
|
||||||
this.end();
|
this.end();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,13 +2,16 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { BattlePhase } from "./battle-phase";
|
import { BattlePhase } from "./battle-phase";
|
||||||
|
|
||||||
export class NewBattlePhase extends BattlePhase {
|
export class NewBattlePhase extends BattlePhase {
|
||||||
|
public readonly phaseName = "NewBattlePhase";
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
// cull any extra `NewBattle` phases from the queue.
|
// cull any extra `NewBattle` phases from the queue.
|
||||||
globalScene.phaseQueue = globalScene.phaseQueue.filter(phase => !(phase instanceof NewBattlePhase));
|
globalScene.phaseManager.phaseQueue = globalScene.phaseManager.phaseQueue.filter(
|
||||||
|
phase => !phase.is("NewBattlePhase"),
|
||||||
|
);
|
||||||
// `phaseQueuePrepend` is private, so we have to use this inefficient loop.
|
// `phaseQueuePrepend` is private, so we have to use this inefficient loop.
|
||||||
while (globalScene.tryRemoveUnshiftedPhase(phase => phase instanceof NewBattlePhase)) {}
|
while (globalScene.phaseManager.tryRemoveUnshiftedPhase(phase => phase.is("NewBattlePhase"))) {}
|
||||||
|
|
||||||
globalScene.newBattle();
|
globalScene.newBattle();
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { getRandomWeatherType } from "#app/data/weather";
|
|||||||
import { NextEncounterPhase } from "./next-encounter-phase";
|
import { NextEncounterPhase } from "./next-encounter-phase";
|
||||||
|
|
||||||
export class NewBiomeEncounterPhase extends NextEncounterPhase {
|
export class NewBiomeEncounterPhase extends NextEncounterPhase {
|
||||||
|
public readonly phaseName = "NewBiomeEncounterPhase";
|
||||||
doEncounter(): void {
|
doEncounter(): void {
|
||||||
globalScene.playBgm(undefined, true);
|
globalScene.playBgm(undefined, true);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import { EncounterPhase } from "./encounter-phase";
|
|||||||
* Handles generating, loading and preparing for it.
|
* Handles generating, loading and preparing for it.
|
||||||
*/
|
*/
|
||||||
export class NextEncounterPhase extends EncounterPhase {
|
export class NextEncounterPhase extends EncounterPhase {
|
||||||
|
public readonly phaseName: "NextEncounterPhase" | "NewBiomeEncounterPhase" = "NextEncounterPhase";
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user