From 860c1a5c11a837df96c473d8bf00edc104b4340e Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Fri, 7 Apr 2023 00:17:55 -0400 Subject: [PATCH] Improve summary UI --- src/battle-phase.ts | 13 ++-- src/battle-scene.ts | 3 - src/ui/party-ui-handler.ts | 3 +- src/ui/summary-ui-handler.ts | 128 +++++++++++++++++++++++++++++++---- src/ui/ui.ts | 30 +++++--- 5 files changed, 146 insertions(+), 31 deletions(-) diff --git a/src/battle-phase.ts b/src/battle-phase.ts index 5b50f4639f6..3d554b9e006 100644 --- a/src/battle-phase.ts +++ b/src/battle-phase.ts @@ -391,8 +391,7 @@ export class CommandPhase extends BattlePhase { } end() { - super.end(); - this.scene.ui.setMode(Mode.MESSAGE); + this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end()); } } @@ -695,8 +694,7 @@ export class SwitchPhase extends BattlePhase { this.scene.ui.setMode(Mode.PARTY, this.isModal ? PartyUiMode.SWITCH : PartyUiMode.FAINT_SWITCH, (slotIndex: integer) => { if (slotIndex && slotIndex < 6) this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, slotIndex, this.doReturn)); - this.scene.ui.setMode(Mode.MESSAGE); - super.end(); + this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end()); }, PartyUiHandler.FilterNonFainted); } } @@ -780,6 +778,13 @@ export class LearnMovePhase extends PartyMemberPokemonPhase { const pokemon = this.getPokemon(); const move = allMoves[this.moveId - 1]; + const existingMoveIndex = pokemon.moveset.findIndex(m => m.moveId === move.id); + + if (existingMoveIndex > -1) { + this.end(); + return; + } + const emptyMoveIndex = pokemon.moveset.length < 4 ? pokemon.moveset.length : pokemon.moveset.findIndex(m => m === null); diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 28eca67d163..e418824cbdf 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -334,9 +334,6 @@ export default class BattleScene extends Phaser.Scene { } else { this.pushPhase(new EncounterPhase(this)); this.pushPhase(new SummonPhase(this)); - this.pushPhase(new LearnMovePhase(this, 0, Moves.AERIAL_ACE)); - this.pushPhase(new LearnMovePhase(this, 0, Moves.AERIAL_ACE)); - this.pushPhase(new LearnMovePhase(this, 0, Moves.AERIAL_ACE)); } this.currentBattle = new Battle((this.currentBattle?.waveIndex || 0) + 1); diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index 01104d31722..512552e52f3 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -170,9 +170,8 @@ export default class PartyUiHandler extends MessageUiHandler { }, null, true); } } else if (option === PartyOption.SUMMARY) { - this.clearOptions(); ui.playSelect(); - ui.setModeWithoutClear(Mode.SUMMARY, this.scene.getParty()[this.cursor]); + ui.setModeWithoutClear(Mode.SUMMARY, this.scene.getParty()[this.cursor]).then(() => this.clearOptions()); } else if (option === PartyOption.CANCEL) this.processInput(keyCodes.X); } else if (keyCode === keyCodes.X) { diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index 22f40bc780c..5b0dc1c95bb 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -23,11 +23,15 @@ export default class SummaryUiHandler extends UiHandler { private summaryContainer: Phaser.GameObjects.Container; private summaryPageContainer: Phaser.GameObjects.Container; private movesContainer: Phaser.GameObjects.Container; + private moveDescriptionText: Phaser.GameObjects.Text; private moveCursorObj: Phaser.GameObjects.Sprite; private selectedMoveCursorObj: Phaser.GameObjects.Sprite; + private moveRowsContainer: Phaser.GameObjects.Container; private extraMoveRowContainer: Phaser.GameObjects.Container; private summaryPageTransitionContainer: Phaser.GameObjects.Container; + private moveCursorBlinkTimer: Phaser.Time.TimerEvent; + private pokemon: PlayerPokemon; private newMove: Move; private moveSelectFunction: Function; @@ -111,11 +115,37 @@ export default class SummaryUiHandler extends UiHandler { if (this.moveCursor < this.pokemon.moveset.length) { if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) this.moveSelectFunction(this.moveCursor); - else - this.selectedMoveIndex = this.moveCursor; + else { + if (this.selectedMoveIndex === -1) + this.selectedMoveIndex = this.moveCursor; + else { + if (this.selectedMoveIndex !== this.moveCursor) { + const tempMove = this.pokemon.moveset[this.selectedMoveIndex]; + this.pokemon.moveset[this.selectedMoveIndex] = this.pokemon.moveset[this.moveCursor]; + this.pokemon.moveset[this.moveCursor] = tempMove; + + const selectedMoveRow = this.moveRowsContainer.getAt(this.selectedMoveIndex) as Phaser.GameObjects.Container; + const switchMoveRow = this.moveRowsContainer.getAt(this.moveCursor) as Phaser.GameObjects.Container; + + this.moveRowsContainer.moveTo(selectedMoveRow, this.moveCursor); + this.moveRowsContainer.moveTo(switchMoveRow, this.selectedMoveIndex); + + selectedMoveRow.setY(this.moveCursor * 16); + switchMoveRow.setY(this.selectedMoveIndex * 16); + } + + this.selectedMoveIndex = -1; + if (this.selectedMoveCursorObj) { + this.selectedMoveCursorObj.destroy(); + this.selectedMoveCursorObj = null; + } + } + } success = true; } else if (this.moveCursor === 4) this.processInput(keyCodes.X); + else + ui.playError(); } else if (keyCode === keyCodes.X) { this.hideMoveSelect(); success = true; @@ -165,13 +195,41 @@ export default class SummaryUiHandler extends UiHandler { if (changed) { this.moveCursor = cursor; - if (!this.moveCursorObj) { - this.moveCursorObj = this.scene.add.sprite(-2, 0, 'summary_moves_cursor', 'highlight'); - this.moveCursorObj.setOrigin(0, 1); - this.movesContainer.add(this.moveCursorObj); + const selectedMove = this.getSelectedMove(); + + this.moveDescriptionText.setText(selectedMove?.effect || ''); + } + + if (!this.moveCursorObj) { + this.moveCursorObj = this.scene.add.sprite(-2, 0, 'summary_moves_cursor', 'highlight'); + this.moveCursorObj.setOrigin(0, 1); + this.movesContainer.add(this.moveCursorObj); + } + + this.moveCursorObj.setY(16 * this.moveCursor + 1); + + if (this.moveCursorBlinkTimer) + this.moveCursorBlinkTimer.destroy(); + this.moveCursorBlinkTimer = this.scene.time.addEvent({ + loop: true, + delay: 600, + callback: () => { + this.moveCursorObj.setVisible(false); + this.scene.time.delayedCall(100, () => { + this.moveCursorObj.setVisible(true); + }); } - - this.moveCursorObj.setY(16 * this.moveCursor + 1); + }); + + if (this.selectedMoveIndex > -1) { + if (!this.selectedMoveCursorObj) { + this.selectedMoveCursorObj = this.scene.add.sprite(-2, 0, 'summary_moves_cursor', 'select'); + this.selectedMoveCursorObj.setOrigin(0, 1); + this.movesContainer.add(this.selectedMoveCursorObj); + this.movesContainer.moveBelow(this.selectedMoveCursorObj, this.moveCursorObj); + } + + this.selectedMoveCursorObj.setY(16 * this.selectedMoveIndex + 1); } } else { changed = this.cursor !== cursor; @@ -228,6 +286,7 @@ export default class SummaryUiHandler extends UiHandler { pageContainer.add(this.movesContainer); this.extraMoveRowContainer = this.scene.add.container(0, 64); + this.extraMoveRowContainer.setVisible(false); this.movesContainer.add(this.extraMoveRowContainer); const extraRowOverlay = this.scene.add.image(-2, 1, 'summary_moves_overlay_row'); @@ -239,25 +298,57 @@ export default class SummaryUiHandler extends UiHandler { extraRowText.setOrigin(0, 1); this.extraMoveRowContainer.add(extraRowText); + this.moveRowsContainer = this.scene.add.container(0, 0); + this.movesContainer.add(this.moveRowsContainer); + for (let m = 0; m < 4; m++) { const move = m < this.pokemon.moveset.length ? this.pokemon.moveset[m] : null; + const moveRowContainer = this.scene.add.container(0, 16 * m); + this.moveRowsContainer.add(moveRowContainer); if (move) { - const typeIcon = this.scene.add.sprite(0, 16 * m, 'types', Type[move.getMove().type].toLowerCase()); + const typeIcon = this.scene.add.sprite(0, 0, 'types', Type[move.getMove().type].toLowerCase()); typeIcon.setOrigin(0, 1); - this.movesContainer.add(typeIcon); + moveRowContainer.add(typeIcon); } - const moveText = addTextObject(this.scene, 35, 16 * m, move ? move.getName() : '-', TextStyle.SUMMARY); + const moveText = addTextObject(this.scene, 35, 0, move ? move.getName() : '-', TextStyle.SUMMARY); moveText.setOrigin(0, 1); - this.movesContainer.add(moveText); + moveRowContainer.add(moveText); } + + this.moveDescriptionText = addTextObject(this.scene, 2, 84, '', TextStyle.WINDOW, { wordWrap: { width: 900 } }); + this.movesContainer.add(this.moveDescriptionText); + + const maskRect = this.scene.make.graphics({}); + maskRect.fillStyle(0xFFFFFF); + maskRect.beginPath(); + maskRect.fillRect(2, 83, 149, 46); + + const moveDescriptionTextMask = maskRect.createGeometryMask(); + + this.moveDescriptionText.setMask(moveDescriptionTextMask); + + console.log(this.moveDescriptionText.displayHeight); break; } } + getSelectedMove(): Move { + if (this.cursor !== Page.MOVES) + return null; + + if (this.moveCursor < 4 && this.moveCursor < this.pokemon.moveset.length) + return this.pokemon.moveset[this.moveCursor].getMove(); + else if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE && this.moveCursor === 4) + return this.newMove; + return null; + } + showMoveSelect() { this.moveSelect = true; + this.extraMoveRowContainer.setVisible(true); + this.selectedMoveIndex = -1; this.setCursor(0); } @@ -268,6 +359,19 @@ export default class SummaryUiHandler extends UiHandler { } this.moveSelect = false; + this.extraMoveRowContainer.setVisible(false); + if (this.moveCursorBlinkTimer) { + this.moveCursorBlinkTimer.destroy(); + this.moveCursorBlinkTimer = null; + } + if (this.moveCursorObj) { + this.moveCursorObj.destroy(); + this.moveCursorObj = null; + } + if (this.selectedMoveCursorObj) { + this.selectedMoveCursorObj.destroy(); + this.selectedMoveCursorObj = null; + } } clear() { diff --git a/src/ui/ui.ts b/src/ui/ui.ts index 3cbfa12597b..a7776cdc14a 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -30,6 +30,8 @@ export default class UI extends Phaser.GameObjects.Container { private mode: Mode; private handlers: UiHandler[]; private overlay: Phaser.GameObjects.Rectangle; + + private transitioning: boolean; constructor(scene: BattleScene) { super(scene, 0, scene.game.canvas.height / 6); @@ -47,7 +49,7 @@ export default class UI extends Phaser.GameObjects.Container { ]; } - setup() { + setup(): void { for (let handler of this.handlers) { handler.setup(); } @@ -57,19 +59,22 @@ export default class UI extends Phaser.GameObjects.Container { this.overlay.setVisible(false); } - getHandler() { + getHandler(): UiHandler { return this.handlers[this.mode]; } - getMessageHandler() { + getMessageHandler(): BattleMessageUiHandler { return this.handlers[Mode.MESSAGE] as BattleMessageUiHandler; } - processInput(keyCode: integer) { + processInput(keyCode: integer): void { + if (this.transitioning) + return; + this.getHandler().processInput(keyCode); } - showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean) { + showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean): void { const handler = this.getHandler(); if (handler instanceof MessageUiHandler) (handler as MessageUiHandler).showText(text, delay, callback, callbackDelay, prompt); @@ -77,7 +82,7 @@ export default class UI extends Phaser.GameObjects.Container { this.getMessageHandler().showText(text, delay, callback, callbackDelay, prompt); } - clearText() { + clearText(): void { const handler = this.getHandler(); if (handler instanceof MessageUiHandler) (handler as MessageUiHandler).clearText(); @@ -93,11 +98,11 @@ export default class UI extends Phaser.GameObjects.Container { return changed; } - playSelect() { + playSelect(): void { this.scene.sound.play('select'); } - playError() { + playError(): void { this.scene.sound.play('error'); } @@ -108,27 +113,32 @@ export default class UI extends Phaser.GameObjects.Container { return; } const doSetMode = () => { - this.getHandler().clear(); + if (clear) + this.getHandler().clear(); this.mode = mode; this.getHandler().show(args); resolve(); }; if (transitionModes.indexOf(this.mode) > -1 || transitionModes.indexOf(mode) > -1) { + this.transitioning = true; this.overlay.setAlpha(0); this.overlay.setVisible(true); this.scene.tweens.add({ targets: this.overlay, alpha: 1, duration: 250, + ease: 'Sine.easeOut', onComplete: () => { - this.scene.time.delayedCall(250, () => { + this.scene.time.delayedCall(100, () => { doSetMode(); this.scene.tweens.add({ targets: this.overlay, alpha: 0, duration: 250, + ease: 'Sine.easeIn', onComplete: () => this.overlay.setVisible(false) }); + this.transitioning = false; }); } });