diff --git a/public/images/ui/summary_moves_cursor.json b/public/images/ui/summary_moves_cursor.json new file mode 100644 index 000000000..dc391a564 --- /dev/null +++ b/public/images/ui/summary_moves_cursor.json @@ -0,0 +1,62 @@ +{ + "textures": [ + { + "image": "summary_moves_cursor.png", + "format": "RGBA8888", + "size": { + "w": 156, + "h": 32 + }, + "scale": 1, + "frames": [ + { + "filename": "highlight", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 146, + "h": 16 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 156, + "h": 16 + }, + "frame": { + "x": 0, + "y": 0, + "w": 156, + "h": 16 + } + }, + { + "filename": "select", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 156, + "h": 16 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 156, + "h": 16 + }, + "frame": { + "x": 0, + "y": 16, + "w": 156, + "h": 16 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:d89e84be7d49aa7957445f38e744aabe:651a727fe05cc993624865e5b14fb859:3f559bc98797893ed427d02379120df2$" + } +} diff --git a/public/images/ui/summary_moves_cursor.png b/public/images/ui/summary_moves_cursor.png new file mode 100644 index 000000000..ca06318e2 Binary files /dev/null and b/public/images/ui/summary_moves_cursor.png differ diff --git a/public/images/ui/summary_moves_effect.png b/public/images/ui/summary_moves_effect.png index 1c90a3450..ca3a9ed9c 100644 Binary files a/public/images/ui/summary_moves_effect.png and b/public/images/ui/summary_moves_effect.png differ diff --git a/public/images/ui/summary_moves_overlay_row.png b/public/images/ui/summary_moves_overlay_row.png new file mode 100644 index 000000000..d89df5252 Binary files /dev/null and b/public/images/ui/summary_moves_overlay_row.png differ diff --git a/src/auto-play.ts b/src/auto-play.ts index 44d23ba30..92f8da427 100644 --- a/src/auto-play.ts +++ b/src/auto-play.ts @@ -10,7 +10,7 @@ import FightUiHandler from "./ui/fight-ui-handler"; import MessageUiHandler from "./ui/message-ui-handler"; import ModifierSelectUiHandler from "./ui/modifier-select-ui-handler"; import PartyUiHandler from "./ui/party-ui-handler"; -import SwitchCheckUiHandler from "./ui/switch-check-ui-handler"; +import ConfirmUiHandler from "./ui/confirm-ui-handler"; import { Mode } from "./ui/ui"; export function initAutoPlay(speed: number) { @@ -56,7 +56,7 @@ export function initAutoPlay(speed: number) { const commandUiHandler = this.ui.handlers[Mode.COMMAND] as CommandUiHandler; const fightUiHandler = this.ui.handlers[Mode.FIGHT] as FightUiHandler; const partyUiHandler = this.ui.handlers[Mode.PARTY] as PartyUiHandler; - const switchCheckUiHandler = this.ui.handlers[Mode.SWITCH_CHECK] as SwitchCheckUiHandler; + const switchCheckUiHandler = this.ui.handlers[Mode.CONFIRM] as ConfirmUiHandler; const modifierSelectUiHandler = this.ui.handlers[Mode.MODIFIER_SELECT] as ModifierSelectUiHandler; const getBestPartyMemberIndex = () => { diff --git a/src/battle-phase.ts b/src/battle-phase.ts index 21c4b5413..5b50f4639 100644 --- a/src/battle-phase.ts +++ b/src/battle-phase.ts @@ -11,6 +11,7 @@ import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, import { pokemonLevelMoves } from "./pokemon-level-moves"; import { MoveAnim, initAnim, loadMoveAnimAssets } from "./battle-anims"; import { StatusEffect } from "./status-effect"; +import { SummaryUiMode } from "./ui/summary-ui-handler"; export class BattlePhase { protected scene: BattleScene; @@ -325,7 +326,10 @@ export class CheckSwitchPhase extends BattlePhase { super.start(); this.scene.ui.showText('Will you switch\nPOKéMON?', null, () => { - this.scene.ui.setMode(Mode.SWITCH_CHECK, () => this.end()); + this.scene.ui.setMode(Mode.CONFIRM, () => { + this.scene.unshiftPhase(new SwitchPhase(this.scene, false, true)); + this.end(); + }, () => this.end()); }); } } @@ -338,11 +342,12 @@ export class CommandPhase extends BattlePhase { start() { super.start(); - this.scene.ui.setMode(Mode.COMMAND); - this.scene.currentBattle.addParticipant(this.scene.getPlayerPokemon()); + this.scene.ui.setMode(Mode.COMMAND).then(() => { + this.scene.currentBattle.addParticipant(this.scene.getPlayerPokemon()); - this.scene.getPlayerPokemon().resetTurnData(); - this.scene.getEnemyPokemon().resetTurnData(); + this.scene.getPlayerPokemon().resetTurnData(); + this.scene.getEnemyPokemon().resetTurnData(); + }); } handleCommand(command: Command, cursor: integer): boolean{ @@ -775,8 +780,12 @@ export class LearnMovePhase extends PartyMemberPokemonPhase { const pokemon = this.getPokemon(); const move = allMoves[this.moveId - 1]; - if (pokemon.moveset.length < 4) { - pokemon.moveset.push(new PokemonMove(this.moveId, 0, 0)); + const emptyMoveIndex = pokemon.moveset.length < 4 + ? pokemon.moveset.length + : pokemon.moveset.findIndex(m => m === null); + + if (emptyMoveIndex > -1) { + pokemon.moveset[emptyMoveIndex] = new PokemonMove(this.moveId, 0, 0); initAnim(this.moveId).then(() => { loadMoveAnimAssets(this.scene, [ this.moveId ], true) .then(() => { @@ -784,8 +793,50 @@ export class LearnMovePhase extends PartyMemberPokemonPhase { this.scene.ui.showText(`${pokemon.name} learned\n${Utils.toPokemonUpperCase(move.name)}!`, null, () => this.end(), null, true); }); }); - } else - this.end(); + } else { + this.scene.ui.setMode(Mode.MESSAGE); + this.scene.ui.showText(`${pokemon.name} wants to learn the\nmove ${move.name}.`, null, () => { + this.scene.ui.showText(`However, ${pokemon.name} already\nknows four moves.`, null, () => { + this.scene.ui.showText(`Should a move be deleted and\nreplaced with ${move.name}?`, null, () => { + const noHandler = () => { + this.scene.ui.setMode(Mode.MESSAGE).then(() => { + this.scene.ui.showText(`Stop trying to teach\n${move.name}?`, null, () => { + this.scene.ui.setMode(Mode.CONFIRM, () => { + this.scene.ui.setMode(Mode.MESSAGE); + this.scene.ui.showText(`${pokemon.name} did not learn the\nmove ${move.name}.`, null, () => this.end(), null, true); + }, () => { + this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId)); + this.end(); + }); + }); + }); + }; + this.scene.ui.setMode(Mode.CONFIRM, () => { + this.scene.ui.setMode(Mode.MESSAGE); + this.scene.ui.showText('Which move should be forgotten?', null, () => { + this.scene.ui.setMode(Mode.SUMMARY, this.getPokemon(), SummaryUiMode.LEARN_MOVE, move, (moveIndex: integer) => { + if (moveIndex === 4) { + noHandler(); + return; + } + this.scene.ui.setMode(Mode.MESSAGE).then(() => { + this.scene.ui.showText('1, 2, and… … … Poof!', null, () => { + this.scene.ui.showText(`${pokemon.name} forgot how to\nuse ${pokemon.moveset[moveIndex].getName()}.`, null, () => { + this.scene.ui.showText('And…', null, () => { + pokemon.moveset[moveIndex] = null; + this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId)); + this.end(); + }, null, true); + }, null, true); + }, null, true); + }); + }); + }, null, true); + }, noHandler); + }); + }, null, true); + }, null, true); + } } } diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 4ce4bc6b3..28eca67d1 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1,7 +1,7 @@ import Phaser from 'phaser'; import { Biome, BiomeArena } from './biome'; import UI from './ui/ui'; -import { BattlePhase, EncounterPhase, SummonPhase, CommandPhase, NextEncounterPhase, SwitchBiomePhase, NewBiomeEncounterPhase } from './battle-phase'; +import { BattlePhase, EncounterPhase, SummonPhase, CommandPhase, NextEncounterPhase, SwitchBiomePhase, NewBiomeEncounterPhase, LearnMovePhase } from './battle-phase'; import { PlayerPokemon, EnemyPokemon } from './pokemon'; import PokemonSpecies, { allSpecies, getPokemonSpecies } from './pokemon-species'; import * as Utils from './utils'; @@ -11,6 +11,7 @@ import { Species } from './species'; import { initAutoPlay } from './auto-play'; import { Battle } from './battle'; import { populateAnims } from './battle-anims'; +import { Moves } from './move'; export default class BattleScene extends Phaser.Scene { private auto: boolean; @@ -138,6 +139,8 @@ export default class BattleScene extends Phaser.Scene { this.loadImage('summary_profile', 'ui'); this.loadImage('summary_moves', 'ui'); this.loadImage('summary_moves_effect', 'ui'); + this.loadImage('summary_moves_overlay_row', 'ui'); + this.loadAtlas('summary_moves_cursor', 'ui'); // Load arena images Utils.getEnumValues(Biome).map(at => { @@ -331,6 +334,9 @@ 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/move.ts b/src/move.ts index c012119d6..68cab4451 100644 --- a/src/move.ts +++ b/src/move.ts @@ -28,7 +28,7 @@ export default class Move { constructor(id: Moves, name: string, type: Type, category: MoveCategory, power: integer, accuracy: integer, pp: integer, tm: string, effect: string, chance: integer, generation: integer, ...attrs: MoveAttr[]) { this.id = id; - this.name = name; + this.name = name.toUpperCase(); this.type = type; this.category = category; this.power = power; diff --git a/src/pokemon.ts b/src/pokemon.ts index 58b171294..f0afa5d56 100644 --- a/src/pokemon.ts +++ b/src/pokemon.ts @@ -716,6 +716,6 @@ export class PokemonMove { } getName(): string { - return this.getMove().name.toUpperCase(); + return this.getMove().name; } } \ No newline at end of file diff --git a/src/text.ts b/src/text.ts index b6f422f5d..53b3f6892 100644 --- a/src/text.ts +++ b/src/text.ts @@ -2,7 +2,9 @@ export enum TextStyle { MESSAGE, WINDOW, BATTLE_INFO, - PARTY + PARTY, + SUMMARY, + SUMMARY_RED }; export function addTextObject(scene: Phaser.Scene, x: number, y: number, content: string, style: TextStyle, extraStyleOptions?: Phaser.Types.GameObjects.Text.TextStyle) { @@ -53,6 +55,22 @@ export function addTextObject(scene: Phaser.Scene, x: number, y: number, content }; shadowColor = '#707070'; break; + case TextStyle.SUMMARY: + styleOptions = { + fontFamily: 'emerald', + fontSize: '96px', + color: '#ffffff' + }; + shadowColor = '#636363'; + break; + case TextStyle.SUMMARY_RED: + styleOptions = { + fontFamily: 'emerald', + fontSize: '96px', + color: '#f4b4b0' + }; + shadowColor = '#d06c6a'; + break; } if (extraStyleOptions) diff --git a/src/ui/confirm-ui-handler.ts b/src/ui/confirm-ui-handler.ts new file mode 100644 index 000000000..e2efb7bbd --- /dev/null +++ b/src/ui/confirm-ui-handler.ts @@ -0,0 +1,114 @@ +import BattleScene from "../battle-scene"; +import { addTextObject, TextStyle } from "../text"; +import { Mode } from "./ui"; +import UiHandler from "./uiHandler"; + +export default class ConfirmUiHandler extends UiHandler { + private yesHandler: Function; + private noHander: Function; + + private confirmContainer: Phaser.GameObjects.Container; + private confirmBg: Phaser.GameObjects.Image; + + private cursorObj: Phaser.GameObjects.Image; + + private switchCheck: boolean; + private switchCheckCursor: integer; + + constructor(scene: BattleScene) { + super(scene, Mode.CONFIRM); + } + + setup() { + const ui = this.getUi(); + + this.confirmContainer = this.scene.add.container((this.scene.game.canvas.width / 6) - 49, -49); + this.confirmContainer.setVisible(false); + ui.add(this.confirmContainer); + + this.confirmBg = this.scene.add.image(0, 0, 'boolean_window'); + this.confirmBg.setOrigin(0, 1); + this.confirmContainer.add(this.confirmBg); + + const confirmText = addTextObject(this.scene, 0, 0, 'Yes\nNo', TextStyle.WINDOW, { maxLines: 2 }); + confirmText.setPositionRelative(this.confirmBg, 16, 9); + confirmText.setLineSpacing(12); + this.confirmContainer.add(confirmText); + + this.setCursor(0); + } + + show(args: any[]) { + if (args.length >= 2 && args[0] instanceof Function && args[1] instanceof Function) { + super.show(args); + + this.yesHandler = args[0] as Function; + this.noHander = args[1] as Function; + this.switchCheck = args.length >= 3 && args[2] as boolean; + + this.confirmContainer.setVisible(true); + this.setCursor(this.switchCheck ? this.switchCheckCursor : 0); + } + } + + processInput(keyCode: integer) { + const keyCodes = Phaser.Input.Keyboard.KeyCodes; + const ui = this.getUi(); + + let success = false; + + if (keyCode === keyCodes.Z || keyCode === keyCodes.X) { + success = true; + if (keyCode === keyCodes.X) + this.setCursor(1); + const handler = this.cursor ? this.noHander : this.yesHandler; + handler(); + console.log(this.cursor ? this.noHander : this.yesHandler); + this.clear(); + } else { + switch (keyCode) { + case keyCodes.UP: + if (this.cursor) + success = this.setCursor(0); + break; + case keyCodes.DOWN: + if (!this.cursor) + success = this.setCursor(1); + break; + } + } + + if (success) + ui.playSelect(); + } + + setCursor(cursor: integer): boolean { + const ret = super.setCursor(cursor); + + if (ret && this.switchCheck) + this.switchCheckCursor = this.cursor; + + if (!this.cursorObj) { + this.cursorObj = this.scene.add.image(0, 0, 'cursor'); + this.confirmContainer.add(this.cursorObj); + } + + this.cursorObj.setPositionRelative(this.confirmBg, 12, this.cursor ? 33 : 17); + + return ret; + } + + clear() { + super.clear(); + this.yesHandler = null; + this.noHander = null; + this.confirmContainer.setVisible(false); + this.eraseCursor(); + } + + eraseCursor() { + if (this.cursorObj) + this.cursorObj.destroy(); + this.cursorObj = null; + } +} \ No newline at end of file diff --git a/src/ui/modifier-select-ui-handler.ts b/src/ui/modifier-select-ui-handler.ts index 461b1392e..234ccbdf3 100644 --- a/src/ui/modifier-select-ui-handler.ts +++ b/src/ui/modifier-select-ui-handler.ts @@ -13,7 +13,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { private cursorObj: Phaser.GameObjects.Image; constructor(scene: BattleScene) { - super(scene, Mode.SWITCH_CHECK); + super(scene, Mode.CONFIRM); this.options = []; } diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index 9235dce66..01104d317 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -172,7 +172,7 @@ export default class PartyUiHandler extends MessageUiHandler { } else if (option === PartyOption.SUMMARY) { this.clearOptions(); ui.playSelect(); - ui.setModeWithoutClear(Mode.SUMMARY); + ui.setModeWithoutClear(Mode.SUMMARY, this.scene.getParty()[this.cursor]); } 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 0b473ae68..22f40bc78 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -2,21 +2,41 @@ import BattleScene from "../battle-scene"; import { Mode } from "./ui"; import UiHandler from "./uiHandler"; import * as Utils from "../utils"; +import { PlayerPokemon } from "../pokemon"; +import { Type } from "../type"; +import { TextStyle, addTextObject } from "../text"; +import Move from "../move"; enum Page { PROFILE, MOVES } +export enum SummaryUiMode { + DEFAULT, + LEARN_MOVE +} + export default class SummaryUiHandler extends UiHandler { + private summaryUiMode: SummaryUiMode; + private summaryContainer: Phaser.GameObjects.Container; private summaryPageContainer: Phaser.GameObjects.Container; - private summaryPageBg: Phaser.GameObjects.Sprite; + private movesContainer: Phaser.GameObjects.Container; + private moveCursorObj: Phaser.GameObjects.Sprite; + private selectedMoveCursorObj: Phaser.GameObjects.Sprite; + private extraMoveRowContainer: Phaser.GameObjects.Container; private summaryPageTransitionContainer: Phaser.GameObjects.Container; - private summaryPageTransitionBg: Phaser.GameObjects.Sprite; + private pokemon: PlayerPokemon; + private newMove: Move; + private moveSelectFunction: Function; private transitioning: boolean; + private moveSelect: boolean; + private moveCursor: integer; + private selectedMoveIndex: integer; + constructor(scene: BattleScene) { super(scene, Mode.SUMMARY); } @@ -35,14 +55,15 @@ export default class SummaryUiHandler extends UiHandler { const getSummaryPageBg = () => { const ret = this.scene.add.sprite(0, 0, this.getPageKey(0)); ret.setOrigin(0, 1); - ret.setVisible(false); return ret; }; - this.summaryPageContainer = this.scene.add.container(106, 0); - this.summaryPageContainer.add((this.summaryPageBg = getSummaryPageBg())); - this.summaryPageTransitionContainer = this.scene.add.container(106, 0); - this.summaryPageTransitionContainer.add((this.summaryPageTransitionBg = getSummaryPageBg())); + this.summaryContainer.add((this.summaryPageContainer = this.scene.add.container(106, 0))); + this.summaryPageContainer.add(getSummaryPageBg()); + this.summaryPageContainer.setVisible(false); + this.summaryContainer.add((this.summaryPageTransitionContainer = this.scene.add.container(106, 0))); + this.summaryPageTransitionContainer.add(getSummaryPageBg()); + this.summaryPageTransitionContainer.setVisible(false); } getPageKey(page?: integer) { @@ -54,9 +75,26 @@ export default class SummaryUiHandler extends UiHandler { show(args: any[]) { super.show(args); + this.pokemon = args[0] as PlayerPokemon; + this.summaryUiMode = args.length > 1 ? args[1] as SummaryUiMode : SummaryUiMode.DEFAULT; + this.summaryContainer.setVisible(true); this.cursor = -1; - this.setCursor(args.length ? args[0] as Page : 0); + + this.pokemon.cry(); + + switch (this.summaryUiMode) { + case SummaryUiMode.DEFAULT: + this.setCursor(Page.PROFILE); + break; + case SummaryUiMode.LEARN_MOVE: + this.newMove = args[2] as Move; + this.moveSelectFunction = args[3] as Function; + + this.setCursor(Page.MOVES); + this.showMoveSelect(); + break; + } } processInput(keyCode: integer) { @@ -68,20 +106,50 @@ export default class SummaryUiHandler extends UiHandler { let success = false; - if (keyCode === keyCodes.X) { - ui.setMode(Mode.PARTY); - success = true; + if (this.moveSelect) { + if (keyCode === keyCodes.Z) { + if (this.moveCursor < this.pokemon.moveset.length) { + if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) + this.moveSelectFunction(this.moveCursor); + else + this.selectedMoveIndex = this.moveCursor; + success = true; + } else if (this.moveCursor === 4) + this.processInput(keyCodes.X); + } else if (keyCode === keyCodes.X) { + this.hideMoveSelect(); + success = true; + } else { + switch (keyCode) { + case keyCodes.UP: + success = this.setCursor(this.moveCursor ? this.moveCursor - 1 : 4); + break; + case keyCodes.DOWN: + success = this.setCursor(this.moveCursor < 4 ? this.moveCursor + 1 : 0); + break; + } + } } else { - const pages = Utils.getEnumValues(Page); - switch (keyCode) { - case keyCodes.LEFT: - if (this.cursor) - success = this.setCursor(this.cursor - 1); - break; - case keyCodes.RIGHT: - if (this.cursor < pages.length - 1) - success = this.setCursor(this.cursor + 1); - break; + if (keyCode === keyCodes.Z) { + if (this.cursor === Page.MOVES) { + this.showMoveSelect(); + success = true; + } + } else if (keyCode === keyCodes.X) { + ui.setMode(Mode.PARTY); + success = true; + } else { + const pages = Utils.getEnumValues(Page); + switch (keyCode) { + case keyCodes.LEFT: + if (this.cursor) + success = this.setCursor(this.cursor - 1); + break; + case keyCodes.RIGHT: + if (this.cursor < pages.length - 1) + success = this.setCursor(this.cursor + 1); + break; + } } } @@ -90,35 +158,52 @@ export default class SummaryUiHandler extends UiHandler { } setCursor(cursor: integer): boolean { - const changed = this.cursor !== cursor; - if (changed) { - const forward = this.cursor < cursor; - this.cursor = cursor; + let changed: boolean; + + if (this.moveSelect) { + changed = this.moveCursor !== cursor; + if (changed) { + this.moveCursor = cursor; - if (this.summaryPageContainer.visible) { - this.transitioning = true; - this.populatePageContainer(this.summaryPageTransitionContainer, forward ? cursor : cursor + 1); - if (forward) - this.summaryPageTransitionContainer.x += 214; - else + 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); + } + } else { + changed = this.cursor !== cursor; + if (changed) { + const forward = this.cursor < cursor; + this.cursor = cursor; + + if (this.summaryPageContainer.visible) { + this.transitioning = true; + this.populatePageContainer(this.summaryPageTransitionContainer, forward ? cursor : cursor + 1); + if (forward) + this.summaryPageTransitionContainer.x += 214; + else + this.populatePageContainer(this.summaryPageContainer); + this.scene.tweens.add({ + targets: this.summaryPageTransitionContainer, + x: forward ? '-=214' : '+=214', + duration: 250, + onComplete: () => { + if (forward) + this.populatePageContainer(this.summaryPageContainer); + else + this.summaryPageTransitionContainer.x -= 214; + this.summaryPageTransitionContainer.setVisible(false); + this.transitioning = false; + } + }); + this.summaryPageTransitionContainer.setVisible(true); + } else { this.populatePageContainer(this.summaryPageContainer); - this.scene.tweens.add({ - targets: this.summaryPageTransitionContainer, - x: forward ? '-=214' : '+=214', - duration: 250, - onComplete: () => { - if (forward) - this.populatePageContainer(this.summaryPageContainer); - else - this.summaryPageTransitionContainer.x -= 214; - this.summaryPageTransitionContainer.setVisible(false); - this.transitioning = false; - } - }); - this.summaryPageTransitionContainer.setVisible(true); - } else { - this.populatePageContainer(this.summaryPageContainer); - this.summaryPageContainer.setVisible(true); + this.summaryPageContainer.setVisible(true); + } } } @@ -129,19 +214,68 @@ export default class SummaryUiHandler extends UiHandler { if (page === undefined) page = this.cursor; - if (pageContainer.getAll().length > 1) + if (pageContainer.getAll().length > 1) { + if (this.movesContainer) + this.movesContainer.removeAll(true); pageContainer.removeBetween(1, undefined, true); - (pageContainer.getAt(0) as Phaser.GameObjects.Sprite).setTexture(this.getPageKey(page)); + } + const pageBg = (pageContainer.getAt(0) as Phaser.GameObjects.Sprite); + pageBg.setTexture(this.getPageKey(page)); switch (page) { case Page.MOVES: + this.movesContainer = this.scene.add.container(5, -pageBg.height + 26); + pageContainer.add(this.movesContainer); + + this.extraMoveRowContainer = this.scene.add.container(0, 64); + this.movesContainer.add(this.extraMoveRowContainer); + + const extraRowOverlay = this.scene.add.image(-2, 1, 'summary_moves_overlay_row'); + extraRowOverlay.setOrigin(0, 1); + this.extraMoveRowContainer.add(extraRowOverlay); + + const extraRowText = addTextObject(this.scene, 35, 0, this.summaryUiMode === SummaryUiMode.LEARN_MOVE ? this.newMove.name : 'CANCEL', + this.summaryUiMode === SummaryUiMode.LEARN_MOVE ? TextStyle.SUMMARY_RED : TextStyle.SUMMARY); + extraRowText.setOrigin(0, 1); + this.extraMoveRowContainer.add(extraRowText); + + for (let m = 0; m < 4; m++) { + const move = m < this.pokemon.moveset.length ? this.pokemon.moveset[m] : null; + + if (move) { + const typeIcon = this.scene.add.sprite(0, 16 * m, 'types', Type[move.getMove().type].toLowerCase()); + typeIcon.setOrigin(0, 1); + this.movesContainer.add(typeIcon); + } + + const moveText = addTextObject(this.scene, 35, 16 * m, move ? move.getName() : '-', TextStyle.SUMMARY); + moveText.setOrigin(0, 1); + this.movesContainer.add(moveText); + } break; } } + showMoveSelect() { + this.moveSelect = true; + this.setCursor(0); + } + + hideMoveSelect() { + if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { + this.moveSelectFunction(4); + return; + } + + this.moveSelect = false; + } + clear() { super.clear(); + this.pokemon = null; this.cursor = -1; + this.newMove = null; + this.moveSelectFunction = null; this.summaryContainer.setVisible(false); this.summaryPageContainer.setVisible(false); } diff --git a/src/ui/switch-check-ui-handler.ts b/src/ui/switch-check-ui-handler.ts deleted file mode 100644 index 33dabb4a8..000000000 --- a/src/ui/switch-check-ui-handler.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { SwitchPhase, SwitchSummonPhase } from "../battle-phase"; -import BattleScene from "../battle-scene"; -import { addTextObject, TextStyle } from "../text"; -import AwaitableUiHandler from "./awaitable-ui-handler"; -import { Mode } from "./ui"; - -export default class SwitchCheckUiHandler extends AwaitableUiHandler { - private switchCheckContainer: Phaser.GameObjects.Container; - private switchCheckBg: Phaser.GameObjects.Image; - - private cursorObj: Phaser.GameObjects.Image; - - constructor(scene: BattleScene) { - super(scene, Mode.SWITCH_CHECK); - } - - setup() { - const ui = this.getUi(); - - const switchCheckContainer = this.scene.add.container((this.scene.game.canvas.width / 6) - 49, -49); - switchCheckContainer.setVisible(false); - ui.add(switchCheckContainer); - - this.switchCheckContainer = switchCheckContainer; - - const switchCheckBg = this.scene.add.image(0, 0, 'boolean_window'); - switchCheckBg.setOrigin(0, 1); - switchCheckContainer.add(switchCheckBg); - - this.switchCheckBg = switchCheckBg; - - const switchCheckText = addTextObject(this.scene, 0, 0, 'Yes\nNo', TextStyle.WINDOW, { maxLines: 2 }); - switchCheckText.setPositionRelative(switchCheckBg, 16, 9); - switchCheckText.setLineSpacing(12); - switchCheckContainer.add(switchCheckText); - - this.setCursor(0); - } - - show(args: any[]) { - if (args.length && args[0] instanceof Function) { - super.show(args); - - this.awaitingActionInput = true; - this.onActionInput = args[0] as Function; - - this.switchCheckContainer.setVisible(true); - this.setCursor(this.cursor); - } - } - - processInput(keyCode: integer) { - const keyCodes = Phaser.Input.Keyboard.KeyCodes; - const ui = this.getUi(); - - if (!this.awaitingActionInput) - return; - - let success = false; - - if (keyCode === keyCodes.Z || keyCode === keyCodes.X) { - success = true; - if (keyCode === keyCodes.X) - this.setCursor(1); - if (this.onActionInput) { - if (!this.cursor) - this.scene.unshiftPhase(new SwitchPhase(this.scene, false, true)); - const originalOnActionInput = this.onActionInput; - this.onActionInput = null; - originalOnActionInput(); - this.clear(); - } - } else { - switch (keyCode) { - case keyCodes.UP: - if (this.cursor) - success = this.setCursor(0); - break; - case keyCodes.DOWN: - if (!this.cursor) - success = this.setCursor(1); - break; - } - } - - if (success) - ui.playSelect(); - } - - setCursor(cursor: integer): boolean { - const ret = super.setCursor(cursor); - - if (!this.cursorObj) { - this.cursorObj = this.scene.add.image(0, 0, 'cursor'); - this.switchCheckContainer.add(this.cursorObj); - } - - this.cursorObj.setPositionRelative(this.switchCheckBg, 12, this.cursor ? 33 : 17); - - return ret; - } - - clear() { - super.clear(); - this.switchCheckContainer.setVisible(false); - this.eraseCursor(); - } - - eraseCursor() { - if (this.cursorObj) - this.cursorObj.destroy(); - this.cursorObj = null; - } -} \ No newline at end of file diff --git a/src/ui/ui.ts b/src/ui/ui.ts index 54f71500a..3cbfa1259 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -5,7 +5,7 @@ import CommandUiHandler from './command-ui-handler'; import PartyUiHandler from './party-ui-handler'; import FightUiHandler from './fight-ui-handler'; import MessageUiHandler from './message-ui-handler'; -import SwitchCheckUiHandler from './switch-check-ui-handler'; +import ConfirmUiHandler from './confirm-ui-handler'; import ModifierSelectUiHandler from './modifier-select-ui-handler'; import BallUiHandler from './ball-ui-handler'; import SummaryUiHandler from './summary-ui-handler'; @@ -15,15 +15,21 @@ export enum Mode { COMMAND, FIGHT, BALL, - SWITCH_CHECK, + CONFIRM, MODIFIER_SELECT, PARTY, SUMMARY }; +const transitionModes = [ + Mode.PARTY, + Mode.SUMMARY +]; + export default class UI extends Phaser.GameObjects.Container { private mode: Mode; private handlers: UiHandler[]; + private overlay: Phaser.GameObjects.Rectangle; constructor(scene: BattleScene) { super(scene, 0, scene.game.canvas.height / 6); @@ -34,7 +40,7 @@ export default class UI extends Phaser.GameObjects.Container { new CommandUiHandler(scene), new FightUiHandler(scene), new BallUiHandler(scene), - new SwitchCheckUiHandler(scene), + new ConfirmUiHandler(scene), new ModifierSelectUiHandler(scene), new PartyUiHandler(scene), new SummaryUiHandler(scene) @@ -45,6 +51,10 @@ export default class UI extends Phaser.GameObjects.Container { for (let handler of this.handlers) { handler.setup(); } + this.overlay = this.scene.add.rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6, 0); + this.overlay.setOrigin(0, 0); + (this.scene as BattleScene).uiContainer.add(this.overlay); + this.overlay.setVisible(false); } getHandler() { @@ -91,18 +101,47 @@ export default class UI extends Phaser.GameObjects.Container { this.scene.sound.play('error'); } - setMode(mode: Mode, ...args: any[]) { - if (this.mode === mode) - return; - this.getHandler().clear(); - this.mode = mode; - this.getHandler().show(args); + private setModeInternal(mode: Mode, clear: boolean, args: any[]): Promise { + return new Promise(resolve => { + if (this.mode === mode) { + resolve(); + return; + } + const doSetMode = () => { + this.getHandler().clear(); + this.mode = mode; + this.getHandler().show(args); + resolve(); + }; + if (transitionModes.indexOf(this.mode) > -1 || transitionModes.indexOf(mode) > -1) { + this.overlay.setAlpha(0); + this.overlay.setVisible(true); + this.scene.tweens.add({ + targets: this.overlay, + alpha: 1, + duration: 250, + onComplete: () => { + this.scene.time.delayedCall(250, () => { + doSetMode(); + this.scene.tweens.add({ + targets: this.overlay, + alpha: 0, + duration: 250, + onComplete: () => this.overlay.setVisible(false) + }); + }); + } + }); + } else + doSetMode(); + }); } - setModeWithoutClear(mode: Mode, ...args: any[]) { - if (this.mode === mode) - return; - this.mode = mode; - this.getHandler().show(args); + setMode(mode: Mode, ...args: any[]): Promise { + return this.setModeInternal(mode, true, args); + } + + setModeWithoutClear(mode: Mode, ...args: any[]): Promise { + return this.setModeInternal(mode, false, args); } } \ No newline at end of file