mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2024-11-25 00:06:18 +00:00
Finish evolution logic and sequence
This commit is contained in:
parent
824106c2a3
commit
5b097b347b
@ -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
|
||||
|
BIN
public/audio/se/beam.wav
Normal file
BIN
public/audio/se/beam.wav
Normal file
Binary file not shown.
BIN
public/audio/se/charge.wav
Normal file
BIN
public/audio/se/charge.wav
Normal file
Binary file not shown.
BIN
public/audio/se/shine.wav
Normal file
BIN
public/audio/se/shine.wav
Normal file
Binary file not shown.
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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<void> {
|
||||
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
445
src/evolution-phase.ts
Normal file
445
src/evolution-phase.ts
Normal file
@ -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<void> {
|
||||
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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -298,15 +298,23 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return null;
|
||||
}
|
||||
|
||||
evolve(evolution: SpeciesEvolution): Promise<void> {
|
||||
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<void> {
|
||||
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 {
|
||||
|
28
src/ui/evolution-scene-handler.ts
Normal file
28
src/ui/evolution-scene-handler.ts
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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<integer, integer>();
|
||||
let soundMap = new Map<integer, string>();
|
||||
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
|
||||
});
|
||||
|
@ -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);
|
||||
}
|
||||
|
44
src/ui/ui.ts
44
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<void> {
|
||||
private setModeInternal(mode: Mode, clear: boolean, forceTransition: boolean, args: any[]): Promise<void> {
|
||||
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<void> {
|
||||
return this.setModeInternal(mode, true, args);
|
||||
return this.setModeInternal(mode, true, false, args);
|
||||
}
|
||||
|
||||
setModeForceTransition(mode: Mode, ...args: any[]): Promise<void> {
|
||||
return this.setModeInternal(mode, true, true, args);
|
||||
}
|
||||
|
||||
setModeWithoutClear(mode: Mode, ...args: any[]): Promise<void> {
|
||||
return this.setModeInternal(mode, false, args);
|
||||
return this.setModeInternal(mode, false, false, args);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user