diff --git a/src/ui-inputs.ts b/src/ui-inputs.ts index 38d8e7830c4..d1e4b99e6e3 100644 --- a/src/ui-inputs.ts +++ b/src/ui-inputs.ts @@ -89,13 +89,10 @@ export class UiInputs { } buttonStats(pressed: boolean = true): void { - 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); - } + for (let p of this.scene.getField().filter(p => p?.isActive(true))) + p.toggleStats(pressed); + + this.scene.ui.processStats(pressed); } buttonMenu(): void { diff --git a/src/ui/battle-flyout.ts b/src/ui/battle-flyout.ts index ca3ef9aba67..fcc4c4aad26 100644 --- a/src/ui/battle-flyout.ts +++ b/src/ui/battle-flyout.ts @@ -21,6 +21,9 @@ export default class BattleFlyout extends Phaser.GameObjects.Container { private flyoutPlaceholder: Phaser.GameObjects.Rectangle; private flyoutTextPlaceholder: Phaser.GameObjects.Text; + private largeFlyoutParent : Phaser.GameObjects.Container; + private largeFlyoutContainer: Phaser.GameObjects.Container; + constructor(scene: Phaser.Scene, player: boolean) { super(scene, 0, 0); this.player = player; @@ -55,11 +58,15 @@ export default class BattleFlyout extends Phaser.GameObjects.Container { this.flyoutTextPlaceholder.setOrigin(0, 0); this.flyoutContainer.add(this.flyoutTextPlaceholder); + + this.largeFlyoutParent = this.scene.add.container() } initInfo(pokemon: Pokemon) { this.name = `Flyout ${pokemon.name}`; this.flyoutParent.name = `Flyout Parent ${pokemon.name}`; + + this.flyoutTextPlaceholder.text = `${pokemon.name}` } setMini(mini: boolean): void { diff --git a/src/ui/battle-info.ts b/src/ui/battle-info.ts index 4209003a540..53a5c3b244a 100644 --- a/src/ui/battle-info.ts +++ b/src/ui/battle-info.ts @@ -200,10 +200,12 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.statValuesContainer.add(statNumber); }); - this.flyoutMenu = new BattleFlyout(this.scene, this.player); - this.add(this.flyoutMenu); + if (!this.player) { + this.flyoutMenu = new BattleFlyout(this.scene, this.player); + this.add(this.flyoutMenu); - this.moveBelow(this.flyoutMenu, this.box); + this.moveBelow(this.flyoutMenu, this.box); + } this.type1Icon = this.scene.add.sprite(player ? -139 : -15, player ? -17 : -15.5, `pbinfo_${player ? 'player' : 'enemy'}_type1`); this.type1Icon.setOrigin(0, 0); @@ -225,7 +227,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.name = pokemon.name; this.box.name = pokemon.name; - this.flyoutMenu.initInfo(pokemon); + this.flyoutMenu?.initInfo(pokemon); this.genderText.setText(getGenderSymbol(pokemon.gender)); this.genderText.setColor(getGenderColor(pokemon.gender)); @@ -343,7 +345,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.mini = mini; - this.flyoutMenu.setMini(this.mini); + this.flyoutMenu?.setMini(this.mini); this.box.setTexture(this.getTextureName()); this.statsBox.setTexture(`${this.getTextureName()}_stats`); @@ -374,7 +376,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { alpha: visible ? 1 : 0 }); - this.flyoutMenu.toggleFlyout(visible); + this.flyoutMenu?.toggleFlyout(visible); } updateBossSegments(pokemon: EnemyPokemon): void { diff --git a/src/ui/fight-flyout.ts b/src/ui/fight-flyout.ts new file mode 100644 index 00000000000..c2d4358da7b --- /dev/null +++ b/src/ui/fight-flyout.ts @@ -0,0 +1,116 @@ +import { addTextObject, TextStyle } from "./text"; +import * as Utils from '../utils'; +import BattleScene from "#app/battle-scene.js"; +import { ArenaTagSide } from "#app/data/arena-tag.js"; +import { WeatherType } from "#app/data/weather.js"; +import { TerrainType } from "#app/data/terrain.js"; +import { addWindow } from "./ui-theme"; + +export default class FightFlyout extends Phaser.GameObjects.Container { + private flyoutWidth = 160; + private flyoutHeight = 55; + + private translationX: number; + private anchorX: number; + private anchorY: number; + + private flyoutParent: Phaser.GameObjects.Container; + private flyoutContainer: Phaser.GameObjects.Container; + + private flyoutWindow: Phaser.GameObjects.NineSlice; + + private flyoutTextPlayer: Phaser.GameObjects.Text; + private flyoutTextEnemy: Phaser.GameObjects.Text; + private flyoutTextAll: Phaser.GameObjects.Text; + + constructor(scene: Phaser.Scene) { + super(scene, 0, 0); + + this.translationX = this.flyoutWidth; + this.anchorX = 0; + this.anchorY = -102; + + this.flyoutParent = this.scene.add.container(this.anchorX - this.translationX, this.anchorY); + this.flyoutParent.setAlpha(0); + this.add(this.flyoutParent); + + this.flyoutContainer = this.scene.add.container(0, 0); + this.flyoutParent.add(this.flyoutContainer); + + this.flyoutWindow = addWindow(this.scene as BattleScene, 0, 0, this.flyoutWidth, this.flyoutHeight); + this.flyoutContainer.add(this.flyoutWindow); + + this.flyoutTextPlayer = addTextObject(this.scene, 8, 7, `Player Effects:`, TextStyle.BATTLE_INFO); + this.flyoutTextPlayer.setFontSize(48); + this.flyoutTextPlayer.setAlign('left'); + this.flyoutTextPlayer.setOrigin(0, 0); + + this.flyoutContainer.add(this.flyoutTextPlayer); + + this.flyoutTextEnemy = addTextObject(this.scene, this.flyoutWidth - 8, 7, `Enemy Effects:`, TextStyle.BATTLE_INFO); + this.flyoutTextEnemy.setFontSize(48); + this.flyoutTextEnemy.setAlign('right'); + this.flyoutTextEnemy.setOrigin(1, 0); + + this.flyoutContainer.add(this.flyoutTextEnemy); + + this.flyoutTextAll = addTextObject(this.scene, this.flyoutWidth / 2, 7, `All Effects:`, TextStyle.BATTLE_INFO); + this.flyoutTextAll.setFontSize(48); + this.flyoutTextAll.setAlign('center'); + this.flyoutTextAll.setOrigin(0.5, 0); + + this.flyoutContainer.add(this.flyoutTextAll); + + this.name = `Fight Flyout`; + this.flyoutParent.name = `Fight Flyout Parent`; + } + + private formatText(unformattedText: string): string { + const text = unformattedText.split('_'); + for (let i = 0; i < text.length; i++) + text[i] = text[i].charAt(0).toUpperCase() + text[i].substring(1).toLowerCase(); + + return text.join(' '); + } + + private setText(battleScene: BattleScene, textObject: Phaser.GameObjects.Text, tagSide: ArenaTagSide): void { + let tags = ''; + battleScene.arena.findTagsOnSide(() => true, tagSide).sort((a, b) => a.turnCount - b.turnCount).forEach( + tag => { + tags += this.formatText(tag.tagType); + if (tag.turnCount > 0 && tag.turnCount < 15) // Don't add tags with infinite duration + tags += ' - ' + tag.turnCount + tags += '\n'}); + + textObject.text += tags; + } + + toggleFlyout(visible: boolean): void { + this.scene.tweens.add({ + targets: this.flyoutParent, + x: visible ? this.anchorX : this.anchorX - this.translationX, + duration: Utils.fixedInt(125), + ease: 'Sine.easeInOut', + alpha: visible ? 1 : 0, + }); + + const battleScene = this.scene as BattleScene; + if (!battleScene) + return; + + this.flyoutTextPlayer.text = `Player Effects\n`; + this.flyoutTextEnemy.text = `Enemy Effects\n`; + + this.setText(battleScene, this.flyoutTextPlayer, ArenaTagSide.PLAYER); + this.setText(battleScene, this.flyoutTextEnemy, ArenaTagSide.ENEMY); + + this.flyoutTextAll.text = `Field Effects\n`; + + if (battleScene.arena.weather) + this.flyoutTextAll.text += + this.formatText(WeatherType[battleScene.arena.weather.weatherType]) + ' - ' + battleScene.arena.weather.turnsLeft + '\n'; + if (battleScene.arena.terrain) + this.flyoutTextAll.text += + this.formatText(TerrainType[battleScene.arena.terrain.terrainType]) + ' - ' + battleScene.arena.terrain.turnsLeft + '\n'; + } +} \ No newline at end of file diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index 084337b4086..880a695bb65 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -9,6 +9,7 @@ import { CommandPhase } from "../phases"; import { MoveCategory } from "#app/data/move.js"; import i18next from '../plugins/i18n'; import {Button} from "../enums/buttons"; +import FightFlyout from "./fight-flyout"; export default class FightUiHandler extends UiHandler { private movesContainer: Phaser.GameObjects.Container; @@ -22,6 +23,8 @@ export default class FightUiHandler extends UiHandler { private cursorObj: Phaser.GameObjects.Image; private moveCategoryIcon: Phaser.GameObjects.Sprite; + private commandFlyout: FightFlyout; + protected fieldIndex: integer = 0; protected cursor2: integer = 0; @@ -75,6 +78,9 @@ export default class FightUiHandler extends UiHandler { this.accuracyText.setOrigin(1, 0.5); this.accuracyText.setVisible(false); ui.add(this.accuracyText); + + this.commandFlyout = new FightFlyout(this.scene); + ui.add(this.commandFlyout); } show(args: any[]): boolean { @@ -135,6 +141,10 @@ export default class FightUiHandler extends UiHandler { return success; } + processStats(pressed: boolean): void { + this.commandFlyout.toggleFlyout(pressed); + } + getCursor(): integer { return !this.fieldIndex ? this.cursor : this.cursor2; } diff --git a/src/ui/ui-handler.ts b/src/ui/ui-handler.ts index 7fdb85d94c0..9d3297cd44a 100644 --- a/src/ui/ui-handler.ts +++ b/src/ui/ui-handler.ts @@ -23,6 +23,10 @@ export default abstract class UiHandler { } abstract processInput(button: Button): boolean; + + processStats(pressed: boolean): void { + return; + }; getUi() { return this.scene.ui; diff --git a/src/ui/ui.ts b/src/ui/ui.ts index 09deb2bdd7a..cb0256e407b 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -211,6 +211,18 @@ export default class UI extends Phaser.GameObjects.Container { return handler.processInput(button); } + processStats(pressed: boolean) { + if (this.overlayActive) + return false; + + if([Mode.CONFIRM, Mode.COMMAND, Mode.FIGHT, Mode.MESSAGE].includes(this.mode)) { + this.handlers[Mode.FIGHT]?.processStats(pressed); + return true; + } + + return false; + } + showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer): void { if (prompt && text.indexOf('$') > -1) { const messagePages = text.split(/\$/g).map(m => m.trim());