Merge branch 'beta' into refactor-starter-handling

This commit is contained in:
Wlowscha 2025-09-10 17:43:27 +02:00 committed by GitHub
commit 022405a1a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 212 additions and 145 deletions

View File

@ -3209,9 +3209,55 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
Math.ceil(Math.pow(m[1], weightMultiplier) * 100), Math.ceil(Math.pow(m[1], weightMultiplier) * 100),
]); ]);
const STAB_BLACKLIST: ReadonlySet<MoveId> = new Set([
MoveId.BEAT_UP,
MoveId.BELCH,
MoveId.BIDE,
MoveId.COMEUPPANCE,
MoveId.COUNTER,
MoveId.DOOM_DESIRE,
MoveId.DRAGON_RAGE,
MoveId.DREAM_EATER,
MoveId.ENDEAVOR,
MoveId.EXPLOSION,
MoveId.FAKE_OUT,
MoveId.FIRST_IMPRESSION,
MoveId.FISSURE,
MoveId.FLING,
MoveId.FOCUS_PUNCH,
MoveId.FUTURE_SIGHT,
MoveId.GUILLOTINE,
MoveId.HOLD_BACK,
MoveId.HORN_DRILL,
MoveId.LAST_RESORT,
MoveId.METAL_BURST,
MoveId.MIRROR_COAT,
MoveId.MISTY_EXPLOSION,
MoveId.NATURAL_GIFT,
MoveId.NATURES_MADNESS,
MoveId.NIGHT_SHADE,
MoveId.PSYWAVE,
MoveId.RUINATION,
MoveId.SELF_DESTRUCT,
MoveId.SHEER_COLD,
MoveId.SHELL_TRAP,
MoveId.SKY_DROP,
MoveId.SNORE,
MoveId.SONIC_BOOM,
MoveId.SPIT_UP,
MoveId.STEEL_BEAM,
MoveId.STEEL_ROLLER,
MoveId.SUPER_FANG,
MoveId.SYNCHRONOISE,
MoveId.UPPER_HAND,
]);
// All Pokemon force a STAB move first // All Pokemon force a STAB move first
const stabMovePool = baseWeights.filter( const stabMovePool = baseWeights.filter(
m => allMoves[m[0]].category !== MoveCategory.STATUS && this.isOfType(allMoves[m[0]].type), m =>
allMoves[m[0]].category !== MoveCategory.STATUS
&& this.isOfType(allMoves[m[0]].type)
&& !STAB_BLACKLIST.has(m[0]),
); );
if (stabMovePool.length > 0) { if (stabMovePool.length > 0) {
@ -3224,7 +3270,9 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
this.moveset.push(new PokemonMove(stabMovePool[index][0])); this.moveset.push(new PokemonMove(stabMovePool[index][0]));
} else { } else {
// If there are no damaging STAB moves, just force a random damaging move // If there are no damaging STAB moves, just force a random damaging move
const attackMovePool = baseWeights.filter(m => allMoves[m[0]].category !== MoveCategory.STATUS); const attackMovePool = baseWeights.filter(
m => allMoves[m[0]].category !== MoveCategory.STATUS && !STAB_BLACKLIST.has(m[0]),
);
if (attackMovePool.length > 0) { if (attackMovePool.length > 0) {
const totalWeight = attackMovePool.reduce((v, m) => v + m[1], 0); const totalWeight = attackMovePool.reduce((v, m) => v + m[1], 0);
let rand = randSeedInt(totalWeight); let rand = randSeedInt(totalWeight);
@ -3261,7 +3309,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
} else if (allMoves[m[0]].category !== MoveCategory.STATUS) { } else if (allMoves[m[0]].category !== MoveCategory.STATUS) {
ret = Math.ceil( ret = Math.ceil(
(m[1] / Math.max(Math.pow(4, this.moveset.filter(mo => (mo.getMove().power ?? 0) > 1).length) / 8, 0.5)) (m[1] / Math.max(Math.pow(4, this.moveset.filter(mo => (mo.getMove().power ?? 0) > 1).length) / 8, 0.5))
* (this.isOfType(allMoves[m[0]].type) ? 20 : 1), * (this.isOfType(allMoves[m[0]].type) && !STAB_BLACKLIST.has(m[0]) ? 20 : 1),
); );
} else { } else {
ret = m[1]; ret = m[1];

View File

@ -11,7 +11,7 @@ import type { EggLapsePhase } from "#phases/egg-lapse-phase";
import { achvs } from "#system/achv"; import { achvs } from "#system/achv";
import { EggCounterContainer } from "#ui/containers/egg-counter-container"; import { EggCounterContainer } from "#ui/containers/egg-counter-container";
import { PokemonInfoContainer } from "#ui/containers/pokemon-info-container"; import { PokemonInfoContainer } from "#ui/containers/pokemon-info-container";
import type { EggHatchSceneHandler } from "#ui/handlers/egg-hatch-scene-handler"; import type { EggHatchSceneUiHandler } from "#ui/handlers/egg-hatch-scene-ui-handler";
import { fixedInt, getFrameMs, randInt } from "#utils/common"; import { fixedInt, getFrameMs, randInt } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
@ -32,7 +32,7 @@ export class EggHatchPhase extends Phase {
private eggCounterContainer: EggCounterContainer; private eggCounterContainer: EggCounterContainer;
/** The scene handler for egg hatching */ /** The scene handler for egg hatching */
private eggHatchHandler: EggHatchSceneHandler; private eggHatchHandler: EggHatchSceneUiHandler;
/** The phaser gameobject container that holds everything */ /** The phaser gameobject container that holds everything */
private eggHatchContainer: Phaser.GameObjects.Container; private eggHatchContainer: Phaser.GameObjects.Container;
/** The phaser image that is the background */ /** The phaser image that is the background */
@ -92,7 +92,7 @@ export class EggHatchPhase extends Phase {
globalScene.fadeOutBgm(undefined, false); globalScene.fadeOutBgm(undefined, false);
this.eggHatchHandler = globalScene.ui.getHandler() as EggHatchSceneHandler; this.eggHatchHandler = globalScene.ui.getHandler() as EggHatchSceneUiHandler;
this.eggHatchContainer = this.eggHatchHandler.eggHatchContainer; this.eggHatchContainer = this.eggHatchHandler.eggHatchContainer;

View File

@ -10,7 +10,7 @@ import { LearnMoveSituation } from "#enums/learn-move-situation";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { cos, sin } from "#field/anims"; import { cos, sin } from "#field/anims";
import type { PlayerPokemon, Pokemon } from "#field/pokemon"; import type { PlayerPokemon, Pokemon } from "#field/pokemon";
import type { EvolutionSceneHandler } from "#ui/handlers/evolution-scene-handler"; import type { EvolutionSceneUiHandler } from "#ui/handlers/evolution-scene-ui-handler";
import { fixedInt, getFrameMs, randInt } from "#utils/common"; import { fixedInt, getFrameMs, randInt } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
@ -29,7 +29,7 @@ export class EvolutionPhase extends Phase {
private evolution: SpeciesFormEvolution | null; private evolution: SpeciesFormEvolution | null;
private fusionSpeciesEvolved: boolean; // Whether the evolution is of the fused species private fusionSpeciesEvolved: boolean; // Whether the evolution is of the fused species
private evolutionBgm: AnySound | null; private evolutionBgm: AnySound | null;
private evolutionHandler: EvolutionSceneHandler; private evolutionHandler: EvolutionSceneUiHandler;
/** Container for all assets used by the scene. When the scene is cleared, the children within this are destroyed. */ /** Container for all assets used by the scene. When the scene is cleared, the children within this are destroyed. */
protected evolutionContainer: Phaser.GameObjects.Container; protected evolutionContainer: Phaser.GameObjects.Container;
@ -79,7 +79,7 @@ export class EvolutionPhase extends Phase {
* *
*/ */
private setupEvolutionAssets(): void { private setupEvolutionAssets(): void {
this.evolutionHandler = globalScene.ui.getHandler() as EvolutionSceneHandler; this.evolutionHandler = globalScene.ui.getHandler() as EvolutionSceneUiHandler;
this.evolutionContainer = this.evolutionHandler.evolutionContainer; this.evolutionContainer = this.evolutionHandler.evolutionContainer;
this.evolutionBaseBg = globalScene.add.image(0, 0, "default_bg").setOrigin(0); this.evolutionBaseBg = globalScene.add.image(0, 0, "default_bg").setOrigin(0);

View File

@ -10,7 +10,7 @@ import { UiMode } from "#enums/ui-mode";
import type { Pokemon } from "#field/pokemon"; import type { Pokemon } from "#field/pokemon";
import type { Move } from "#moves/move"; import type { Move } from "#moves/move";
import { PlayerPartyMemberPokemonPhase } from "#phases/player-party-member-pokemon-phase"; import { PlayerPartyMemberPokemonPhase } from "#phases/player-party-member-pokemon-phase";
import { EvolutionSceneHandler } from "#ui/handlers/evolution-scene-handler"; import { EvolutionSceneUiHandler } from "#ui/handlers/evolution-scene-ui-handler";
import { SummaryUiMode } from "#ui/handlers/summary-ui-handler"; import { SummaryUiMode } from "#ui/handlers/summary-ui-handler";
import i18next from "i18next"; import i18next from "i18next";
@ -47,7 +47,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
} }
this.messageMode = this.messageMode =
globalScene.ui.getHandler() instanceof EvolutionSceneHandler ? UiMode.EVOLUTION_SCENE : UiMode.MESSAGE; globalScene.ui.getHandler() instanceof EvolutionSceneUiHandler ? UiMode.EVOLUTION_SCENE : UiMode.MESSAGE;
globalScene.ui.setMode(this.messageMode); globalScene.ui.setMode(this.messageMode);
// If the Pokemon has less than 4 moves, the new move is added to the largest empty moveset index // If the Pokemon has less than 4 moves, the new move is added to the largest empty moveset index
// If it has 4 moves, the phase then checks if the player wants to replace the move itself. // If it has 4 moves, the phase then checks if the player wants to replace the move itself.

View File

@ -120,6 +120,14 @@ export interface Setting {
default: number; default: number;
type: SettingType; type: SettingType;
requireReload?: boolean; requireReload?: boolean;
/**
* Specifies the behavior when navigating left/right at the boundaries of the option
*
* - `true`: the cursor will stay on the boundary instead of moving
* - `false`: the cursor will wrap to the other end of the options list
* @defaultValue `false`
*/
clamp?: boolean;
/** Whether the setting can be activated or not */ /** Whether the setting can be activated or not */
activatable?: boolean; activatable?: boolean;
/** Determines whether the setting should be hidden from the UI */ /** Determines whether the setting should be hidden from the UI */
@ -230,6 +238,7 @@ export const Setting: Array<Setting> = [
], ],
default: 3, default: 3,
type: SettingType.GENERAL, type: SettingType.GENERAL,
clamp: false,
}, },
{ {
key: SettingKeys.HP_Bar_Speed, key: SettingKeys.HP_Bar_Speed,
@ -639,6 +648,7 @@ export const Setting: Array<Setting> = [
options: VOLUME_OPTIONS, options: VOLUME_OPTIONS,
default: 5, default: 5,
type: SettingType.AUDIO, type: SettingType.AUDIO,
clamp: true,
}, },
{ {
key: SettingKeys.BGM_Volume, key: SettingKeys.BGM_Volume,
@ -646,6 +656,7 @@ export const Setting: Array<Setting> = [
options: VOLUME_OPTIONS, options: VOLUME_OPTIONS,
default: 10, default: 10,
type: SettingType.AUDIO, type: SettingType.AUDIO,
clamp: true,
}, },
{ {
key: SettingKeys.Field_Volume, key: SettingKeys.Field_Volume,
@ -653,6 +664,7 @@ export const Setting: Array<Setting> = [
options: VOLUME_OPTIONS, options: VOLUME_OPTIONS,
default: 10, default: 10,
type: SettingType.AUDIO, type: SettingType.AUDIO,
clamp: true,
}, },
{ {
key: SettingKeys.SE_Volume, key: SettingKeys.SE_Volume,
@ -660,6 +672,7 @@ export const Setting: Array<Setting> = [
options: VOLUME_OPTIONS, options: VOLUME_OPTIONS,
default: 10, default: 10,
type: SettingType.AUDIO, type: SettingType.AUDIO,
clamp: true,
}, },
{ {
key: SettingKeys.UI_Volume, key: SettingKeys.UI_Volume,
@ -667,6 +680,7 @@ export const Setting: Array<Setting> = [
options: VOLUME_OPTIONS, options: VOLUME_OPTIONS,
default: 10, default: 10,
type: SettingType.AUDIO, type: SettingType.AUDIO,
clamp: true,
}, },
{ {
key: SettingKeys.Battle_Music, key: SettingKeys.Battle_Music,

View File

@ -3,8 +3,8 @@ import type { InputsController } from "#app/inputs-controller";
import { Button } from "#enums/buttons"; import { Button } from "#enums/buttons";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { Setting, SettingKeys, settingIndex } from "#system/settings"; import { Setting, SettingKeys, settingIndex } from "#system/settings";
import { PokedexPageUiHandler } from "#ui/containers/pokedex-page-ui-handler";
import type { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import type { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { PokedexPageUiHandler } from "#ui/handlers/pokedex-page-ui-handler";
import { PokedexUiHandler } from "#ui/handlers/pokedex-ui-handler"; import { PokedexUiHandler } from "#ui/handlers/pokedex-ui-handler";
import { RunInfoUiHandler } from "#ui/handlers/run-info-ui-handler"; import { RunInfoUiHandler } from "#ui/handlers/run-info-ui-handler";
import { StarterSelectUiHandler } from "#ui/handlers/starter-select-ui-handler"; import { StarterSelectUiHandler } from "#ui/handlers/starter-select-ui-handler";

View File

@ -2,7 +2,7 @@ import { globalScene } from "#app/global-scene";
import { TextStyle } from "#enums/text-style"; import { TextStyle } from "#enums/text-style";
import type { EggCountChangedEvent } from "#events/egg"; import type { EggCountChangedEvent } from "#events/egg";
import { EggEventType } from "#events/egg"; import { EggEventType } from "#events/egg";
import type { EggHatchSceneHandler } from "#ui/handlers/egg-hatch-scene-handler"; import type { EggHatchSceneUiHandler } from "#ui/handlers/egg-hatch-scene-ui-handler";
import { addTextObject } from "#ui/text"; import { addTextObject } from "#ui/text";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
@ -27,7 +27,7 @@ export class EggCounterContainer extends Phaser.GameObjects.Container {
super(globalScene, 0, 0); super(globalScene, 0, 0);
this.eggCount = eggCount; this.eggCount = eggCount;
const uiHandler = globalScene.ui.getHandler() as EggHatchSceneHandler; const uiHandler = globalScene.ui.getHandler() as EggHatchSceneUiHandler;
uiHandler.eventTarget.addEventListener(EggEventType.EGG_COUNT_CHANGED, this.onEggCountChangedEvent); uiHandler.eventTarget.addEventListener(EggEventType.EGG_COUNT_CHANGED, this.onEggCountChangedEvent);
this.setup(); this.setup();

View File

@ -4,8 +4,8 @@ import { Gender } from "#data/gender";
import type { PokemonSpecies } from "#data/pokemon-species"; import type { PokemonSpecies } from "#data/pokemon-species";
import { DexAttr } from "#enums/dex-attr"; import { DexAttr } from "#enums/dex-attr";
import { getVariantTint } from "#sprites/variant"; import { getVariantTint } from "#sprites/variant";
import type { PokemonIconAnimHandler } from "#ui/handlers/pokemon-icon-anim-handler"; import type { PokemonIconAnimHelper } from "#ui/utils/pokemon-icon-anim-helper";
import { PokemonIconAnimMode } from "#ui/handlers/pokemon-icon-anim-handler"; import { PokemonIconAnimMode } from "#ui/utils/pokemon-icon-anim-helper";
/** /**
* A container for a Pokemon's sprite and icons to get displayed in the egg summary screen * A container for a Pokemon's sprite and icons to get displayed in the egg summary screen
@ -81,9 +81,9 @@ export class HatchedPokemonContainer extends Phaser.GameObjects.Container {
* Animates the pokemon icon if it has a new form or shiny variant * Animates the pokemon icon if it has a new form or shiny variant
* *
* @param hatchData the {@linkcode EggHatchData} to base the icons on * @param hatchData the {@linkcode EggHatchData} to base the icons on
* @param iconAnimHandler the {@linkcode PokemonIconAnimHandler} to use to animate the sprites * @param iconAnimHandler the {@linkcode PokemonIconAnimHelper} to use to animate the sprites
*/ */
updateAndAnimate(hatchData: EggHatchData, iconAnimHandler: PokemonIconAnimHandler) { updateAndAnimate(hatchData: EggHatchData, iconAnimHandler: PokemonIconAnimHelper) {
const displayPokemon = hatchData.pokemon; const displayPokemon = hatchData.pokemon;
this.species = displayPokemon.species; this.species = displayPokemon.species;

View File

@ -1,7 +1,7 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { fixedInt } from "#utils/common"; import { fixedInt } from "#utils/common";
export class SavingIconHandler extends Phaser.GameObjects.Container { export class SavingIconContainer extends Phaser.GameObjects.Container {
private icon: Phaser.GameObjects.Sprite; private icon: Phaser.GameObjects.Sprite;
private animActive: boolean; private animActive: boolean;

View File

@ -3,7 +3,7 @@ import { Button } from "#enums/buttons";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { UiHandler } from "#ui/handlers/ui-handler"; import { UiHandler } from "#ui/handlers/ui-handler";
export class EggHatchSceneHandler extends UiHandler { export class EggHatchSceneUiHandler extends UiHandler {
public eggHatchContainer: Phaser.GameObjects.Container; public eggHatchContainer: Phaser.GameObjects.Container;
/** /**

View File

@ -4,10 +4,10 @@ import { TextStyle } from "#enums/text-style";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { ScrollBar } from "#ui/containers/scroll-bar"; import { ScrollBar } from "#ui/containers/scroll-bar";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/handlers/pokemon-icon-anim-handler";
import { ScrollableGridUiHandler } from "#ui/handlers/scrollable-grid-handler";
import { addTextObject } from "#ui/text"; import { addTextObject } from "#ui/text";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
import { PokemonIconAnimHelper, PokemonIconAnimMode } from "#ui/utils/pokemon-icon-anim-helper";
import { ScrollableGridHelper } from "#ui/utils/scrollable-grid-helper";
import i18next from "i18next"; import i18next from "i18next";
export class EggListUiHandler extends MessageUiHandler { export class EggListUiHandler extends MessageUiHandler {
@ -25,9 +25,9 @@ export class EggListUiHandler extends MessageUiHandler {
private eggListMessageBoxContainer: Phaser.GameObjects.Container; private eggListMessageBoxContainer: Phaser.GameObjects.Container;
private cursorObj: Phaser.GameObjects.Image; private cursorObj: Phaser.GameObjects.Image;
private scrollGridHandler: ScrollableGridUiHandler; private scrollGridHandler: ScrollableGridHelper;
private iconAnimHandler: PokemonIconAnimHandler; private iconAnimHandler: PokemonIconAnimHelper;
constructor() { constructor() {
super(UiMode.EGG_LIST); super(UiMode.EGG_LIST);
@ -45,7 +45,7 @@ export class EggListUiHandler extends MessageUiHandler {
const eggListBg = globalScene.add.image(0, 0, "egg_list_bg").setOrigin(0); const eggListBg = globalScene.add.image(0, 0, "egg_list_bg").setOrigin(0);
this.iconAnimHandler = new PokemonIconAnimHandler(); this.iconAnimHandler = new PokemonIconAnimHelper();
this.iconAnimHandler.setup(); this.iconAnimHandler.setup();
this.eggNameText = addTextObject(8, 68, "", TextStyle.SUMMARY).setOrigin(0); this.eggNameText = addTextObject(8, 68, "", TextStyle.SUMMARY).setOrigin(0);
@ -64,7 +64,7 @@ export class EggListUiHandler extends MessageUiHandler {
const scrollBar = new ScrollBar(310, 5, 4, 170, this.ROWS); const scrollBar = new ScrollBar(310, 5, 4, 170, this.ROWS);
this.scrollGridHandler = new ScrollableGridUiHandler(this, this.ROWS, this.COLUMNS) this.scrollGridHandler = new ScrollableGridHelper(this, this.ROWS, this.COLUMNS)
.withScrollBar(scrollBar) .withScrollBar(scrollBar)
.withUpdateGridCallBack(() => this.updateEggIcons()) .withUpdateGridCallBack(() => this.updateEggIcons())
.withUpdateSingleElementCallback((i: number) => this.setEggDetails(i)); .withUpdateSingleElementCallback((i: number) => this.setEggDetails(i));

View File

@ -7,8 +7,8 @@ import { HatchedPokemonContainer } from "#ui/containers/hatched-pokemon-containe
import { PokemonHatchInfoContainer } from "#ui/containers/pokemon-hatch-info-container"; import { PokemonHatchInfoContainer } from "#ui/containers/pokemon-hatch-info-container";
import { ScrollBar } from "#ui/containers/scroll-bar"; import { ScrollBar } from "#ui/containers/scroll-bar";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/handlers/pokemon-icon-anim-handler"; import { PokemonIconAnimHelper, PokemonIconAnimMode } from "#ui/utils/pokemon-icon-anim-helper";
import { ScrollableGridUiHandler } from "#ui/handlers/scrollable-grid-handler"; import { ScrollableGridHelper } from "#ui/utils/scrollable-grid-helper";
const iconContainerX = 112; const iconContainerX = 112;
const iconContainerY = 9; const iconContainerY = 9;
@ -34,11 +34,11 @@ export class EggSummaryUiHandler extends MessageUiHandler {
/** hatch info container that displays the current pokemon / hatch (main element on left hand side) */ /** hatch info container that displays the current pokemon / hatch (main element on left hand side) */
private infoContainer: PokemonHatchInfoContainer; private infoContainer: PokemonHatchInfoContainer;
/** handles jumping animations for the pokemon sprite icons */ /** handles jumping animations for the pokemon sprite icons */
private iconAnimHandler: PokemonIconAnimHandler; private iconAnimHandler: PokemonIconAnimHelper;
private eggHatchBg: Phaser.GameObjects.Image; private eggHatchBg: Phaser.GameObjects.Image;
private eggHatchData: EggHatchData[]; private eggHatchData: EggHatchData[];
private scrollGridHandler: ScrollableGridUiHandler; private scrollGridHandler: ScrollableGridHelper;
private cursorObj: Phaser.GameObjects.Image; private cursorObj: Phaser.GameObjects.Image;
/** used to add a delay before which it is not possible to exit the summary */ /** used to add a delay before which it is not possible to exit the summary */
@ -67,7 +67,7 @@ export class EggSummaryUiHandler extends MessageUiHandler {
this.eggHatchContainer.setVisible(false); this.eggHatchContainer.setVisible(false);
ui.add(this.eggHatchContainer); ui.add(this.eggHatchContainer);
this.iconAnimHandler = new PokemonIconAnimHandler(); this.iconAnimHandler = new PokemonIconAnimHelper();
this.iconAnimHandler.setup(); this.iconAnimHandler.setup();
this.eggHatchBg = globalScene.add.image(0, 0, "egg_summary_bg"); this.eggHatchBg = globalScene.add.image(0, 0, "egg_summary_bg");
@ -97,7 +97,7 @@ export class EggSummaryUiHandler extends MessageUiHandler {
); );
this.summaryContainer.add(scrollBar); this.summaryContainer.add(scrollBar);
this.scrollGridHandler = new ScrollableGridUiHandler(this, numRows, numCols) this.scrollGridHandler = new ScrollableGridHelper(this, numRows, numCols)
.withScrollBar(scrollBar) .withScrollBar(scrollBar)
.withUpdateGridCallBack(() => this.updatePokemonIcons()) .withUpdateGridCallBack(() => this.updatePokemonIcons())
.withUpdateSingleElementCallback((i: number) => this.infoContainer.showHatchInfo(this.eggHatchData[i])); .withUpdateSingleElementCallback((i: number) => this.infoContainer.showHatchInfo(this.eggHatchData[i]));

View File

@ -5,7 +5,7 @@ import { UiMode } from "#enums/ui-mode";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { addTextObject } from "#ui/text"; import { addTextObject } from "#ui/text";
export class EvolutionSceneHandler extends MessageUiHandler { export class EvolutionSceneUiHandler extends MessageUiHandler {
public evolutionContainer: Phaser.GameObjects.Container; public evolutionContainer: Phaser.GameObjects.Container;
public messageBg: Phaser.GameObjects.Image; public messageBg: Phaser.GameObjects.Image;
public messageContainer: Phaser.GameObjects.Container; public messageContainer: Phaser.GameObjects.Container;

View File

@ -23,9 +23,9 @@ import { getVariantTint } from "#sprites/variant";
import type { TurnMove } from "#types/turn-move"; import type { TurnMove } from "#types/turn-move";
import { MoveInfoOverlay } from "#ui/containers/move-info-overlay"; import { MoveInfoOverlay } from "#ui/containers/move-info-overlay";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/handlers/pokemon-icon-anim-handler";
import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text"; import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
import { PokemonIconAnimHelper, PokemonIconAnimMode } from "#ui/utils/pokemon-icon-anim-helper";
import { applyChallenges } from "#utils/challenge-utils"; import { applyChallenges } from "#utils/challenge-utils";
import { BooleanHolder, getLocalizedSpriteKey, randInt } from "#utils/common"; import { BooleanHolder, getLocalizedSpriteKey, randInt } from "#utils/common";
import { toCamelCase, toTitleCase } from "#utils/strings"; import { toCamelCase, toTitleCase } from "#utils/strings";
@ -201,7 +201,7 @@ export class PartyUiHandler extends MessageUiHandler {
private tmMoveId: MoveId; private tmMoveId: MoveId;
private showMovePp: boolean; private showMovePp: boolean;
private iconAnimHandler: PokemonIconAnimHandler; private iconAnimHandler: PokemonIconAnimHelper;
private blockInput: boolean; private blockInput: boolean;
@ -320,7 +320,7 @@ export class PartyUiHandler extends MessageUiHandler {
this.optionsContainer = globalScene.add.container(globalScene.scaledCanvas.width - 1, -1); this.optionsContainer = globalScene.add.container(globalScene.scaledCanvas.width - 1, -1);
partyContainer.add(this.optionsContainer); partyContainer.add(this.optionsContainer);
this.iconAnimHandler = new PokemonIconAnimHandler(); this.iconAnimHandler = new PokemonIconAnimHelper();
this.iconAnimHandler.setup(); this.iconAnimHandler.setup();
const partyDiscardModeButton = new PartyDiscardModeButton(DISCARD_BUTTON_X, DISCARD_BUTTON_Y, this); const partyDiscardModeButton = new PartyDiscardModeButton(DISCARD_BUTTON_X, DISCARD_BUTTON_Y, this);
@ -1892,12 +1892,12 @@ class PartySlot extends Phaser.GameObjects.Container {
private slotBgKey: string; private slotBgKey: string;
private pokemonIcon: Phaser.GameObjects.Container; private pokemonIcon: Phaser.GameObjects.Container;
private iconAnimHandler: PokemonIconAnimHandler; private iconAnimHandler: PokemonIconAnimHelper;
constructor( constructor(
slotIndex: number, slotIndex: number,
pokemon: PlayerPokemon, pokemon: PlayerPokemon,
iconAnimHandler: PokemonIconAnimHandler, iconAnimHandler: PokemonIconAnimHelper,
partyUiMode: PartyUiMode, partyUiMode: PartyUiMode,
tmMoveId: MoveId, tmMoveId: MoveId,
) { ) {

View File

@ -48,9 +48,9 @@ import { PokedexMonContainer } from "#ui/containers/pokedex-mon-container";
import { ScrollBar } from "#ui/containers/scroll-bar"; import { ScrollBar } from "#ui/containers/scroll-bar";
import type { OptionSelectConfig } from "#ui/handlers/abstract-option-select-ui-handler"; import type { OptionSelectConfig } from "#ui/handlers/abstract-option-select-ui-handler";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/handlers/pokemon-icon-anim-handler";
import { addTextObject, getTextColor } from "#ui/text"; import { addTextObject, getTextColor } from "#ui/text";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
import { PokemonIconAnimHelper, PokemonIconAnimMode } from "#ui/utils/pokemon-icon-anim-helper";
import { BooleanHolder, fixedInt, getLocalizedSpriteKey, padInt, randIntRange, rgbHexToRgba } from "#utils/common"; import { BooleanHolder, fixedInt, getLocalizedSpriteKey, padInt, randIntRange, rgbHexToRgba } from "#utils/common";
import type { StarterPreferences } from "#utils/data"; import type { StarterPreferences } from "#utils/data";
import { loadStarterPreferences } from "#utils/data"; import { loadStarterPreferences } from "#utils/data";
@ -198,7 +198,7 @@ export class PokedexUiHandler extends MessageUiHandler {
public cursorObj: Phaser.GameObjects.Image; public cursorObj: Phaser.GameObjects.Image;
private pokerusCursorObjs: Phaser.GameObjects.Image[]; private pokerusCursorObjs: Phaser.GameObjects.Image[];
private iconAnimHandler: PokemonIconAnimHandler; private iconAnimHandler: PokemonIconAnimHelper;
private starterPreferences: StarterPreferences; private starterPreferences: StarterPreferences;
@ -482,7 +482,7 @@ export class PokedexUiHandler extends MessageUiHandler {
pokemonContainerWindow.setVisible(false); pokemonContainerWindow.setVisible(false);
} }
this.iconAnimHandler = new PokemonIconAnimHandler(); this.iconAnimHandler = new PokemonIconAnimHelper();
this.iconAnimHandler.setup(); this.iconAnimHandler.setup();
this.pokemonNumberText = addTextObject(6, 141, "", TextStyle.SUMMARY); this.pokemonNumberText = addTextObject(6, 141, "", TextStyle.SUMMARY);

View File

@ -65,9 +65,9 @@ import { StarterContainer } from "#ui/containers/starter-container";
import { StatsContainer } from "#ui/containers/stats-container"; import { StatsContainer } from "#ui/containers/stats-container";
import type { OptionSelectItem } from "#ui/handlers/abstract-option-select-ui-handler"; import type { OptionSelectItem } from "#ui/handlers/abstract-option-select-ui-handler";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/handlers/pokemon-icon-anim-handler";
import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text"; import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
import { PokemonIconAnimHelper, PokemonIconAnimMode } from "#ui/utils/pokemon-icon-anim-helper";
import { applyChallenges, checkStarterValidForChallenge } from "#utils/challenge-utils"; import { applyChallenges, checkStarterValidForChallenge } from "#utils/challenge-utils";
import { import {
BooleanHolder, BooleanHolder,
@ -384,7 +384,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
private startCursorObj: Phaser.GameObjects.NineSlice; private startCursorObj: Phaser.GameObjects.NineSlice;
private randomCursorObj: Phaser.GameObjects.NineSlice; private randomCursorObj: Phaser.GameObjects.NineSlice;
private iconAnimHandler: PokemonIconAnimHandler; private iconAnimHandler: PokemonIconAnimHelper;
//variables to keep track of the dynamically rendered list of instruction prompts for starter select //variables to keep track of the dynamically rendered list of instruction prompts for starter select
private instructionRowX = 0; private instructionRowX = 0;
@ -597,7 +597,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
starterContainerWindow.setVisible(false); starterContainerWindow.setVisible(false);
} }
this.iconAnimHandler = new PokemonIconAnimHandler(); this.iconAnimHandler = new PokemonIconAnimHelper();
this.iconAnimHandler.setup(); this.iconAnimHandler.setup();
this.pokemonSprite = globalScene.add.sprite(53, 63, "pkmn__sub"); this.pokemonSprite = globalScene.add.sprite(53, 63, "pkmn__sub");

View File

@ -4,6 +4,7 @@ import { TextStyle } from "#enums/text-style";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import type { SettingType } from "#system/settings"; import type { SettingType } from "#system/settings";
import { Setting, SettingKeys } from "#system/settings"; import { Setting, SettingKeys } from "#system/settings";
import type { AnyFn } from "#types/type-helpers";
import type { InputsIcons } from "#ui/abstract-control-settings-ui-handler"; import type { InputsIcons } from "#ui/abstract-control-settings-ui-handler";
import { ScrollBar } from "#ui/containers/scroll-bar"; import { ScrollBar } from "#ui/containers/scroll-bar";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
@ -53,54 +54,47 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
*/ */
setup() { setup() {
const ui = this.getUi(); const ui = this.getUi();
const canvasWidth = globalScene.scaledCanvas.width;
const canvasHeight = globalScene.scaledCanvas.height;
this.settingsContainer = globalScene.add.container(1, -globalScene.scaledCanvas.height + 1); this.settingsContainer = globalScene.add
this.settingsContainer.setName(`settings-${this.title}`); .container(1, -canvasHeight + 1)
this.settingsContainer.setInteractive( .setName(`settings-${this.title}`)
new Phaser.Geom.Rectangle(0, 0, globalScene.scaledCanvas.width, globalScene.scaledCanvas.height - 20), .setInteractive(new Phaser.Geom.Rectangle(0, 0, canvasWidth, canvasHeight - 20), Phaser.Geom.Rectangle.Contains);
Phaser.Geom.Rectangle.Contains,
);
this.navigationIcons = {}; this.navigationIcons = {};
this.navigationContainer = new NavigationMenu(0, 0); this.navigationContainer = new NavigationMenu(0, 0);
const navWidth = this.navigationContainer.width;
const navHeight = this.navigationContainer.height;
this.optionsBg = addWindow( this.optionsBg = addWindow(0, navHeight, canvasWidth - 2, canvasHeight - 16 - navHeight - 2)
0, .setName("window-options-bg")
this.navigationContainer.height, .setOrigin(0);
globalScene.scaledCanvas.width - 2,
globalScene.scaledCanvas.height - 16 - this.navigationContainer.height - 2,
);
this.optionsBg.setName("window-options-bg");
this.optionsBg.setOrigin(0, 0);
const actionsBg = addWindow( const actionsBg = addWindow(0, canvasHeight - navHeight, canvasWidth - 2, 22) // formatting
0, .setOrigin(0);
globalScene.scaledCanvas.height - this.navigationContainer.height,
globalScene.scaledCanvas.width - 2,
22,
);
actionsBg.setOrigin(0, 0);
const iconAction = globalScene.add.sprite(0, 0, "keyboard"); const iconAction = globalScene.add
iconAction.setOrigin(0, -0.1); .sprite(0, 0, "keyboard")
iconAction.setPositionRelative(actionsBg, this.navigationContainer.width - 32, 4); .setOrigin(0, -0.1)
.setPositionRelative(actionsBg, navWidth - 32, 4);
this.navigationIcons["BUTTON_ACTION"] = iconAction; this.navigationIcons["BUTTON_ACTION"] = iconAction;
const actionText = addTextObject(0, 0, i18next.t("settings:action"), TextStyle.SETTINGS_LABEL); const actionText = addTextObject(0, 0, i18next.t("settings:action"), TextStyle.SETTINGS_LABEL).setOrigin(0, 0.15);
actionText.setOrigin(0, 0.15);
actionText.setPositionRelative(iconAction, -actionText.width / 6 - 2, 0); actionText.setPositionRelative(iconAction, -actionText.width / 6 - 2, 0);
const iconCancel = globalScene.add.sprite(0, 0, "keyboard"); const iconCancel = globalScene.add
iconCancel.setOrigin(0, -0.1); .sprite(0, 0, "keyboard")
iconCancel.setPositionRelative(actionsBg, actionText.x - 28, 4); .setOrigin(0, -0.1)
.setPositionRelative(actionsBg, actionText.x - 28, 4);
this.navigationIcons["BUTTON_CANCEL"] = iconCancel; this.navigationIcons["BUTTON_CANCEL"] = iconCancel;
const cancelText = addTextObject(0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL); const cancelText = addTextObject(0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL) // formatting
cancelText.setOrigin(0, 0.15); .setOrigin(0, 0.15);
cancelText.setPositionRelative(iconCancel, -cancelText.width / 6 - 2, 0); cancelText.setPositionRelative(iconCancel, -cancelText.width / 6 - 2, 0);
this.optionsContainer = globalScene.add.container(0, 0); this.optionsContainer = globalScene.add.container();
this.settingLabels = []; this.settingLabels = [];
this.optionValueLabels = []; this.optionValueLabels = [];
@ -113,8 +107,7 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
anyReloadRequired = true; anyReloadRequired = true;
} }
this.settingLabels[s] = addTextObject(8, 28 + s * 16, settingName, TextStyle.SETTINGS_LABEL); this.settingLabels[s] = addTextObject(8, 28 + s * 16, settingName, TextStyle.SETTINGS_LABEL).setOrigin(0);
this.settingLabels[s].setOrigin(0, 0);
this.optionsContainer.add(this.settingLabels[s]); this.optionsContainer.add(this.settingLabels[s]);
this.optionValueLabels.push( this.optionValueLabels.push(
@ -125,7 +118,7 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
option.label, option.label,
setting.default === o ? TextStyle.SETTINGS_SELECTED : TextStyle.SETTINGS_VALUE, setting.default === o ? TextStyle.SETTINGS_SELECTED : TextStyle.SETTINGS_VALUE,
); );
valueLabel.setOrigin(0, 0); valueLabel.setOrigin(0);
this.optionsContainer.add(valueLabel); this.optionsContainer.add(valueLabel);
@ -160,32 +153,33 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
this.scrollBar.setTotalRows(this.settings.length); this.scrollBar.setTotalRows(this.settings.length);
// Two-lines message box // Two-lines message box
this.messageBoxContainer = globalScene.add.container(0, globalScene.scaledCanvas.height); this.messageBoxContainer = globalScene.add
this.messageBoxContainer.setName("settings-message-box"); .container(0, globalScene.scaledCanvas.height)
this.messageBoxContainer.setVisible(false); .setName("settings-message-box")
.setVisible(false);
const settingsMessageBox = addWindow(0, -1, globalScene.scaledCanvas.width - 2, 48); const settingsMessageBox = addWindow(0, -1, globalScene.scaledCanvas.width - 2, 48);
settingsMessageBox.setOrigin(0, 1); settingsMessageBox.setOrigin(0, 1);
this.messageBoxContainer.add(settingsMessageBox); this.messageBoxContainer.add(settingsMessageBox);
const messageText = addTextObject(8, -40, "", TextStyle.WINDOW, { const messageText = addTextObject(8, -40, "", TextStyle.WINDOW, { maxLines: 2 })
maxLines: 2, .setWordWrapWidth(globalScene.game.canvas.width - 60)
}); .setName("settings-message")
messageText.setWordWrapWidth(globalScene.game.canvas.width - 60); .setOrigin(0);
messageText.setName("settings-message");
messageText.setOrigin(0, 0);
this.messageBoxContainer.add(messageText); this.messageBoxContainer.add(messageText);
this.message = messageText; this.message = messageText;
this.settingsContainer.add(this.optionsBg); this.settingsContainer.add([
this.settingsContainer.add(this.scrollBar); this.optionsBg,
this.settingsContainer.add(this.navigationContainer); this.scrollBar,
this.settingsContainer.add(actionsBg); this.navigationContainer,
this.settingsContainer.add(this.optionsContainer); actionsBg,
this.settingsContainer.add(iconAction); this.optionsContainer,
this.settingsContainer.add(iconCancel); iconAction,
this.settingsContainer.add(actionText); iconCancel,
actionText,
]);
// Only add the ReloadRequired text on pages that have settings that require a reload. // Only add the ReloadRequired text on pages that have settings that require a reload.
if (anyReloadRequired) { if (anyReloadRequired) {
const reloadRequired = addTextObject(0, 0, `*${i18next.t("settings:requireReload")}`, TextStyle.SETTINGS_LABEL) const reloadRequired = addTextObject(0, 0, `*${i18next.t("settings:requireReload")}`, TextStyle.SETTINGS_LABEL)
@ -194,8 +188,7 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
.setY(actionText.y); .setY(actionText.y);
this.settingsContainer.add(reloadRequired); this.settingsContainer.add(reloadRequired);
} }
this.settingsContainer.add(cancelText); this.settingsContainer.add([cancelText, this.messageBoxContainer]);
this.settingsContainer.add(this.messageBoxContainer);
ui.add(this.settingsContainer); ui.add(this.settingsContainer);
@ -210,17 +203,13 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
updateBindings(): void { updateBindings(): void {
for (const settingName of Object.keys(this.navigationIcons)) { for (const settingName of Object.keys(this.navigationIcons)) {
if (settingName === "BUTTON_HOME") { if (settingName === "BUTTON_HOME") {
this.navigationIcons[settingName].setTexture("keyboard"); this.navigationIcons[settingName].setTexture("keyboard").setFrame("HOME.png").alpha = 1;
this.navigationIcons[settingName].setFrame("HOME.png");
this.navigationIcons[settingName].alpha = 1;
continue; continue;
} }
const icon = globalScene.inputController?.getIconForLatestInputRecorded(settingName); const icon = globalScene.inputController?.getIconForLatestInputRecorded(settingName);
if (icon) { if (icon) {
const type = globalScene.inputController?.getLastSourceType(); const type = globalScene.inputController?.getLastSourceType();
this.navigationIcons[settingName].setTexture(type); this.navigationIcons[settingName].setTexture(type).setFrame(icon).alpha = 1;
this.navigationIcons[settingName].setFrame(icon);
this.navigationIcons[settingName].alpha = 1;
} else { } else {
this.navigationIcons[settingName].alpha = 0; this.navigationIcons[settingName].alpha = 0;
} }
@ -242,21 +231,43 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
? JSON.parse(localStorage.getItem(this.localStorageKey)!) ? JSON.parse(localStorage.getItem(this.localStorageKey)!)
: {}; // TODO: is this bang correct? : {}; // TODO: is this bang correct?
this.settings.forEach((setting, s) => this.settings.forEach((setting, s) => {
this.setOptionCursor(s, settings.hasOwnProperty(setting.key) ? settings[setting.key] : this.settings[s].default), this.setOptionCursor(s, settings.hasOwnProperty(setting.key) ? settings[setting.key] : this.settings[s].default);
); });
this.settingsContainer.setVisible(true); this.settingsContainer.setVisible(true);
this.setCursor(0); this.setCursor(0);
this.setScrollCursor(0); this.setScrollCursor(0);
this.getUi().moveTo(this.settingsContainer, this.getUi().length - 1); const ui = this.getUi();
this.getUi().hideTooltip(); ui.moveTo(this.settingsContainer, ui.length - 1);
ui.hideTooltip();
return true; return true;
} }
/**
* Submethod of {@linkcode processInput} to handle left/right input for changing option values
*
* @remarks
* If the cursor is positioned on a boundary option, will apply clamping / wrapping as appropriate
* @param cursor - Current cursor position in the settings menu
* @param dir - Direction to pan when scrolling, -1 for left, 1 for right
* @returns `true` if the action associated with the button was successfully processed, `false` otherwise.
*/
private processLeftRightInput(cursor: number, dir: -1 | 1): boolean {
let boundaryAction = Phaser.Math.Wrap;
let upperBound = this.optionValueLabels[cursor].length;
if (this.settings[cursor]?.clamp) {
boundaryAction = Phaser.Math.Clamp;
// clamping is right inclusive; wrapping isn't
upperBound -= 1;
}
return this.setOptionCursor(cursor, boundaryAction(this.optionCursors[cursor] + dir, 0, upperBound), true);
}
/** /**
* Processes input from a specified button. * Processes input from a specified button.
* This method handles navigation through a UI menu, including movement through menu items * This method handles navigation through a UI menu, including movement through menu items
@ -314,20 +325,10 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
} }
break; break;
case Button.LEFT: case Button.LEFT:
// Cycle to the rightmost position when at the leftmost, otherwise move left success = this.processLeftRightInput(cursor, -1);
success = this.setOptionCursor(
cursor,
Phaser.Math.Wrap(this.optionCursors[cursor] - 1, 0, this.optionValueLabels[cursor].length),
true,
);
break; break;
case Button.RIGHT: case Button.RIGHT:
// Cycle to the leftmost position when at the rightmost, otherwise move right success = this.processLeftRightInput(cursor, 1);
success = this.setOptionCursor(
cursor,
Phaser.Math.Wrap(this.optionCursors[cursor] + 1, 0, this.optionValueLabels[cursor].length),
true,
);
break; break;
case Button.CYCLE_FORM: case Button.CYCLE_FORM:
case Button.CYCLE_SHINY: case Button.CYCLE_SHINY:
@ -376,8 +377,9 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
if (!this.cursorObj) { if (!this.cursorObj) {
const cursorWidth = globalScene.scaledCanvas.width - (this.scrollBar.visible ? 16 : 10); const cursorWidth = globalScene.scaledCanvas.width - (this.scrollBar.visible ? 16 : 10);
this.cursorObj = globalScene.add.nineslice(0, 0, "summary_moves_cursor", undefined, cursorWidth, 16, 1, 1, 1, 1); this.cursorObj = globalScene.add
this.cursorObj.setOrigin(0, 0); .nineslice(0, 0, "summary_moves_cursor", undefined, cursorWidth, 16, 1, 1, 1, 1)
.setOrigin(0);
this.optionsContainer.add(this.cursorObj); this.optionsContainer.add(this.cursorObj);
} }
@ -399,18 +401,21 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
settingIndex = this.cursor + this.scrollCursor; settingIndex = this.cursor + this.scrollCursor;
} }
const setting = this.settings[settingIndex]; const setting = this.settings[settingIndex];
const lastCursor = this.optionCursors[settingIndex]; const lastCursor = this.optionCursors[settingIndex];
// do nothing if the option isn't changing
if (cursor === lastCursor) {
return false;
}
const lastValueLabel = this.optionValueLabels[settingIndex][lastCursor]; this.optionValueLabels[settingIndex][lastCursor]
lastValueLabel.setColor(getTextColor(TextStyle.SETTINGS_VALUE)); .setColor(getTextColor(TextStyle.SETTINGS_VALUE))
lastValueLabel.setShadowColor(getTextColor(TextStyle.SETTINGS_VALUE, true)); .setShadowColor(getTextColor(TextStyle.SETTINGS_VALUE, true));
this.optionCursors[settingIndex] = cursor; this.optionCursors[settingIndex] = cursor;
const newValueLabel = this.optionValueLabels[settingIndex][cursor]; this.optionValueLabels[settingIndex][cursor]
newValueLabel.setColor(getTextColor(TextStyle.SETTINGS_SELECTED)); .setColor(getTextColor(TextStyle.SETTINGS_SELECTED))
newValueLabel.setShadowColor(getTextColor(TextStyle.SETTINGS_SELECTED, true)); .setShadowColor(getTextColor(TextStyle.SETTINGS_SELECTED, true));
if (save) { if (save) {
const saveSetting = () => { const saveSetting = () => {
@ -511,7 +516,7 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
override showText( override showText(
text: string, text: string,
delay?: number, delay?: number,
callback?: Function, callback?: AnyFn,
callbackDelay?: number, callbackDelay?: number,
prompt?: boolean, prompt?: boolean,
promptDelay?: number, promptDelay?: number,

View File

@ -6,8 +6,7 @@ import { TextStyle } from "#enums/text-style";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { AchvBar } from "#ui/containers/achv-bar"; import { AchvBar } from "#ui/containers/achv-bar";
import type { BgmBar } from "#ui/containers/bgm-bar"; import type { BgmBar } from "#ui/containers/bgm-bar";
import { PokedexPageUiHandler } from "#ui/containers/pokedex-page-ui-handler"; import { SavingIconContainer } from "#ui/containers/saving-icon-handler";
import { SavingIconHandler } from "#ui/containers/saving-icon-handler";
import { GamepadBindingUiHandler } from "#ui/gamepad-binding-ui-handler"; import { GamepadBindingUiHandler } from "#ui/gamepad-binding-ui-handler";
import { AchvsUiHandler } from "#ui/handlers/achvs-ui-handler"; import { AchvsUiHandler } from "#ui/handlers/achvs-ui-handler";
import { AutoCompleteUiHandler } from "#ui/handlers/autocomplete-ui-handler"; import { AutoCompleteUiHandler } from "#ui/handlers/autocomplete-ui-handler";
@ -19,10 +18,10 @@ import { ChangePasswordFormUiHandler } from "#ui/handlers/change-password-form-u
import { CommandUiHandler } from "#ui/handlers/command-ui-handler"; import { CommandUiHandler } from "#ui/handlers/command-ui-handler";
import { ConfirmUiHandler } from "#ui/handlers/confirm-ui-handler"; import { ConfirmUiHandler } from "#ui/handlers/confirm-ui-handler";
import { EggGachaUiHandler } from "#ui/handlers/egg-gacha-ui-handler"; import { EggGachaUiHandler } from "#ui/handlers/egg-gacha-ui-handler";
import { EggHatchSceneHandler } from "#ui/handlers/egg-hatch-scene-handler"; import { EggHatchSceneUiHandler } from "#ui/handlers/egg-hatch-scene-ui-handler";
import { EggListUiHandler } from "#ui/handlers/egg-list-ui-handler"; import { EggListUiHandler } from "#ui/handlers/egg-list-ui-handler";
import { EggSummaryUiHandler } from "#ui/handlers/egg-summary-ui-handler"; import { EggSummaryUiHandler } from "#ui/handlers/egg-summary-ui-handler";
import { EvolutionSceneHandler } from "#ui/handlers/evolution-scene-handler"; import { EvolutionSceneUiHandler } from "#ui/handlers/evolution-scene-ui-handler";
import { FightUiHandler } from "#ui/handlers/fight-ui-handler"; import { FightUiHandler } from "#ui/handlers/fight-ui-handler";
import { GameStatsUiHandler } from "#ui/handlers/game-stats-ui-handler"; import { GameStatsUiHandler } from "#ui/handlers/game-stats-ui-handler";
import { LoadingModalUiHandler } from "#ui/handlers/loading-modal-ui-handler"; import { LoadingModalUiHandler } from "#ui/handlers/loading-modal-ui-handler";
@ -32,6 +31,7 @@ import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { ModifierSelectUiHandler } from "#ui/handlers/modifier-select-ui-handler"; import { ModifierSelectUiHandler } from "#ui/handlers/modifier-select-ui-handler";
import { MysteryEncounterUiHandler } from "#ui/handlers/mystery-encounter-ui-handler"; import { MysteryEncounterUiHandler } from "#ui/handlers/mystery-encounter-ui-handler";
import { PartyUiHandler } from "#ui/handlers/party-ui-handler"; import { PartyUiHandler } from "#ui/handlers/party-ui-handler";
import { PokedexPageUiHandler } from "#ui/handlers/pokedex-page-ui-handler";
import { PokedexScanUiHandler } from "#ui/handlers/pokedex-scan-ui-handler"; import { PokedexScanUiHandler } from "#ui/handlers/pokedex-scan-ui-handler";
import { PokedexUiHandler } from "#ui/handlers/pokedex-ui-handler"; import { PokedexUiHandler } from "#ui/handlers/pokedex-ui-handler";
import { RegistrationFormUiHandler } from "#ui/handlers/registration-form-ui-handler"; import { RegistrationFormUiHandler } from "#ui/handlers/registration-form-ui-handler";
@ -115,7 +115,7 @@ export class UI extends Phaser.GameObjects.Container {
private overlay: Phaser.GameObjects.Rectangle; private overlay: Phaser.GameObjects.Rectangle;
public achvBar: AchvBar; public achvBar: AchvBar;
public bgmBar: BgmBar; public bgmBar: BgmBar;
public savingIcon: SavingIconHandler; public savingIcon: SavingIconContainer;
private tooltipContainer: Phaser.GameObjects.Container; private tooltipContainer: Phaser.GameObjects.Container;
private tooltipBg: Phaser.GameObjects.NineSlice; private tooltipBg: Phaser.GameObjects.NineSlice;
@ -141,8 +141,8 @@ export class UI extends Phaser.GameObjects.Container {
new PartyUiHandler(), new PartyUiHandler(),
new SummaryUiHandler(), new SummaryUiHandler(),
new StarterSelectUiHandler(), new StarterSelectUiHandler(),
new EvolutionSceneHandler(), new EvolutionSceneUiHandler(),
new EggHatchSceneHandler(), new EggHatchSceneUiHandler(),
new EggSummaryUiHandler(), new EggSummaryUiHandler(),
new ConfirmUiHandler(), new ConfirmUiHandler(),
new OptionSelectUiHandler(), new OptionSelectUiHandler(),
@ -198,7 +198,7 @@ export class UI extends Phaser.GameObjects.Container {
globalScene.uiContainer.add(this.achvBar); globalScene.uiContainer.add(this.achvBar);
this.savingIcon = new SavingIconHandler(); this.savingIcon = new SavingIconContainer();
this.savingIcon.setup(); this.savingIcon.setup();
globalScene.uiContainer.add(this.savingIcon); globalScene.uiContainer.add(this.savingIcon);

View File

@ -9,7 +9,7 @@ export enum PokemonIconAnimMode {
type PokemonIcon = Phaser.GameObjects.Container | Phaser.GameObjects.Sprite; type PokemonIcon = Phaser.GameObjects.Container | Phaser.GameObjects.Sprite;
export class PokemonIconAnimHandler { export class PokemonIconAnimHelper {
private icons: Map<PokemonIcon, PokemonIconAnimMode>; private icons: Map<PokemonIcon, PokemonIconAnimMode>;
private toggled: boolean; private toggled: boolean;

View File

@ -16,7 +16,7 @@ type UpdateDetailsCallbackFunction = (index: number) => void;
* - in `UiHandler.processInput`: call `processNavigationInput` to have it handle the cursor updates while calling the defined callbacks * - in `UiHandler.processInput`: call `processNavigationInput` to have it handle the cursor updates while calling the defined callbacks
* - in `UiHandler.clear`: call `reset` * - in `UiHandler.clear`: call `reset`
*/ */
export class ScrollableGridUiHandler { export class ScrollableGridHelper {
private readonly ROWS: number; private readonly ROWS: number;
private readonly COLUMNS: number; private readonly COLUMNS: number;
private handler: UiHandler; private handler: UiHandler;
@ -47,7 +47,7 @@ export class ScrollableGridUiHandler {
* @param scrollBar {@linkcode ScrollBar} * @param scrollBar {@linkcode ScrollBar}
* @returns this * @returns this
*/ */
withScrollBar(scrollBar: ScrollBar): ScrollableGridUiHandler { withScrollBar(scrollBar: ScrollBar): ScrollableGridHelper {
this.scrollBar = scrollBar; this.scrollBar = scrollBar;
this.scrollBar.setTotalRows(Math.ceil(this.totalElements / this.COLUMNS)); this.scrollBar.setTotalRows(Math.ceil(this.totalElements / this.COLUMNS));
return this; return this;
@ -58,7 +58,7 @@ export class ScrollableGridUiHandler {
* @param callback {@linkcode UpdateGridCallbackFunction} * @param callback {@linkcode UpdateGridCallbackFunction}
* @returns this * @returns this
*/ */
withUpdateGridCallBack(callback: UpdateGridCallbackFunction): ScrollableGridUiHandler { withUpdateGridCallBack(callback: UpdateGridCallbackFunction): ScrollableGridHelper {
this.updateGridCallback = callback; this.updateGridCallback = callback;
return this; return this;
} }
@ -68,7 +68,7 @@ export class ScrollableGridUiHandler {
* @param callback {@linkcode UpdateDetailsCallbackFunction} * @param callback {@linkcode UpdateDetailsCallbackFunction}
* @returns this * @returns this
*/ */
withUpdateSingleElementCallback(callback: UpdateDetailsCallbackFunction): ScrollableGridUiHandler { withUpdateSingleElementCallback(callback: UpdateDetailsCallbackFunction): ScrollableGridHelper {
this.updateDetailsCallback = callback; this.updateDetailsCallback = callback;
return this; return this;
} }

View File

@ -9,7 +9,7 @@ import { UiMode } from "#enums/ui-mode";
import type { StarterAttributes } from "#system/game-data"; import type { StarterAttributes } from "#system/game-data";
import { GameManager } from "#test/test-utils/game-manager"; import { GameManager } from "#test/test-utils/game-manager";
import { FilterTextRow } from "#ui/containers/filter-text"; import { FilterTextRow } from "#ui/containers/filter-text";
import { PokedexPageUiHandler } from "#ui/containers/pokedex-page-ui-handler"; import { PokedexPageUiHandler } from "#ui/handlers/pokedex-page-ui-handler";
import { PokedexUiHandler } from "#ui/handlers/pokedex-ui-handler"; import { PokedexUiHandler } from "#ui/handlers/pokedex-ui-handler";
import { getPokemonSpecies } from "#utils/pokemon-utils"; import { getPokemonSpecies } from "#utils/pokemon-utils";
import Phaser from "phaser"; import Phaser from "phaser";