Add WiP evolution phase

pull/1/head
Flashfyre 2023-04-10 07:59:00 -04:00
parent 15105231ba
commit 824106c2a3
10 changed files with 331 additions and 26 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

View File

@ -101,7 +101,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
}
}
updateInfo(pokemon: Pokemon): Promise<void> {
updateInfo(pokemon: Pokemon, instant?: boolean): Promise<void> {
return new Promise(resolve => {
if (!this.scene) {
resolve();
@ -109,7 +109,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
}
const updatePokemonHp = () => {
const duration = Utils.clampInt(Math.abs((this.lastHp) - pokemon.hp) * 5, 250, 5000);
const duration = !instant ? Utils.clampInt(Math.abs((this.lastHp) - pokemon.hp) * 5, 250, 5000) : 0;
this.scene.tweens.add({
targets: this.hpBar,
ease: 'Sine.easeOut',
@ -154,13 +154,13 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
});
}
updatePokemonExp(battler: Pokemon): Promise<void> {
updatePokemonExp(battler: Pokemon, instant?: boolean): Promise<void> {
return new Promise(resolve => {
const levelUp = this.lastLevel < battler.level;
const relLevelExp = getLevelRelExp(this.lastLevel + 1, battler.species.growthRate);
const levelExp = levelUp ? relLevelExp : battler.levelExp;
let ratio = levelExp / relLevelExp;
let duration = this.visible ? ((levelExp - this.lastLevelExp) / relLevelExp) * 1650 : 0;
let duration = this.visible && !instant ? ((levelExp - this.lastLevelExp) / relLevelExp) * 1650 : 0;
if (duration)
this.scene.sound.play('exp');
this.scene.tweens.add({
@ -191,7 +191,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
this.setLevel(this.lastLevel);
this.scene.time.delayedCall(500, () => {
this.expBar.setScale(0, 1);
this.updateInfo(battler).then(() => resolve());
this.updateInfo(battler, instant).then(() => resolve());
});
return;
} else {

View File

@ -12,6 +12,8 @@ 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";
export class BattlePhase {
protected scene: BattleScene;
@ -1014,6 +1016,277 @@ 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);

View File

@ -1,17 +1,16 @@
import Phaser from 'phaser';
import { Biome, BiomeArena } from './biome';
import UI from './ui/ui';
import { BattlePhase, EncounterPhase, SummonPhase, CommandPhase, NextEncounterPhase, SwitchBiomePhase, NewBiomeEncounterPhase } from './battle-phase';
import { BattlePhase, EncounterPhase, SummonPhase, CommandPhase, NextEncounterPhase, SwitchBiomePhase, NewBiomeEncounterPhase, EvolutionPhase } from './battle-phase';
import { PlayerPokemon, EnemyPokemon } from './pokemon';
import PokemonSpecies, { allSpecies, getPokemonSpecies } from './pokemon-species';
import * as Utils from './utils';
import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PartyShareModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonBaseStatBoosterModifierType, PokemonBaseStatModifier } from './modifier';
import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PartyShareModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier } from './modifier';
import { PokeballType } from './pokeball';
import { Species } from './species';
import { initAutoPlay } from './auto-play';
import { Battle } from './battle';
import { populateAnims } from './battle-anims';
import { Stat } from './pokemon-stat';
const enableAuto = true;
@ -164,6 +163,8 @@ export default class BattleScene extends Phaser.Scene {
this.loadImage(`pkmn__back__sub`, 'pokemon/back', 'sub.png');
this.loadImage(`pkmn__sub`, 'pokemon', 'sub.png');
this.loadAtlas('shiny', 'effects');
this.loadImage('evo_sparkle', 'effects');
this.load.video('evo_bg', 'images/effects/evo_bg.mp4', null, false, true);
this.loadAtlas('pb', '');
this.loadAtlas('items', '');
@ -197,6 +198,8 @@ export default class BattleScene extends Phaser.Scene {
this.loadSe('pb_lock');
this.loadBgm('level_up_fanfare');
this.loadBgm('evolution');
this.loadBgm('evolution_fanfare');
//this.load.glsl('sprite', 'shaders/sprite.frag');
@ -254,7 +257,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, 5);
const playerPokemon = new PlayerPokemon(this, playerSpecies, 16);
playerPokemon.setVisible(false);
loadPokemonAssets.push(playerPokemon.loadAssets());
@ -302,10 +305,6 @@ export default class BattleScene extends Phaser.Scene {
this.plusKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.PLUS);
this.minusKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.MINUS);
for (let a = 0; a < 3; a++) {
this.addModifier(new PokemonBaseStatModifier(new PokemonBaseStatBoosterModifierType('HP-UP', Stat.HP), this.getParty()[0].id, Stat.HP));
}
Promise.all(loadPokemonAssets).then(() => {
if (enableAuto)
initAutoPlay.apply(this);
@ -346,6 +345,7 @@ 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 +356,7 @@ export default class BattleScene extends Phaser.Scene {
}
newBiome(): BiomeArena {
const biome = this.currentBattle ? Utils.randInt(20) as Biome : Biome.PLAINS;
const biome = this.currentBattle ? Utils.randInt(20) as Biome : Biome.LAKE;
this.arena = new BiomeArena(this, biome, Biome[biome].toLowerCase());
return this.arena;
}

View File

@ -36,7 +36,11 @@ export class SpeciesEvolutionCondition {
}
}
export const pokemonEvolutions = {
interface PokemonEvolutions {
[key: string]: SpeciesEvolution[]
}
export const pokemonEvolutions: PokemonEvolutions = {
[Species.BULBASAUR]: [
new SpeciesEvolution(Species.IVYSAUR, 16, null, null)
],

View File

@ -4,7 +4,7 @@ import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from './battle-info';
import { MessagePhase } from './battle-phase';
import { default as Move, allMoves, MoveCategory, Moves } from './move';
import { pokemonLevelMoves } from './pokemon-level-moves';
import { default as PokemonSpecies } from './pokemon-species';
import { default as PokemonSpecies, getPokemonSpecies } from './pokemon-species';
import * as Utils from './utils';
import { getTypeDamageMultiplier } from './type';
import { getLevelTotalExp } from './exp';
@ -15,6 +15,7 @@ import { Gender } from './gender';
import { initAnim, loadMoveAnimAssets } from './battle-anims';
import { StatusEffect } from './status-effect';
import { tmSpecies } from './tms';
import { pokemonEvolutions, SpeciesEvolution, SpeciesEvolutionCondition } from './pokemon-evolutions';
export default abstract class Pokemon extends Phaser.GameObjects.Container {
public id: integer;
@ -241,13 +242,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return this.getAt(2) as Phaser.GameObjects.Sprite;
}
playAnim() {
playAnim(): void{
this.getSprite().play(this.getBattleSpriteKey());
this.getTintSprite().play(this.getBattleSpriteKey());
this.getZoomSprite().play(this.getBattleSpriteKey());
}
calculateStats() {
calculateStats(): void {
if (!this.stats)
this.stats = [ 0, 0, 0, 0, 0, 0 ];
const baseStats = this.species.baseStats.slice(0);
@ -273,15 +274,42 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}
}
getMaxHp() {
getMaxHp(): integer {
return this.stats[Stat.HP];
}
getHpRatio() {
getHpRatio(): number {
return Math.floor((this.hp / this.getMaxHp()) * 100) / 100;
}
generateAndPopulateMoveset() {
getEvolution(): SpeciesEvolution {
if (!pokemonEvolutions.hasOwnProperty(this.species.speciesId))
return null;
const evolutions = pokemonEvolutions[this.species.speciesId];
for (let e of evolutions) {
if (this.level >= e.level) {
// TODO: Remove string conditions
if (e.condition === null || typeof e.condition === 'string' || (e.condition as SpeciesEvolutionCondition).predicate(this))
return e;
}
}
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());
});
});
}
generateAndPopulateMoveset(): void {
this.moveset = [];
const movePool = [];
const allLevelMoves = pokemonLevelMoves[this.species.speciesId];
@ -352,8 +380,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}
}
updateInfo(): Promise<void> {
return this.battleInfo.updateInfo(this);
updateInfo(instant?: boolean): Promise<void> {
return this.battleInfo.updateInfo(this, instant);
}
addExp(exp: integer) {
@ -669,10 +697,9 @@ export class EnemyPokemon extends Pokemon {
const scoreB = moveScores[movePool.indexOf(b)];
return scoreA < scoreB ? 1 : scoreA > scoreB ? -1 : 0;
});
let randInt: integer;
let r = 0;
if (this.aiType === AiType.SMART_RANDOM) {
while (r < sortedMovePool.length - 1 && (randInt = Utils.randInt(8)) >= 5)
while (r < sortedMovePool.length - 1 && Utils.randInt(8) >= 5)
r++;
}
console.log(movePool.map(m => m.getName()), moveScores, r, sortedMovePool.map(m => m.getName()));

View File

@ -10,6 +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';
export enum Mode {
MESSAGE = 0,
@ -20,7 +21,7 @@ export enum Mode {
MODIFIER_SELECT,
PARTY,
SUMMARY,
STARTER_SELECT,
STARTER_SELECT
};
const transitionModes = [