extracted UI inputs out of battle-scene

This commit is contained in:
Greenlamp 2024-05-03 17:40:44 +02:00
parent 9853a3ae75
commit 5197311cd8
29 changed files with 189 additions and 160 deletions

View File

@ -60,7 +60,8 @@ import CandyBar from './ui/candy-bar';
import { Variant, variantData } from './data/variant';
import { Localizable } from './plugins/i18n';
import { STARTING_WAVE_OVERRIDE, OPP_SPECIES_OVERRIDE, SEED_OVERRIDE, STARTING_BIOME_OVERRIDE } from './overrides';
import {Button, InputsController} from "#app/inputsController";
import {InputsController} from "./inputs-controller";
import {UiInputs} from "./ui-inputs";
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
@ -85,6 +86,7 @@ export type AnySound = Phaser.Sound.WebAudioSound | Phaser.Sound.HTML5AudioSound
export default class BattleScene extends SceneBase {
public rexUI: UIPlugin;
public inputController: InputsController;
public uiInputs: UiInputs;
public sessionPlayTime: integer = null;
public masterVolume: number = 0.5;
@ -201,6 +203,7 @@ export default class BattleScene extends SceneBase {
async preload() {
this.load.scenePlugin('inputController', InputsController);
this.load.scenePlugin('uiInputs', UiInputs);
if (DEBUG_RNG) {
const scene = this;
const originalRealInRange = Phaser.Math.RND.realInRange;
@ -224,7 +227,6 @@ export default class BattleScene extends SceneBase {
initGameSpeed.apply(this);
this.gameData = new GameData(this);
this.listenInputs();
addUiThemeOverrides(this);
@ -243,23 +245,6 @@ export default class BattleScene extends SceneBase {
this.ui?.update();
}
listenInputs(): void {
this.inputController.events.on('input_down', (event) => {
const actions = this.getActionsKeyDown();
if (!actions.hasOwnProperty(event.button)) return;
const [inputSuccess, vibrationLength] = actions[event.button]();
if (inputSuccess && this.enableVibration && typeof navigator.vibrate !== 'undefined')
navigator.vibrate(vibrationLength);
}, this);
this.inputController.events.on('input_up', (event) => {
const actions = this.getActionsKeyUp();
if (!actions.hasOwnProperty(event.button)) return;
const [inputSuccess, vibrationLength] = actions[event.button]();
if (inputSuccess && this.enableVibration && typeof navigator.vibrate !== 'undefined')
navigator.vibrate(vibrationLength);
}, this);
}
launchBattle() {
this.arenaBg = this.add.sprite(0, 0, 'plains_bg');
this.arenaBgTransition = this.add.sprite(0, 0, 'plains_bg');
@ -1276,121 +1261,6 @@ export default class BattleScene extends SceneBase {
return biomes[Utils.randSeedInt(biomes.length)];
}
buttonDirection(direction): Array<boolean | number> {
const inputSuccess = this.ui.processInput(direction);
const vibrationLength = 5;
return [inputSuccess, vibrationLength];
}
buttonAb(button): Array<boolean | number> {
const inputSuccess = this.ui.processInput(button);
return [inputSuccess, 0];
}
buttonTouch(): Array<boolean | number> {
const inputSuccess = this.ui.processInput(Button.SUBMIT) || this.ui.processInput(Button.ACTION);
return [inputSuccess, 0];
}
buttonStats(pressed = true): Array<boolean | number> {
if (pressed) {
for (let p of this.getField().filter(p => p?.isActive(true)))
p.toggleStats(true);
} else {
for (let p of this.getField().filter(p => p?.isActive(true)))
p.toggleStats(false);
}
return [true, 0];
}
buttonMenu(): Array<boolean | number> {
let inputSuccess;
if (this.disableMenu)
return [true, 0];
switch (this.ui?.getMode()) {
case Mode.MESSAGE:
if (!(this.ui.getHandler() as MessageUiHandler).pendingPrompt)
return [true, 0];
case Mode.TITLE:
case Mode.COMMAND:
case Mode.FIGHT:
case Mode.BALL:
case Mode.TARGET_SELECT:
case Mode.SAVE_SLOT:
case Mode.PARTY:
case Mode.SUMMARY:
case Mode.STARTER_SELECT:
case Mode.CONFIRM:
case Mode.OPTION_SELECT:
this.ui.setOverlayMode(Mode.MENU);
inputSuccess = true;
break;
case Mode.MENU:
case Mode.SETTINGS:
case Mode.ACHIEVEMENTS:
this.ui.revertMode();
this.playSound('select');
inputSuccess = true;
break;
default:
return [true, 0];
}
return [inputSuccess, 0];
}
buttonCycleOption(button): Array<boolean | number> {
let inputSuccess;
if (this.ui?.getHandler() instanceof StarterSelectUiHandler) {
inputSuccess = this.ui.processInput(button);
}
return [inputSuccess, 0];
}
buttonSpeedChange(up= true): Array<boolean | number> {
if (up) {
if (this.gameSpeed < 5) {
this.gameData.saveSetting(Setting.Game_Speed, settingOptions[Setting.Game_Speed].indexOf(`${this.gameSpeed}x`) + 1);
if (this.ui?.getMode() === Mode.SETTINGS)
(this.ui.getHandler() as SettingsUiHandler).show([]);
}
return [0, 0];
}
if (this.gameSpeed > 1) {
this.gameData.saveSetting(Setting.Game_Speed, Math.max(settingOptions[Setting.Game_Speed].indexOf(`${this.gameSpeed}x`) - 1, 0));
if (this.ui?.getMode() === Mode.SETTINGS)
(this.ui.getHandler() as SettingsUiHandler).show([]);
}
return [0, 0];
}
getActionsKeyDown() {
const actions = {};
actions[Button.UP] = () => this.buttonDirection(Button.UP);
actions[Button.DOWN] = () => this.buttonDirection(Button.DOWN);
actions[Button.LEFT] = () => this.buttonDirection(Button.LEFT);
actions[Button.RIGHT] = () => this.buttonDirection(Button.RIGHT);
actions[Button.SUBMIT] = () => this.buttonTouch();
actions[Button.ACTION] = () => this.buttonAb(Button.ACTION);
actions[Button.CANCEL] = () => this.buttonAb(Button.CANCEL);
actions[Button.MENU] = () => this.buttonMenu();
actions[Button.STATS] = () => this.buttonStats(true);
actions[Button.CYCLE_SHINY] = () => this.buttonCycleOption(Button.CYCLE_SHINY);
actions[Button.CYCLE_FORM] = () => this.buttonCycleOption(Button.CYCLE_FORM);
actions[Button.CYCLE_GENDER] = () => this.buttonCycleOption(Button.CYCLE_GENDER);
actions[Button.CYCLE_ABILITY] = () => this.buttonCycleOption(Button.CYCLE_ABILITY);
actions[Button.CYCLE_NATURE] = () => this.buttonCycleOption(Button.CYCLE_NATURE);
actions[Button.CYCLE_VARIANT] = () => this.buttonCycleOption(Button.CYCLE_VARIANT);
actions[Button.SPEED_UP] = () => this.buttonSpeedChange();
actions[Button.SLOW_DOWN] = () => this.buttonSpeedChange(false);
return actions;
}
getActionsKeyUp() {
const actions = {};
actions[Button.STATS] = () => this.buttonStats(false);
return actions;
}
isBgmPlaying(): boolean {
return this.bgm && this.bgm.isPlaying;
}

159
src/ui-inputs.ts Normal file
View File

@ -0,0 +1,159 @@
import Phaser from "phaser";
import UI, {Mode} from "./ui/ui";
import {Button} from "#app/inputs-controller";
import MessageUiHandler from "#app/ui/message-ui-handler";
import StarterSelectUiHandler from "#app/ui/starter-select-ui-handler";
import {Setting, settingOptions} from "#app/system/settings";
import SettingsUiHandler from "#app/ui/settings-ui-handler";
export class UiInputs extends Phaser.Plugins.ScenePlugin {
private game: Phaser.Game;
private scene: Phaser.Scene;
private events;
constructor(scene: Phaser.Scene, pluginManager: Phaser.Plugins.PluginManager, pluginKey: string) {
super(scene, pluginManager, pluginKey);
this.game = pluginManager.game;
this.scene = scene;
this.events = this.scene.inputController.events
}
boot() {
this.listenInputs();
}
listenInputs(): void {
this.events.on('input_down', (event) => {
const actions = this.getActionsKeyDown();
if (!actions.hasOwnProperty(event.button)) return;
const [inputSuccess, vibrationLength] = actions[event.button]();
if (inputSuccess && this.scene.enableVibration && typeof navigator.vibrate !== 'undefined')
navigator.vibrate(vibrationLength);
}, this);
this.events.on('input_up', (event) => {
const actions = this.getActionsKeyUp();
if (!actions.hasOwnProperty(event.button)) return;
const [inputSuccess, vibrationLength] = actions[event.button]();
if (inputSuccess && this.scene.enableVibration && typeof navigator.vibrate !== 'undefined')
navigator.vibrate(vibrationLength);
}, this);
}
getActionsKeyDown() {
const actions = {};
actions[Button.UP] = () => this.buttonDirection(Button.UP);
actions[Button.DOWN] = () => this.buttonDirection(Button.DOWN);
actions[Button.LEFT] = () => this.buttonDirection(Button.LEFT);
actions[Button.RIGHT] = () => this.buttonDirection(Button.RIGHT);
actions[Button.SUBMIT] = () => this.buttonTouch();
actions[Button.ACTION] = () => this.buttonAb(Button.ACTION);
actions[Button.CANCEL] = () => this.buttonAb(Button.CANCEL);
actions[Button.MENU] = () => this.buttonMenu();
actions[Button.STATS] = () => this.buttonStats(true);
actions[Button.CYCLE_SHINY] = () => this.buttonCycleOption(Button.CYCLE_SHINY);
actions[Button.CYCLE_FORM] = () => this.buttonCycleOption(Button.CYCLE_FORM);
actions[Button.CYCLE_GENDER] = () => this.buttonCycleOption(Button.CYCLE_GENDER);
actions[Button.CYCLE_ABILITY] = () => this.buttonCycleOption(Button.CYCLE_ABILITY);
actions[Button.CYCLE_NATURE] = () => this.buttonCycleOption(Button.CYCLE_NATURE);
actions[Button.CYCLE_VARIANT] = () => this.buttonCycleOption(Button.CYCLE_VARIANT);
actions[Button.SPEED_UP] = () => this.buttonSpeedChange();
actions[Button.SLOW_DOWN] = () => this.buttonSpeedChange(false);
return actions;
}
getActionsKeyUp() {
const actions = {};
actions[Button.STATS] = () => this.buttonStats(false);
return actions;
}
buttonDirection(direction): Array<boolean | number> {
const inputSuccess = this.scene.ui.processInput(direction);
const vibrationLength = 5;
return [inputSuccess, vibrationLength];
}
buttonAb(button): Array<boolean | number> {
const inputSuccess = this.scene.ui.processInput(button);
return [inputSuccess, 0];
}
buttonTouch(): Array<boolean | number> {
const inputSuccess = this.scene.ui.processInput(Button.SUBMIT) || this.scene.ui.processInput(Button.ACTION);
return [inputSuccess, 0];
}
buttonStats(pressed = true): Array<boolean | number> {
if (pressed) {
for (let p of this.scene.getField().filter(p => p?.isActive(true)))
p.toggleStats(true);
} else {
for (let p of this.scene.getField().filter(p => p?.isActive(true)))
p.toggleStats(false);
}
return [true, 0];
}
buttonMenu(): Array<boolean | number> {
let inputSuccess;
if (this.scene.disableMenu)
return [true, 0];
switch (this.scene.ui?.getMode()) {
case Mode.MESSAGE:
if (!(this.scene.ui.getHandler() as MessageUiHandler).pendingPrompt)
return [true, 0];
case Mode.TITLE:
case Mode.COMMAND:
case Mode.FIGHT:
case Mode.BALL:
case Mode.TARGET_SELECT:
case Mode.SAVE_SLOT:
case Mode.PARTY:
case Mode.SUMMARY:
case Mode.STARTER_SELECT:
case Mode.CONFIRM:
case Mode.OPTION_SELECT:
this.scene.ui.setOverlayMode(Mode.MENU);
inputSuccess = true;
break;
case Mode.MENU:
case Mode.SETTINGS:
case Mode.ACHIEVEMENTS:
this.scene.ui.revertMode();
this.scene.playSound('select');
inputSuccess = true;
break;
default:
return [true, 0];
}
return [inputSuccess, 0];
}
buttonCycleOption(button): Array<boolean | number> {
let inputSuccess;
if (this.scene.ui?.getHandler() instanceof StarterSelectUiHandler) {
inputSuccess = this.scene.ui.processInput(button);
}
return [inputSuccess, 0];
}
buttonSpeedChange(up= true): Array<boolean | number> {
if (up) {
if (this.scene.gameSpeed < 5) {
this.scene.gameData.saveSetting(Setting.Game_Speed, settingOptions[Setting.Game_Speed].indexOf(`${this.scene.gameSpeed}x`) + 1);
if (this.scene.ui?.getMode() === Mode.SETTINGS)
(this.scene.ui.getHandler() as SettingsUiHandler).show([]);
}
return [0, 0];
}
if (this.scene.gameSpeed > 1) {
this.scene.gameData.saveSetting(Setting.Game_Speed, Math.max(settingOptions[Setting.Game_Speed].indexOf(`${this.scene.gameSpeed}x`) - 1, 0));
if (this.scene.ui?.getMode() === Mode.SETTINGS)
(this.scene.ui.getHandler() as SettingsUiHandler).show([]);
}
return [0, 0];
}
}

View File

@ -5,7 +5,7 @@ import UiHandler from "./ui-handler";
import { addWindow } from "./ui-theme";
import * as Utils from "../utils";
import { argbFromRgba } from "@material/material-color-utilities";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export interface OptionSelectConfig {
xOffset?: number;

View File

@ -4,7 +4,7 @@ import MessageUiHandler from "./message-ui-handler";
import { TextStyle, addTextObject } from "./text";
import { Mode } from "./ui";
import { addWindow } from "./ui-theme";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export default class AchvsUiHandler extends MessageUiHandler {
private achvsContainer: Phaser.GameObjects.Container;

View File

@ -1,7 +1,7 @@
import BattleScene from "../battle-scene";
import { Mode } from "./ui";
import UiHandler from "./ui-handler";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export default abstract class AwaitableUiHandler extends UiHandler {
protected awaitingActionInput: boolean;

View File

@ -6,7 +6,7 @@ import { Command } from "./command-ui-handler";
import { Mode } from "./ui";
import UiHandler from "./ui-handler";
import { addWindow } from "./ui-theme";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export default class BallUiHandler extends UiHandler {
private pokeballSelectContainer: Phaser.GameObjects.Container;

View File

@ -6,7 +6,7 @@ import MessageUiHandler from "./message-ui-handler";
import { getStatName, Stat } from "../data/pokemon-stat";
import { addWindow } from "./ui-theme";
import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export default class BattleMessageUiHandler extends MessageUiHandler {
private levelUpStatsContainer: Phaser.GameObjects.Container;

View File

@ -5,7 +5,7 @@ import PartyUiHandler, { PartyUiMode } from "./party-ui-handler";
import { Mode } from "./ui";
import UiHandler from "./ui-handler";
import i18next from '../plugins/i18n';
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export enum Command {
FIGHT = 0,

View File

@ -1,7 +1,7 @@
import BattleScene from "../battle-scene";
import AbstractOptionSelectUiHandler, { OptionSelectConfig } from "./abstact-option-select-ui-handler";
import { Mode } from "./ui";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler {
private switchCheck: boolean;

View File

@ -9,7 +9,7 @@ import { getPokemonSpecies } from "../data/pokemon-species";
import { addWindow } from "./ui-theme";
import { Tutorial, handleTutorial } from "../tutorial";
import { EggTier } from "../data/enums/egg-type";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
const defaultText = 'Select a machine.';

View File

@ -2,7 +2,7 @@ import BattleScene from "../battle-scene";
import { EggHatchPhase } from "../egg-hatch-phase";
import { Mode } from "./ui";
import UiHandler from "./ui-handler";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export default class EggHatchSceneHandler extends UiHandler {
public eggHatchContainer: Phaser.GameObjects.Container;

View File

@ -6,7 +6,7 @@ import MessageUiHandler from "./message-ui-handler";
import { EGG_SEED, Egg, GachaType, getEggGachaTypeDescriptor, getEggHatchWavesMessage, getEggDescriptor } from "../data/egg";
import * as Utils from "../utils";
import { addWindow } from "./ui-theme";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export default class EggListUiHandler extends MessageUiHandler {
private eggListContainer: Phaser.GameObjects.Container;

View File

@ -2,7 +2,7 @@ import BattleScene from "../battle-scene";
import MessageUiHandler from "./message-ui-handler";
import { TextStyle, addTextObject } from "./text";
import { Mode } from "./ui";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export default class EvolutionSceneHandler extends MessageUiHandler {
public evolutionContainer: Phaser.GameObjects.Container;

View File

@ -8,7 +8,7 @@ import * as Utils from "../utils";
import { CommandPhase } from "../phases";
import { MoveCategory } from "#app/data/move.js";
import i18next from '../plugins/i18n';
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export default class FightUiHandler extends UiHandler {
private movesContainer: Phaser.GameObjects.Container;

View File

@ -6,7 +6,7 @@ import { WindowVariant, addWindow } from "./ui-theme";
import InputText from "phaser3-rex-plugins/plugins/inputtext";
import * as Utils from "../utils";
import i18next from '../plugins/i18n';
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export interface FormModalConfig extends ModalConfig {
errorMessage?: string;

View File

@ -6,7 +6,7 @@ import { addWindow } from "./ui-theme";
import * as Utils from "../utils";
import { DexAttr, GameData } from "../system/game-data";
import { speciesStarters } from "../data/pokemon-species";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
interface DisplayStat {
label?: string;

View File

@ -9,7 +9,7 @@ import { OptionSelectConfig, OptionSelectItem } from "./abstact-option-select-ui
import { Tutorial, handleTutorial } from "../tutorial";
import { updateUserInfo } from "../account";
import i18next from '../plugins/i18n';
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export enum MenuOptions {
GAME_SETTINGS,

View File

@ -3,7 +3,7 @@ import { TextStyle, addTextObject } from "./text";
import { Mode } from "./ui";
import UiHandler from "./ui-handler";
import { WindowVariant, addWindow } from "./ui-theme";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export interface ModalConfig {
buttonActions: Function[];

View File

@ -6,7 +6,7 @@ import AwaitableUiHandler from "./awaitable-ui-handler";
import { Mode } from "./ui";
import { LockModifierTiersModifier, PokemonHeldItemModifier } from "../modifier/modifier";
import { handleTutorial, Tutorial } from "../tutorial";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export const SHOP_OPTIONS_ROW_LIMIT = 6;

View File

@ -16,7 +16,7 @@ import { pokemonEvolutions } from "../data/pokemon-evolutions";
import { addWindow } from "./ui-theme";
import { SpeciesFormChangeItemTrigger } from "../data/pokemon-forms";
import { getVariantTint } from "#app/data/variant";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
const defaultMessage = 'Choose a Pokémon.';

View File

@ -8,7 +8,7 @@ import * as Utils from "../utils";
import PokemonData from "../system/pokemon-data";
import { PokemonHeldItemModifier } from "../modifier/modifier";
import MessageUiHandler from "./message-ui-handler";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
const sessionSlotCount = 5;

View File

@ -5,7 +5,7 @@ import { TextStyle, addTextObject } from "./text";
import { Mode } from "./ui";
import UiHandler from "./ui-handler";
import { addWindow } from "./ui-theme";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export default class SettingsUiHandler extends UiHandler {
private settingsContainer: Phaser.GameObjects.Container;

View File

@ -27,7 +27,7 @@ import { argbFromRgba } from "@material/material-color-utilities";
import { OptionSelectItem } from "./abstact-option-select-ui-handler";
import { pokemonPrevolutions } from "#app/data/pokemon-evolutions";
import { Variant, getVariantTint } from "#app/data/variant";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export type StarterSelectCallback = (starters: Starter[]) => void;

View File

@ -17,7 +17,7 @@ import { Nature, getNatureStatMultiplier } from "../data/nature";
import { loggedInUser } from "../account";
import { PlayerGender } from "../system/game-data";
import { Variant, getVariantTint } from "#app/data/variant";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
enum Page {
PROFILE,

View File

@ -5,7 +5,7 @@ import { Mode } from "./ui";
import UiHandler from "./ui-handler";
import * as Utils from "../utils";
import { getMoveTargets } from "../data/move";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export type TargetSelectCallback = (cursor: integer) => void;

View File

@ -1,7 +1,7 @@
import BattleScene from "../battle-scene";
import { TextStyle, getTextColor } from "./text";
import UI, { Mode } from "./ui";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export default abstract class UiHandler {
protected scene: BattleScene;

View File

@ -35,7 +35,7 @@ import SavingIconHandler from './saving-icon-handler';
import UnavailableModalUiHandler from './unavailable-modal-ui-handler';
import OutdatedModalUiHandler from './outdated-modal-ui-handler';
import SessionReloadModalUiHandler from './session-reload-modal-ui-handler';
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
export enum Mode {
MESSAGE,

View File

@ -4,7 +4,7 @@ import MessageUiHandler from "./message-ui-handler";
import { TextStyle, addTextObject } from "./text";
import { Mode } from "./ui";
import { addWindow } from "./ui-theme";
import {Button} from "#app/inputsController";
import {Button} from "#app/inputs-controller";
const itemRows = 4;
const itemCols = 17;