diff --git a/README.md b/README.md index e719a780d..91d35e665 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,9 @@ ## To do - Title screen +- Starter select screen + - UI + - Get starters from save data caught Pokemon - Moves - Move logic - Can't use when PP consumed @@ -15,7 +18,6 @@ - EXP logic - Fix algorithm (currently inaccurate) - Pokemon summary screen - - Move learning when full - Move remembering (no cost?) - Capture logic - Critical capture @@ -24,10 +26,6 @@ - Battle info - Owned icon - Status effect indicator -- Evolution - - Evolution screen - - Background (ripped video?) - - Particles - Modifiers - PP Up - Ether/elixir diff --git a/public/audio/se/beam.wav b/public/audio/se/beam.wav new file mode 100644 index 000000000..f6fec5322 Binary files /dev/null and b/public/audio/se/beam.wav differ diff --git a/public/audio/se/charge.wav b/public/audio/se/charge.wav new file mode 100644 index 000000000..c4fa97c6e Binary files /dev/null and b/public/audio/se/charge.wav differ diff --git a/public/audio/se/shine.wav b/public/audio/se/shine.wav new file mode 100644 index 000000000..41c68c81b Binary files /dev/null and b/public/audio/se/shine.wav differ diff --git a/public/audio/se/shiny.wav b/public/audio/se/sparkle.wav similarity index 100% rename from public/audio/se/shiny.wav rename to public/audio/se/sparkle.wav diff --git a/src/auto-play.ts b/src/auto-play.ts index 7314adf38..68c91337f 100644 --- a/src/auto-play.ts +++ b/src/auto-play.ts @@ -117,12 +117,13 @@ export function initAutoPlay() { let nextPartyMemberIndex = -1; const originalMessageUiHandlerShowText = MessageUiHandler.prototype.showText; - MessageUiHandler.prototype.showText = function (text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean) { + MessageUiHandler.prototype.showText = function (text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer) { if (thisArg.auto) { delay = 1; callbackDelay = 0; + promptDelay = 0; } - originalMessageUiHandlerShowText.apply(this, [ text, delay, callback, callbackDelay, prompt ]); + originalMessageUiHandlerShowText.apply(this, [ text, delay, callback, callbackDelay, prompt, promptDelay ]); }; const originalMessageUiHandlerShowPrompt = MessageUiHandler.prototype.showPrompt; diff --git a/src/battle-info.ts b/src/battle-info.ts index b6b2143f9..8aab1d98c 100644 --- a/src/battle-info.ts +++ b/src/battle-info.ts @@ -6,6 +6,7 @@ import { getGenderSymbol, getGenderColor } from './gender'; export default class BattleInfo extends Phaser.GameObjects.Container { private player: boolean; + private lastName: string; private lastHp: integer; private lastMaxHp: integer; private lastHpFrame: string; @@ -75,6 +76,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { initInfo(pokemon: Pokemon) { this.nameText.setText(pokemon.name); + this.lastName = pokemon.name; const nameSizeTest = addTextObject(this.scene, 0, 0, pokemon.name, TextStyle.BATTLE_INFO); const nameTextWidth = nameSizeTest.displayWidth; @@ -108,6 +110,17 @@ export default class BattleInfo extends Phaser.GameObjects.Container { return; } + if (this.lastName !== pokemon.species.name) { + this.nameText.setText(pokemon.name); + this.lastName = pokemon.name; + + const nameSizeTest = addTextObject(this.scene, 0, 0, pokemon.name, TextStyle.BATTLE_INFO); + const nameTextWidth = nameSizeTest.displayWidth; + nameSizeTest.destroy(); + + this.genderText.setPositionRelative(this.nameText, nameTextWidth, 0); + } + const updatePokemonHp = () => { const duration = !instant ? Utils.clampInt(Math.abs((this.lastHp) - pokemon.hp) * 5, 250, 5000) : 0; this.scene.tweens.add({ @@ -205,7 +218,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { } setLevel(level: integer) { - this.levelNumbersContainer.removeAll(); + this.levelNumbersContainer.removeAll(true); const levelStr = level.toString(); for (let i = 0; i < levelStr.length; i++) this.levelNumbersContainer.add(this.scene.add.image(i * 8, 0, 'numbers', levelStr[i])); @@ -215,7 +228,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { setHpNumbers(hp: integer, maxHp: integer) { if (!this.player) return; - this.hpNumbersContainer.removeAll(); + this.hpNumbersContainer.removeAll(true); const hpStr = hp.toString(); const maxHpStr = maxHp.toString(); let offset = 0; diff --git a/src/battle-phase.ts b/src/battle-phase.ts index aecdd4096..7c76000cb 100644 --- a/src/battle-phase.ts +++ b/src/battle-phase.ts @@ -1,19 +1,18 @@ import BattleScene from "./battle-scene"; import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove } from "./pokemon"; import * as Utils from './utils'; -import { allMoves, Moves as Move, MoveCategory, Moves } from "./move"; +import { allMoves, MoveCategory, Moves } from "./move"; import { Mode } from './ui/ui'; import { Command } from "./ui/command-ui-handler"; import { Stat } from "./pokemon-stat"; import { ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, getModifierTypesForWave, ModifierType, PokemonModifierType, regenerateModifierPoolThresholds } from "./modifier"; import PartyUiHandler, { PartyUiMode } from "./ui/party-ui-handler"; import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor as getPokeballTintColor, PokeballType } from "./pokeball"; -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"; -import { Species } from "./species"; -import { SpeciesEvolution } from "./pokemon-evolutions"; +import EvolutionSceneHandler from "./ui/evolution-scene-handler"; +import { EvolutionPhase } from "./evolution-phase"; export class BattlePhase { protected scene: BattleScene; @@ -63,7 +62,8 @@ export class EncounterPhase extends BattlePhase { if (this.scene.getPlayerPokemon().visible) this.scene.field.moveBelow(enemyPokemon, this.scene.getPlayerPokemon()); enemyPokemon.tint(0, 0.5); - this.doEncounter(); + + this.scene.ui.setMode(Mode.MESSAGE).then(() => this.doEncounter()); }); } @@ -735,7 +735,7 @@ export class ExpPhase extends PartyMemberPokemonPhase { pokemon.addExp(exp.value); newLevel = pokemon.level; if (newLevel > lastLevel) - this.scene.unshiftPhase(new LevelUpPhase(this.scene, this.partyMemberIndex, newLevel)); + this.scene.unshiftPhase(new LevelUpPhase(this.scene, this.partyMemberIndex, lastLevel, newLevel)); pokemon.updateInfo().then(() => this.end()); }, null, true); } @@ -744,11 +744,13 @@ export class ExpPhase extends PartyMemberPokemonPhase { } export class LevelUpPhase extends PartyMemberPokemonPhase { + private lastLevel: integer; private level: integer; - constructor(scene: BattleScene, partyMemberIndex: integer, level: integer) { + constructor(scene: BattleScene, partyMemberIndex: integer, lastLevel: integer, level: integer) { super(scene, partyMemberIndex); + this.lastLevel = lastLevel; this.level = level; } @@ -762,25 +764,20 @@ export class LevelUpPhase extends PartyMemberPokemonPhase { this.scene.pauseBgm(); this.scene.sound.play('level_up_fanfare'); this.scene.ui.showText(`${this.getPokemon().name} grew to\nLV. ${this.level}!`, null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(prevStats, false, () => this.end()), null, true); - const levelMoves = pokemonLevelMoves[pokemon.species.speciesId]; - if (levelMoves) { - for (let lm of levelMoves) { - const level = lm[0]; - if (level < this.level) - continue; - else if (level > this.level) - break; - this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, lm[1])); - } - } + const levelMoves = this.getPokemon().getLevelMoves(this.lastLevel + 1); + for (let lm of levelMoves) + this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, lm)); + const evolution = pokemon.getEvolution(); + if (evolution) + this.scene.unshiftPhase(new EvolutionPhase(this.scene, this.partyMemberIndex, evolution, this.lastLevel)); this.scene.time.delayedCall(1500, () => this.scene.resumeBgm()); } } export class LearnMovePhase extends PartyMemberPokemonPhase { - private moveId: Move; + private moveId: Moves; - constructor(scene: BattleScene, partyMemberIndex: integer, moveId: Move) { + constructor(scene: BattleScene, partyMemberIndex: integer, moveId: Moves) { super(scene, partyMemberIndex); this.moveId = moveId; @@ -791,7 +788,6 @@ export class LearnMovePhase extends PartyMemberPokemonPhase { const pokemon = this.getPokemon(); const move = allMoves[this.moveId - 1]; - console.log(move, this.moveId); const existingMoveIndex = pokemon.moveset.findIndex(m => m?.moveId === move.id); @@ -804,45 +800,52 @@ export class LearnMovePhase extends PartyMemberPokemonPhase { ? pokemon.moveset.length : pokemon.moveset.findIndex(m => m === null); + const messageMode = this.scene.ui.getHandler() instanceof EvolutionSceneHandler + ? Mode.EVOLUTION_SCENE + : Mode.MESSAGE; + if (emptyMoveIndex > -1) { pokemon.moveset[emptyMoveIndex] = new PokemonMove(this.moveId, 0, 0); initAnim(this.moveId).then(() => { loadMoveAnimAssets(this.scene, [ this.moveId ], true) .then(() => { - this.scene.ui.setMode(Mode.MESSAGE).then(() => { + this.scene.ui.setMode(messageMode).then(() => { + this.scene.pauseBgm(); this.scene.sound.play('level_up_fanfare'); - this.scene.ui.showText(`${pokemon.name} learned\n${Utils.toPokemonUpperCase(move.name)}!`, null, () => this.end(), null, true); + this.scene.ui.showText(`${pokemon.name} learned\n${Utils.toPokemonUpperCase(move.name)}!`, null, () => this.end(), messageMode === Mode.EVOLUTION_SCENE ? 1000 : null, true); + this.scene.time.delayedCall(1500, () => this.scene.resumeBgm()); }); }); }); } else { - this.scene.ui.setMode(Mode.MESSAGE).then(() => { + this.scene.ui.setMode(messageMode).then(() => { 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.setMode(messageMode).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.setModeWithoutClear(Mode.CONFIRM, () => { + this.scene.ui.setMode(messageMode); this.scene.ui.showText(`${pokemon.name} did not learn the\nmove ${move.name}.`, null, () => this.end(), null, true); }, () => { + this.scene.ui.setMode(messageMode); 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.setModeWithoutClear(Mode.CONFIRM, () => { + this.scene.ui.setMode(messageMode); this.scene.ui.showText('Which move should be forgotten?', null, () => { - this.scene.ui.setMode(Mode.SUMMARY, this.getPokemon(), SummaryUiMode.LEARN_MOVE, move, (moveIndex: integer) => { + this.scene.ui.setModeWithoutClear(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.setMode(messageMode).then(() => { + this.scene.ui.showText('@d{32}1, @d{15}2, and@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}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; @@ -1016,277 +1019,6 @@ export class AttemptCapturePhase extends BattlePhase { } } -export class EvolutionPhase extends BattlePhase { - private partyMemberIndex: integer; - private evolution: SpeciesEvolution; - - private evolutionContainer: Phaser.GameObjects.Container; - private evolutionBaseBg: Phaser.GameObjects.Image; - private evolutionBg: Phaser.GameObjects.Video; - private evolutionBgOverlay: Phaser.GameObjects.Rectangle; - private pokemonSprite: Phaser.GameObjects.Sprite; - private pokemonTintSprite: Phaser.GameObjects.Sprite; - private pokemonEvoSprite: Phaser.GameObjects.Sprite; - private pokemonEvoTintSprite: Phaser.GameObjects.Sprite; - - constructor(scene: BattleScene, partyMemberIndex: integer, evolution: SpeciesEvolution) { - super(scene); - - this.partyMemberIndex = partyMemberIndex; - this.evolution = evolution; - } - - start() { - super.start(); - - if (!this.evolution) { - this.end(); - return; - } - - this.scene.pauseBgm(); - - this.evolutionContainer = this.scene.add.container(0, 0); - this.scene.field.add(this.evolutionContainer); - - this.evolutionBaseBg = this.scene.add.image(0, 0, 'plains_bg'); - this.evolutionBaseBg.setOrigin(0, 0); - this.evolutionContainer.add(this.evolutionBaseBg); - - this.evolutionBg = this.scene.add.video(0, 0, 'evo_bg').stop(); - this.evolutionBg.setOrigin(0, 0); - this.evolutionBg.setScale(0.4359673025); - this.evolutionBg.setVisible(false); - this.evolutionContainer.add(this.evolutionBg); - - this.evolutionBgOverlay = this.scene.add.rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6, 0x262626); - this.evolutionBgOverlay.setOrigin(0, 0); - this.evolutionBgOverlay.setAlpha(0); - this.evolutionContainer.add(this.evolutionBgOverlay); - - const getPokemonSprite = () => { - return this.scene.add.sprite(this.evolutionBaseBg.displayWidth / 2, this.evolutionBaseBg.displayHeight / 2, `pkmn__sub`); - }; - - this.evolutionContainer.add((this.pokemonSprite = getPokemonSprite())); - this.evolutionContainer.add((this.pokemonTintSprite = getPokemonSprite())); - this.evolutionContainer.add((this.pokemonEvoSprite = getPokemonSprite())); - this.evolutionContainer.add((this.pokemonEvoTintSprite = getPokemonSprite())); - - this.pokemonTintSprite.setAlpha(0); - this.pokemonTintSprite.setTintFill(0xFFFFFF); - this.pokemonEvoSprite.setVisible(false); - this.pokemonEvoTintSprite.setVisible(false); - this.pokemonEvoTintSprite.setTintFill(0xFFFFFF); - - const pokemon = this.scene.getParty()[this.partyMemberIndex]; - - this.pokemonSprite.play(pokemon.getSpriteKey()); - this.pokemonTintSprite.play(pokemon.getSpriteKey()); - this.pokemonEvoSprite.play(pokemon.getSpriteKey()); - this.pokemonEvoTintSprite.play(pokemon.getSpriteKey()); - - this.scene.ui.showText(`What?\n${pokemon.name} is evolving!`, null, () => { - pokemon.cry(); - - pokemon.evolve(this.evolution).then(() => { - this.pokemonEvoSprite.play(pokemon.getSpriteKey()); - this.pokemonEvoTintSprite.play(pokemon.getSpriteKey()); - }); - - this.scene.time.delayedCall(1000, () => { - this.scene.tweens.add({ - targets: this.evolutionBgOverlay, - alpha: 1, - delay: 500, - duration: 1500, - ease: 'Sine.easeOut', - onComplete: () => { - this.scene.time.delayedCall(1000, () => { - this.scene.tweens.add({ - targets: this.evolutionBgOverlay, - alpha: 0, - duration: 250, - onComplete: () => this.evolutionBgOverlay.setVisible(false) - }); - this.evolutionBg.setVisible(true); - this.evolutionBg.play(); - }); - this.doSpiralUpward(); - this.scene.tweens.addCounter({ - from: 0, - to: 1, - duration: 2000, - onUpdate: t => { - this.pokemonTintSprite.setAlpha(t.getValue()); - }, - onComplete: () => { - this.pokemonSprite.setVisible(false); - this.scene.time.delayedCall(1000, () => { - this.doArcDownward(); - this.scene.time.delayedCall(1500, () => { - this.pokemonEvoTintSprite.setScale(0.25); - this.pokemonEvoTintSprite.setVisible(true); - this.doCycle(1).then(() => { - this.scene.sound.play('shiny'); - this.pokemonEvoSprite.setVisible(true); - }); - }); - }); - } - }) - } - }); - //this.scene.sound.play('evolution'); - }); - }, 1000); - } - - sin(index: integer, amplitude: integer) { - return amplitude * Math.sin(index * (Math.PI / 128)); - } - - cos(index: integer, amplitude: integer) { - return amplitude * Math.cos(index * (Math.PI / 128)); - } - - doSpiralUpward() { - let f = 0; - - this.scene.tweens.addCounter({ - repeat: 64, - duration: 1, - useFrames: true, - onRepeat: () => { - if (f < 64) { - if (!(f & 7)) { - for (let i = 0; i < 4; i++) - this.doSpiralUpwardParticle((f & 120) * 2 + i * 64); - } - f++; - } - } - }); - } - - doArcDownward() { - let f = 0; - - this.scene.tweens.addCounter({ - repeat: 96, - duration: 1, - useFrames: true, - onRepeat: () => { - if (f < 96) { - if (f < 6) { - for (let i = 0; i < 9; i++) - this.doArcDownParticle(i * 16); - } - f++; - } - } - }); - } - - doCycle(l: number): Promise { - return new Promise(resolve => { - const isLastCycle = l === 15; - this.scene.tweens.add({ - targets: this.pokemonTintSprite, - scale: 0.25, - ease: 'Cubic.easeInOut', - duration: 500 / l, - yoyo: !isLastCycle - }); - this.scene.tweens.add({ - targets: this.pokemonEvoTintSprite, - scale: 1, - ease: 'Cubic.easeInOut', - duration: 500 / l, - yoyo: !isLastCycle, - onComplete: () => { - if (l < 15) - this.doCycle(l + 0.5).then(() => resolve()); - else { - this.pokemonTintSprite.setVisible(false); - resolve(); - } - } - }); - }); - } - - doSpiralUpwardParticle(trigIndex: integer) { - const initialX = (this.scene.game.canvas.width / 6) / 2; - const particle = this.scene.add.image(initialX, 0, 'evo_sparkle'); - this.evolutionContainer.add(particle); - - let f = 0; - let amp = 48; - - const particleTimer = this.scene.tweens.addCounter({ - repeat: -1, - duration: 1, - useFrames: true, - onRepeat: () => { - updateParticle(); - } - }); - - const updateParticle = () => { - if (!f || particle.y > 8) { - particle.setPosition(initialX, 88 - (f * f) / 80); - particle.y += this.sin(trigIndex, amp) / 4; - particle.x += this.cos(trigIndex, amp); - particle.setScale(1 - (f / 80)); - trigIndex += 4; - if (f & 1) - amp--; - f++; - } else { - particle.destroy(); - particleTimer.remove(); - } - }; - - updateParticle(); - } - - doArcDownParticle(trigIndex: integer) { - const initialX = (this.scene.game.canvas.width / 6) / 2; - const particle = this.scene.add.image(initialX, 0, 'evo_sparkle'); - particle.setScale(0.5); - this.evolutionContainer.add(particle); - - let f = 0; - let amp = 8; - - const particleTimer = this.scene.tweens.addCounter({ - repeat: -1, - duration: 1, - useFrames: true, - onRepeat: () => { - updateParticle(); - } - }); - - const updateParticle = () => { - if (!f || particle.y < 88) { - particle.setPosition(initialX, 8 + (f * f) / 5); - particle.y += this.sin(trigIndex, amp) / 4; - particle.x += this.cos(trigIndex, amp); - amp = 8 + this.sin(f * 4, 40); - f++; - } else { - particle.destroy(); - particleTimer.remove(); - } - }; - - updateParticle(); - } -} - export class SelectModifierPhase extends BattlePhase { constructor(scene: BattleScene) { super(scene); diff --git a/src/battle-scene.ts b/src/battle-scene.ts index d3ce92073..750230536 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -162,7 +162,7 @@ export default class BattleScene extends Phaser.Scene { // Load pokemon-related images this.loadImage(`pkmn__back__sub`, 'pokemon/back', 'sub.png'); this.loadImage(`pkmn__sub`, 'pokemon', 'sub.png'); - this.loadAtlas('shiny', 'effects'); + this.loadAtlas('sparkle', 'effects'); this.loadImage('evo_sparkle', 'effects'); this.load.video('evo_bg', 'images/effects/evo_bg.mp4', null, false, true); @@ -184,8 +184,11 @@ export default class BattleScene extends Phaser.Scene { this.loadSe('flee'); this.loadSe('exp'); this.loadSe('level_up'); - this.loadSe('shiny'); + this.loadSe('sparkle'); this.loadSe('restore'); + this.loadSe('shine'); + this.loadSe('charge'); + this.loadSe('beam'); this.loadSe('error'); this.loadSe('pb'); @@ -257,7 +260,7 @@ export default class BattleScene extends Phaser.Scene { for (let s = 0; s < 3; s++) { const playerSpecies = getPokemonSpecies(s === 0 ? Species.TORCHIC : s === 1 ? Species.TREECKO : Species.MUDKIP); //this.randomSpecies(); - const playerPokemon = new PlayerPokemon(this, playerSpecies, 16); + const playerPokemon = new PlayerPokemon(this, playerSpecies, 5); playerPokemon.setVisible(false); loadPokemonAssets.push(playerPokemon.loadAssets()); @@ -345,7 +348,6 @@ export default class BattleScene extends Phaser.Scene { this.unshiftPhase(new NewBiomeEncounterPhase(this)); } } else { - this.pushPhase(new EvolutionPhase(this, 0, this.getPlayerPokemon().getEvolution())); //this.pushPhase(new SelectStarterPhase(this)); this.pushPhase(new EncounterPhase(this)); this.pushPhase(new SummonPhase(this)); @@ -356,7 +358,7 @@ export default class BattleScene extends Phaser.Scene { } newBiome(): BiomeArena { - const biome = this.currentBattle ? Utils.randInt(20) as Biome : Biome.LAKE; + const biome = this.currentBattle ? Utils.randInt(20) as Biome : Biome.PLAINS; this.arena = new BiomeArena(this, biome, Biome[biome].toLowerCase()); return this.arena; } @@ -401,7 +403,13 @@ export default class BattleScene extends Phaser.Scene { }); } - playBgm(bgmName: string): void { + playBgm(bgmName?: string): void { + if (!bgmName && this.bgm) { + this.bgm.play({ + volume: 1 + }); + return; + } if (this.bgm && this.bgm.isPlaying) this.bgm.stop(); this.bgm = this.sound.add(bgmName, { loop: true }); @@ -418,6 +426,10 @@ export default class BattleScene extends Phaser.Scene { this.bgm.resume(); } + fadeOutBgm(destroy?: boolean): void { + this.arena.fadeOutBgm(500, destroy); + } + getCurrentPhase(): BattlePhase { return this.currentPhase; } diff --git a/src/biome.ts b/src/biome.ts index afaf94ea1..6ff01607f 100644 --- a/src/biome.ts +++ b/src/biome.ts @@ -132,8 +132,11 @@ export class BiomeArena { this.scene.load.once(Phaser.Loader.Events.COMPLETE, () => this.scene.playBgm(this.bgm)); } - fadeOutBgm(duration: integer) { - SoundFade.fadeOut(this.scene, this.scene.sound.get(this.bgm), duration); + fadeOutBgm(duration: integer, destroy?: boolean) { + if (destroy === undefined) + destroy = true; + const bgm = this.scene.sound.get(this.bgm); + SoundFade.fadeOut(this.scene, bgm, duration, destroy); } } diff --git a/src/evolution-phase.ts b/src/evolution-phase.ts new file mode 100644 index 000000000..cc58f2fc7 --- /dev/null +++ b/src/evolution-phase.ts @@ -0,0 +1,445 @@ +import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; +import { BattlePhase, LearnMovePhase } from "./battle-phase"; +import BattleScene from "./battle-scene"; +import { SpeciesEvolution } from "./pokemon-evolutions"; +import EvolutionSceneHandler from "./ui/evolution-scene-handler"; +import * as Utils from "./utils"; +import { Mode } from "./ui/ui"; + +export class EvolutionPhase extends BattlePhase { + private partyMemberIndex: integer; + private evolution: SpeciesEvolution; + private lastLevel: integer; + + private evolutionContainer: Phaser.GameObjects.Container; + private evolutionBaseBg: Phaser.GameObjects.Image; + private evolutionBg: Phaser.GameObjects.Video; + private evolutionBgOverlay: Phaser.GameObjects.Rectangle; + private evolutionOverlay: Phaser.GameObjects.Rectangle; + private pokemonSprite: Phaser.GameObjects.Sprite; + private pokemonTintSprite: Phaser.GameObjects.Sprite; + private pokemonEvoSprite: Phaser.GameObjects.Sprite; + private pokemonEvoTintSprite: Phaser.GameObjects.Sprite; + + constructor(scene: BattleScene, partyMemberIndex: integer, evolution: SpeciesEvolution, lastLevel: integer) { + super(scene); + + this.partyMemberIndex = partyMemberIndex; + this.evolution = evolution; + this.lastLevel = lastLevel; + } + + start() { + super.start(); + + this.scene.ui.setModeForceTransition(Mode.EVOLUTION_SCENE).then(() => { + + if (!this.evolution) { + this.end(); + return; + } + + this.scene.fadeOutBgm(false); + + this.evolutionContainer = (this.scene.ui.getHandler() as EvolutionSceneHandler).evolutionContainer; + + this.evolutionBaseBg = this.scene.add.image(0, 0, 'plains_bg'); + this.evolutionBaseBg.setOrigin(0, 0); + this.evolutionContainer.add(this.evolutionBaseBg); + + this.evolutionBg = this.scene.add.video(0, 0, 'evo_bg').stop(); + this.evolutionBg.setOrigin(0, 0); + this.evolutionBg.setScale(0.4359673025); + this.evolutionBg.setVisible(false); + this.evolutionContainer.add(this.evolutionBg); + + this.evolutionBgOverlay = this.scene.add.rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6, 0x262626); + this.evolutionBgOverlay.setOrigin(0, 0); + this.evolutionBgOverlay.setAlpha(0); + this.evolutionContainer.add(this.evolutionBgOverlay); + + const getPokemonSprite = () => { + return this.scene.add.sprite(this.evolutionBaseBg.displayWidth / 2, this.evolutionBaseBg.displayHeight / 2, `pkmn__sub`); + }; + + this.evolutionContainer.add((this.pokemonSprite = getPokemonSprite())); + this.evolutionContainer.add((this.pokemonTintSprite = getPokemonSprite())); + this.evolutionContainer.add((this.pokemonEvoSprite = getPokemonSprite())); + this.evolutionContainer.add((this.pokemonEvoTintSprite = getPokemonSprite())); + + this.pokemonTintSprite.setAlpha(0); + this.pokemonTintSprite.setTintFill(0xFFFFFF); + this.pokemonEvoSprite.setVisible(false); + this.pokemonEvoTintSprite.setVisible(false); + this.pokemonEvoTintSprite.setTintFill(0xFFFFFF); + + this.evolutionOverlay = this.scene.add.rectangle(0, -this.scene.game.canvas.height / 6, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6, 0xFFFFFF); + this.evolutionOverlay.setOrigin(0, 0); + this.evolutionOverlay.setAlpha(0); + this.scene.fieldUI.add(this.evolutionOverlay); + + const pokemon = this.scene.getParty()[this.partyMemberIndex]; + const preName = pokemon.name; + + this.pokemonSprite.play(pokemon.getSpriteKey()); + this.pokemonTintSprite.play(pokemon.getSpriteKey()); + this.pokemonEvoSprite.play(pokemon.getSpriteKey()); + this.pokemonEvoTintSprite.play(pokemon.getSpriteKey()); + + this.scene.ui.showText(`What?\n${preName} is evolving!`, null, () => { + pokemon.cry(); + + pokemon.evolve(this.evolution).then(() => { + this.pokemonEvoSprite.play(pokemon.getSpriteKey()); + this.pokemonEvoTintSprite.play(pokemon.getSpriteKey()); + }); + + const levelMoves = pokemon.getLevelMoves(this.lastLevel + 1); + for (let lm of levelMoves) + this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, lm)); + + this.scene.time.delayedCall(1000, () => { + const evolutionBgm = this.scene.sound.add('evolution'); + evolutionBgm.play(); + this.scene.tweens.add({ + targets: this.evolutionBgOverlay, + alpha: 1, + delay: 500, + duration: 1500, + ease: 'Sine.easeOut', + onComplete: () => { + this.scene.time.delayedCall(1000, () => { + this.scene.tweens.add({ + targets: this.evolutionBgOverlay, + alpha: 0, + duration: 250 + }); + this.evolutionBg.setVisible(true); + this.evolutionBg.play(); + }); + this.scene.sound.play('charge'); + this.doSpiralUpward(); + this.scene.tweens.addCounter({ + from: 0, + to: 1, + duration: 2000, + onUpdate: t => { + this.pokemonTintSprite.setAlpha(t.getValue()); + }, + onComplete: () => { + this.pokemonSprite.setVisible(false); + this.scene.time.delayedCall(1100, () => { + this.scene.sound.play('beam'); + this.doArcDownward(); + this.scene.time.delayedCall(1500, () => { + this.pokemonEvoTintSprite.setScale(0.25); + this.pokemonEvoTintSprite.setVisible(true); + this.doCycle(1).then(() => { + this.scene.sound.play('sparkle'); + this.pokemonEvoSprite.setVisible(true); + this.doCircleInward(); + this.scene.time.delayedCall(900, () => { + this.scene.sound.play('shine'); + this.doSpray(); + this.scene.tweens.add({ + targets: this.evolutionOverlay, + alpha: 1, + duration: 250, + easing: 'Sine.easeIn', + onComplete: () => { + this.evolutionBgOverlay.setAlpha(1); + this.evolutionBg.setVisible(false); + this.scene.tweens.add({ + targets: [ this.evolutionOverlay, this.pokemonEvoTintSprite ], + alpha: 0, + duration: 2000, + delay: 150, + easing: 'Sine.easeIn', + onComplete: () => { + this.scene.tweens.add({ + targets: this.evolutionBgOverlay, + alpha: 0, + duration: 250, + onComplete: () => { + SoundFade.fadeOut(this.scene, evolutionBgm, 100); + this.scene.time.delayedCall(250, () => { + pokemon.cry(); + this.scene.time.delayedCall(1250, () => { + this.scene.sound.play('evolution_fanfare'); + this.scene.ui.showText(`Congratulations! Your ${preName}\nevolved into ${pokemon.name}!`, null, () => this.end(), null, true, 3000); + this.scene.time.delayedCall(4250, () => this.scene.playBgm()); + }); + }); + } + }); + } + }); + } + }) + }); + }); + }); + }); + } + }) + } + }); + }); + }, 1000); + }); + } + + sin(index: integer, amplitude: integer): number { + return amplitude * Math.sin(index * (Math.PI / 128)); + } + + cos(index: integer, amplitude: integer): number { + return amplitude * Math.cos(index * (Math.PI / 128)); + } + + doSpiralUpward() { + let f = 0; + + this.scene.tweens.addCounter({ + repeat: 64, + duration: 1, + useFrames: true, + onRepeat: () => { + if (f < 64) { + if (!(f & 7)) { + for (let i = 0; i < 4; i++) + this.doSpiralUpwardParticle((f & 120) * 2 + i * 64); + } + f++; + } + } + }); + } + + doArcDownward() { + let f = 0; + + this.scene.tweens.addCounter({ + repeat: 96, + duration: 1, + useFrames: true, + onRepeat: () => { + if (f < 96) { + if (f < 6) { + for (let i = 0; i < 9; i++) + this.doArcDownParticle(i * 16); + } + f++; + } + } + }); + } + + doCycle(l: number): Promise { + return new Promise(resolve => { + const isLastCycle = l === 15; + this.scene.tweens.add({ + targets: this.pokemonTintSprite, + scale: 0.25, + ease: 'Cubic.easeInOut', + duration: 500 / l, + yoyo: !isLastCycle + }); + this.scene.tweens.add({ + targets: this.pokemonEvoTintSprite, + scale: 1, + ease: 'Cubic.easeInOut', + duration: 500 / l, + yoyo: !isLastCycle, + onComplete: () => { + if (l < 15) + this.doCycle(l + 0.5).then(() => resolve()); + else { + this.pokemonTintSprite.setVisible(false); + resolve(); + } + } + }); + }); + } + + doCircleInward() { + let f = 0; + + this.scene.tweens.addCounter({ + repeat: 48, + duration: 1, + useFrames: true, + onRepeat: () => { + if (!f) { + for (let i = 0; i < 16; i++) + this.doCircleInwardParticle(i * 16, 4); + } else if (f === 32) { + for (let i = 0; i < 16; i++) + this.doCircleInwardParticle(i * 16, 8); + } + f++; + } + }); + } + + doSpray() { + let f = 0; + + this.scene.tweens.addCounter({ + repeat: 48, + duration: 1, + useFrames: true, + onRepeat: () => { + if (!f) { + for (let i = 0; i < 8; i++) + this.doSprayParticle(i); + } else if (f < 50) + this.doSprayParticle(Utils.randInt(8)); + f++; + } + }); + } + + doSpiralUpwardParticle(trigIndex: integer) { + const initialX = this.evolutionBaseBg.displayWidth / 2; + const particle = this.scene.add.image(initialX, 0, 'evo_sparkle'); + this.evolutionContainer.add(particle); + + let f = 0; + let amp = 48; + + const particleTimer = this.scene.tweens.addCounter({ + repeat: -1, + duration: 1, + useFrames: true, + onRepeat: () => { + updateParticle(); + } + }); + + const updateParticle = () => { + if (!f || particle.y > 8) { + particle.setPosition(initialX, 88 - (f * f) / 80); + particle.y += this.sin(trigIndex, amp) / 4; + particle.x += this.cos(trigIndex, amp); + particle.setScale(1 - (f / 80)); + trigIndex += 4; + if (f & 1) + amp--; + f++; + } else { + particle.destroy(); + particleTimer.remove(); + } + }; + + updateParticle(); + } + + doArcDownParticle(trigIndex: integer) { + const initialX = this.evolutionBaseBg.displayWidth / 2; + const particle = this.scene.add.image(initialX, 0, 'evo_sparkle'); + particle.setScale(0.5); + this.evolutionContainer.add(particle); + + let f = 0; + let amp = 8; + + const particleTimer = this.scene.tweens.addCounter({ + repeat: -1, + duration: 1, + useFrames: true, + onRepeat: () => { + updateParticle(); + } + }); + + const updateParticle = () => { + if (!f || particle.y < 88) { + particle.setPosition(initialX, 8 + (f * f) / 5); + particle.y += this.sin(trigIndex, amp) / 4; + particle.x += this.cos(trigIndex, amp); + amp = 8 + this.sin(f * 4, 40); + f++; + } else { + particle.destroy(); + particleTimer.remove(); + } + }; + + updateParticle(); + } + + doCircleInwardParticle(trigIndex: integer, speed: integer) { + const initialX = this.evolutionBaseBg.displayWidth / 2; + const initialY = this.evolutionBaseBg.displayHeight / 2; + const particle = this.scene.add.image(initialX, initialY, 'evo_sparkle'); + this.evolutionContainer.add(particle); + + let amp = 120; + + const particleTimer = this.scene.tweens.addCounter({ + repeat: -1, + duration: 1, + useFrames: true, + onRepeat: () => { + updateParticle(); + } + }); + + const updateParticle = () => { + if (amp > 8) { + particle.setPosition(initialX, initialY); + particle.y += this.sin(trigIndex, amp); + particle.x += this.cos(trigIndex, amp); + amp -= speed; + trigIndex += 4; + } else { + particle.destroy(); + particleTimer.remove(); + } + }; + + updateParticle(); + } + + doSprayParticle(trigIndex: integer) { + const initialX = this.evolutionBaseBg.displayWidth / 2; + const initialY = this.evolutionBaseBg.displayHeight / 2; + const particle = this.scene.add.image(initialX, initialY, 'evo_sparkle'); + this.evolutionContainer.add(particle); + + let f = 0; + let yOffset = 0; + let speed = 3 - Utils.randInt(8); + let amp = 48 + Utils.randInt(64); + + const particleTimer = this.scene.tweens.addCounter({ + repeat: -1, + duration: 1, + useFrames: true, + onRepeat: () => { + updateParticle(); + } + }); + + const updateParticle = () => { + if (!(f & 3)) + yOffset++; + if (trigIndex < 128) { + particle.setPosition(initialX + (speed * f) / 3, initialY + yOffset); + particle.y += -this.sin(trigIndex, amp); + if (f > 108) + particle.setScale((1 - (f - 108) / 20)); + trigIndex++; + f++; + } else { + particle.destroy(); + particleTimer.remove(); + } + }; + + updateParticle(); + } +} \ No newline at end of file diff --git a/src/modifier.ts b/src/modifier.ts index 69e0d5830..4456f9ed1 100644 --- a/src/modifier.ts +++ b/src/modifier.ts @@ -342,7 +342,7 @@ export class PokemonLevelIncrementModifier extends ConsumablePokemonModifier { pokemon.levelExp = 0; const scene = pokemon.scene as BattleScene; - scene.unshiftPhase(new LevelUpPhase(scene, scene.getParty().indexOf(pokemon), pokemon.level)); + scene.unshiftPhase(new LevelUpPhase(scene, scene.getParty().indexOf(pokemon), pokemon.level - 1, pokemon.level)); return true; } diff --git a/src/pokemon.ts b/src/pokemon.ts index 62cb94fe0..75401412c 100644 --- a/src/pokemon.ts +++ b/src/pokemon.ts @@ -298,15 +298,23 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return null; } - evolve(evolution: SpeciesEvolution): Promise { - return new Promise(resolve => { - console.log(evolution?.speciesId) - this.species = getPokemonSpecies(evolution.speciesId); - this.loadAssets().then(() => { - this.calculateStats(); - this.updateInfo().then(() => resolve()); - }); - }); + getLevelMoves(startingLevel?: integer): Moves[] { + const ret: Moves[] = []; + const levelMoves = pokemonLevelMoves[this.species.speciesId]; + if (levelMoves) { + if (!startingLevel) + startingLevel = this.level; + for (let lm of levelMoves) { + const level = lm[0]; + if (level < startingLevel) + continue; + else if (level > this.level) + break; + ret.push(lm[1]); + } + } + + return ret; } generateAndPopulateMoveset(): void { @@ -593,7 +601,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { sparkle(): void { if (this.shinySparkle) { this.shinySparkle.play('sparkle'); - this.scene.sound.play('shiny'); + this.scene.sound.play('sparkle'); } } } @@ -631,6 +639,20 @@ export class PlayerPokemon extends Pokemon { } } } + + evolve(evolution: SpeciesEvolution): Promise { + return new Promise(resolve => { + this.species = getPokemonSpecies(evolution.speciesId); + this.name = this.species.name.toUpperCase(); + this.species.generateIconAnim(this.scene as BattleScene); + this.compatibleTms.splice(0, this.compatibleTms.length); + this.generateCompatibleTms(); + this.loadAssets().then(() => { + this.calculateStats(); + this.updateInfo().then(() => resolve()); + }); + }); + } } export class EnemyPokemon extends Pokemon { diff --git a/src/ui/evolution-scene-handler.ts b/src/ui/evolution-scene-handler.ts new file mode 100644 index 000000000..2ef37da5f --- /dev/null +++ b/src/ui/evolution-scene-handler.ts @@ -0,0 +1,28 @@ +import BattleScene from "../battle-scene"; +import { Mode } from "./ui"; +import UiHandler from "./uiHandler"; + +export default class EvolutionSceneHandler extends UiHandler { + public evolutionContainer: Phaser.GameObjects.Container; + + constructor(scene: BattleScene) { + super(scene, Mode.EVOLUTION_SCENE); + } + + setup() { + this.evolutionContainer = this.scene.add.container(0, -this.scene.game.canvas.height / 6); + this.scene.fieldUI.add(this.evolutionContainer); + } + + processInput(keyCode: integer) { + this.scene.ui.getMessageHandler().processInput(keyCode); + } + + setCursor(_cursor: integer): boolean { + return false; + } + + clear() { + this.evolutionContainer.removeAll(true); + } + } \ No newline at end of file diff --git a/src/ui/message-ui-handler.ts b/src/ui/message-ui-handler.ts index 3d7bea076..2d5c9cef8 100644 --- a/src/ui/message-ui-handler.ts +++ b/src/ui/message-ui-handler.ts @@ -16,9 +16,25 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler { this.pendingPrompt = false; } - showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean) { + showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer) { if (delay === null || delay === undefined) delay = 20; + let delayMap = new Map(); + let soundMap = new Map(); + const actionPattern = /@(d|s)\{(.*?)\}/; + let actionMatch: RegExpExecArray; + while ((actionMatch = actionPattern.exec(text))) { + switch (actionMatch[1]) { + case 'd': + delayMap.set(actionMatch.index, parseInt(actionMatch[2])); + break; + case 's': + soundMap.set(actionMatch.index, actionMatch[2]); + break; + } + + text = text.slice(0, actionMatch.index) + text.slice(actionMatch.index + actionMatch[2].length + 4); + } if (this.textTimer) { this.textTimer.remove(); if (this.textCallbackTimer) @@ -26,7 +42,13 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler { }; if (prompt) { const originalCallback = callback; - callback = () => this.showPrompt(originalCallback, callbackDelay); + callback = () => { + const showPrompt = () => this.showPrompt(originalCallback, callbackDelay); + if (promptDelay) + this.scene.time.delayedCall(promptDelay, showPrompt); + else + showPrompt(); + }; } if (delay) { this.clearText(); @@ -35,19 +57,38 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler { this.textTimer = this.scene.time.addEvent({ delay: delay, callback: () => { - this.message.setText(text.slice(0, text.length - this.textTimer.repeatCount)); - if (callback && !this.textTimer.repeatCount) { - if (callbackDelay && !prompt) { - this.textCallbackTimer = this.scene.time.delayedCall(callbackDelay, () => { - if (this.textCallbackTimer) { - this.textCallbackTimer.destroy(); - this.textCallbackTimer = null; - } + const charIndex = text.length - this.textTimer.repeatCount; + const charSound = soundMap.get(charIndex); + const charDelay = delayMap.get(charIndex); + this.message.setText(text.slice(0, charIndex)); + const advance = () => { + if (charSound) + this.scene.sound.play(charSound); + if (callback && !this.textTimer.repeatCount) { + if (callbackDelay && !prompt) { + this.textCallbackTimer = this.scene.time.delayedCall(callbackDelay, () => { + if (this.textCallbackTimer) { + this.textCallbackTimer.destroy(); + this.textCallbackTimer = null; + } + callback(); + }); + } else callback(); - }); - } else - callback(); - } + } + }; + if (charDelay) { + this.textTimer.paused = true; + this.scene.tweens.addCounter({ + duration: charDelay, + useFrames: true, + onComplete: () => { + this.textTimer.paused = false; + advance(); + } + }); + } else + advance(); }, repeat: text.length }); diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index e859e505e..1abaaa998 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -411,6 +411,12 @@ export default class SummaryUiHandler extends UiHandler { extraRowText.setOrigin(0, 1); this.extraMoveRowContainer.add(extraRowText); + if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { + const newMoveTypeIcon = this.scene.add.sprite(0, 0, 'types', Type[this.newMove.type].toLowerCase()); + newMoveTypeIcon.setOrigin(0, 1); + this.extraMoveRowContainer.add(newMoveTypeIcon); + } + this.moveRowsContainer = this.scene.add.container(0, 0); this.movesContainer.add(this.moveRowsContainer); @@ -518,7 +524,24 @@ export default class SummaryUiHandler extends UiHandler { this.pokemon = null; this.cursor = -1; this.newMove = null; - this.moveSelectFunction = null; + if (this.moveSelect) { + this.moveSelect = false; + this.moveSelectFunction = null; + 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; + } + this.hideMoveEffect(true); + } this.summaryContainer.setVisible(false); this.summaryPageContainer.setVisible(false); } diff --git a/src/ui/ui.ts b/src/ui/ui.ts index 94fdc0670..a7333635e 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -10,7 +10,7 @@ import ModifierSelectUiHandler from './modifier-select-ui-handler'; import BallUiHandler from './ball-ui-handler'; import SummaryUiHandler from './summary-ui-handler'; import StarterSelectUiHandler from './starter-select-ui-handler'; -import EvolutionUiHandler from './evolution-ui-handler'; +import EvolutionSceneHandler from './evolution-scene-handler'; export enum Mode { MESSAGE = 0, @@ -21,13 +21,19 @@ export enum Mode { MODIFIER_SELECT, PARTY, SUMMARY, - STARTER_SELECT + STARTER_SELECT, + EVOLUTION_SCENE }; const transitionModes = [ Mode.PARTY, Mode.SUMMARY, Mode.STARTER_SELECT, + Mode.EVOLUTION_SCENE +]; + +const noTransitionModes = [ + Mode.CONFIRM ]; export default class UI extends Phaser.GameObjects.Container { @@ -50,7 +56,8 @@ export default class UI extends Phaser.GameObjects.Container { new ModifierSelectUiHandler(scene), new PartyUiHandler(scene), new SummaryUiHandler(scene), - new StarterSelectUiHandler(scene) + new StarterSelectUiHandler(scene), + new EvolutionSceneHandler(scene) ]; } @@ -79,12 +86,12 @@ export default class UI extends Phaser.GameObjects.Container { this.getHandler().processInput(keyCode); } - showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean): void { + showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer): void { const handler = this.getHandler(); if (handler instanceof MessageUiHandler) - (handler as MessageUiHandler).showText(text, delay, callback, callbackDelay, prompt); + (handler as MessageUiHandler).showText(text, delay, callback, callbackDelay, prompt, promptDelay); else - this.getMessageHandler().showText(text, delay, callback, callbackDelay, prompt); + this.getMessageHandler().showText(text, delay, callback, callbackDelay, prompt, promptDelay); } clearText(): void { @@ -111,20 +118,23 @@ export default class UI extends Phaser.GameObjects.Container { this.scene.sound.play('error'); } - private setModeInternal(mode: Mode, clear: boolean, args: any[]): Promise { + private setModeInternal(mode: Mode, clear: boolean, forceTransition: boolean, args: any[]): Promise { return new Promise(resolve => { - if (this.mode === mode) { + if (this.mode === mode && !forceTransition) { resolve(); return; } const doSetMode = () => { - if (clear) - this.getHandler().clear(); - this.mode = mode; - this.getHandler().show(args); + if (this.mode !== mode) { + if (clear) + this.getHandler().clear(); + this.mode = mode; + this.getHandler().show(args); + } resolve(); }; - if ((transitionModes.indexOf(this.mode) > -1 || transitionModes.indexOf(mode) > -1) && !(this.scene as BattleScene).auto) { + if ((transitionModes.indexOf(this.mode) > -1 || transitionModes.indexOf(mode) > -1) + && (noTransitionModes.indexOf(this.mode) === -1 && noTransitionModes.indexOf(mode) === -1) && !(this.scene as BattleScene).auto) { this.transitioning = true; this.overlay.setAlpha(0); this.overlay.setVisible(true); @@ -153,10 +163,14 @@ export default class UI extends Phaser.GameObjects.Container { } setMode(mode: Mode, ...args: any[]): Promise { - return this.setModeInternal(mode, true, args); + return this.setModeInternal(mode, true, false, args); + } + + setModeForceTransition(mode: Mode, ...args: any[]): Promise { + return this.setModeInternal(mode, true, true, args); } setModeWithoutClear(mode: Mode, ...args: any[]): Promise { - return this.setModeInternal(mode, false, args); + return this.setModeInternal(mode, false, false, args); } } \ No newline at end of file