2023-03-28 18:54:52 +00:00
|
|
|
import Phaser from 'phaser';
|
2023-03-31 03:02:35 +00:00
|
|
|
import { Biome, BiomeArena } from './biome';
|
2023-03-28 18:54:52 +00:00
|
|
|
import UI from './ui/ui';
|
2023-04-10 18:12:01 +00:00
|
|
|
import { EncounterPhase, SummonPhase, CommandPhase, NextEncounterPhase, SwitchBiomePhase, NewBiomeEncounterPhase } from './battle-phases';
|
2023-03-28 18:54:52 +00:00
|
|
|
import { PlayerPokemon, EnemyPokemon } from './pokemon';
|
2023-03-29 04:31:25 +00:00
|
|
|
import PokemonSpecies, { allSpecies, getPokemonSpecies } from './pokemon-species';
|
2023-03-28 18:54:52 +00:00
|
|
|
import * as Utils from './utils';
|
2023-04-11 15:04:39 +00:00
|
|
|
import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PartyShareModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ConsumablePokemonMoveModifier } from './modifier';
|
2023-03-28 18:54:52 +00:00
|
|
|
import { PokeballType } from './pokeball';
|
2023-03-29 04:31:25 +00:00
|
|
|
import { Species } from './species';
|
|
|
|
import { initAutoPlay } from './auto-play';
|
2023-03-31 03:02:35 +00:00
|
|
|
import { Battle } from './battle';
|
2023-04-11 23:08:03 +00:00
|
|
|
import { initCommonAnims, loadCommonAnimAssets, populateAnims } from './battle-anims';
|
2023-04-10 18:12:01 +00:00
|
|
|
import { BattlePhase } from './battle-phase';
|
2023-03-28 18:54:52 +00:00
|
|
|
|
2023-04-09 04:22:14 +00:00
|
|
|
const enableAuto = true;
|
|
|
|
|
2023-04-11 04:24:55 +00:00
|
|
|
export enum Button {
|
|
|
|
UP,
|
|
|
|
DOWN,
|
|
|
|
LEFT,
|
|
|
|
RIGHT,
|
|
|
|
ACTION,
|
|
|
|
CANCEL,
|
|
|
|
RANDOM,
|
|
|
|
AUTO,
|
|
|
|
SPEED_UP,
|
|
|
|
SLOW_DOWN
|
|
|
|
}
|
|
|
|
|
2023-03-28 18:54:52 +00:00
|
|
|
export default class BattleScene extends Phaser.Scene {
|
2023-04-09 04:22:14 +00:00
|
|
|
public auto: boolean;
|
|
|
|
public autoSpeed: integer = 1;
|
2023-03-29 04:31:25 +00:00
|
|
|
|
2023-04-10 18:12:01 +00:00
|
|
|
private phaseQueue: BattlePhase[];
|
|
|
|
private phaseQueuePrepend: BattlePhase[];
|
2023-03-28 18:54:52 +00:00
|
|
|
private currentPhase: BattlePhase;
|
|
|
|
public field: Phaser.GameObjects.Container;
|
|
|
|
public fieldUI: Phaser.GameObjects.Container;
|
|
|
|
public arenaBg: Phaser.GameObjects.Image;
|
2023-03-31 20:04:39 +00:00
|
|
|
public arenaBgTransition: Phaser.GameObjects.Image;
|
2023-03-28 18:54:52 +00:00
|
|
|
public arenaPlayer: Phaser.GameObjects.Image;
|
2023-03-31 20:04:39 +00:00
|
|
|
public arenaPlayerTransition: Phaser.GameObjects.Image;
|
2023-03-28 18:54:52 +00:00
|
|
|
public arenaEnemy: Phaser.GameObjects.Image;
|
2023-03-31 20:04:39 +00:00
|
|
|
public arenaEnemyTransition: Phaser.GameObjects.Image;
|
|
|
|
public arenaNextEnemy: Phaser.GameObjects.Image;
|
|
|
|
public arena: BiomeArena;
|
2023-03-28 18:54:52 +00:00
|
|
|
public trainer: Phaser.GameObjects.Sprite;
|
2023-03-31 03:02:35 +00:00
|
|
|
public currentBattle: Battle;
|
2023-04-02 02:59:07 +00:00
|
|
|
public pokeballCounts = Object.fromEntries(Utils.getEnumValues(PokeballType).filter(p => p <= PokeballType.MASTER_BALL).map(t => [ t, 0 ]));
|
2023-03-28 18:54:52 +00:00
|
|
|
private party: PlayerPokemon[];
|
|
|
|
private modifierBar: ModifierBar;
|
2023-04-09 23:15:21 +00:00
|
|
|
private modifiers: PersistentModifier[];
|
2023-03-28 18:54:52 +00:00
|
|
|
public uiContainer: Phaser.GameObjects.Container;
|
|
|
|
public ui: UI;
|
|
|
|
|
2023-04-04 00:47:41 +00:00
|
|
|
//public spritePipeline: SpritePipeline;
|
|
|
|
|
2023-03-28 18:54:52 +00:00
|
|
|
private bgm: Phaser.Sound.BaseSound;
|
|
|
|
|
2023-04-11 04:24:55 +00:00
|
|
|
private buttonKeys: Phaser.Input.Keyboard.Key[][];
|
2023-03-28 18:54:52 +00:00
|
|
|
|
|
|
|
private blockInput: boolean;
|
|
|
|
|
|
|
|
public trainerId: integer = Utils.randInt(65536);
|
|
|
|
public secretId: integer = Utils.randInt(65536);
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
super('battle');
|
|
|
|
|
|
|
|
this.phaseQueue = [];
|
|
|
|
this.phaseQueuePrepend = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
loadImage(key: string, folder: string, filename?: string) {
|
|
|
|
if (!filename)
|
|
|
|
filename = `${key}.png`;
|
|
|
|
this.load.image(key, `images/${folder}/${filename}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
loadAtlas(key: string, folder: string, filenameRoot?: string) {
|
|
|
|
if (!filenameRoot)
|
|
|
|
filenameRoot = key;
|
|
|
|
if (folder)
|
|
|
|
folder += '/';
|
2023-04-10 20:17:25 +00:00
|
|
|
this.load.atlas(key, `images/${folder}${filenameRoot}.png`, `images/${folder}/${filenameRoot}.json`);
|
2023-03-28 18:54:52 +00:00
|
|
|
}
|
|
|
|
|
2023-04-04 00:47:41 +00:00
|
|
|
loadSpritesheet(key: string, folder: string, size: integer, filename?: string) {
|
|
|
|
if (!filename)
|
|
|
|
filename = `${key}.png`;
|
|
|
|
this.load.spritesheet(key, `images/${folder}/${filename}`, { frameWidth: size, frameHeight: size });
|
|
|
|
}
|
|
|
|
|
2023-03-28 18:54:52 +00:00
|
|
|
loadSe(key: string, folder?: string, filenames?: string | string[]) {
|
|
|
|
if (!filenames)
|
|
|
|
filenames = `${key}.wav`;
|
|
|
|
if (!folder)
|
|
|
|
folder = '';
|
|
|
|
else
|
|
|
|
folder += '/';
|
|
|
|
if (!Array.isArray(filenames))
|
|
|
|
filenames = [ filenames ];
|
|
|
|
for (let f of filenames as string[]) {
|
|
|
|
this.load.audio(key, `audio/se/${folder}${f}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
loadBgm(key: string, filename?: string) {
|
|
|
|
if (!filename)
|
|
|
|
filename = `${key}.mp3`;
|
|
|
|
this.load.audio(key, `audio/bgm/${filename}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
preload() {
|
|
|
|
// Load menu images
|
|
|
|
this.loadImage('bg', 'ui');
|
|
|
|
this.loadImage('bg_command', 'ui');
|
|
|
|
this.loadImage('bg_fight', 'ui');
|
|
|
|
this.loadAtlas('prompt', 'ui');
|
|
|
|
this.loadImage('cursor', 'ui');
|
|
|
|
this.loadImage('pbinfo_player', 'ui');
|
|
|
|
this.loadImage('pbinfo_enemy', 'ui');
|
|
|
|
this.loadImage('overlay_lv', 'ui');
|
|
|
|
this.loadAtlas('numbers', 'ui');
|
|
|
|
this.loadAtlas('overlay_hp', 'ui');
|
|
|
|
this.loadImage('overlay_exp', 'ui');
|
|
|
|
this.loadImage('level_up_stats', 'ui');
|
2023-04-02 02:59:07 +00:00
|
|
|
this.loadImage('ball_window', 'ui');
|
2023-03-28 18:54:52 +00:00
|
|
|
this.loadImage('boolean_window', 'ui');
|
|
|
|
|
|
|
|
this.loadImage('party_bg', 'ui');
|
|
|
|
this.loadAtlas('party_slot_main', 'ui');
|
|
|
|
this.loadAtlas('party_slot', 'ui');
|
|
|
|
this.loadImage('party_slot_overlay_lv', 'ui');
|
|
|
|
this.loadImage('party_slot_hp_bar', 'ui');
|
|
|
|
this.loadAtlas('party_slot_hp_overlay', 'ui');
|
|
|
|
this.loadAtlas('party_pb', 'ui');
|
|
|
|
this.loadImage('party_message', 'ui');
|
|
|
|
this.loadImage('party_message_large', 'ui');
|
2023-04-05 12:35:15 +00:00
|
|
|
this.loadImage('party_message_options', 'ui');
|
|
|
|
this.loadImage('party_options_top', 'ui');
|
|
|
|
this.loadImage('party_options_center', 'ui');
|
|
|
|
this.loadImage('party_options_bottom', 'ui');
|
2023-03-28 18:54:52 +00:00
|
|
|
this.loadAtlas('party_cancel', 'ui');
|
|
|
|
|
2023-04-05 12:35:15 +00:00
|
|
|
this.loadImage('summary_bg', 'ui');
|
2023-04-06 14:05:12 +00:00
|
|
|
this.loadImage('summary_overlay_shiny', 'ui');
|
|
|
|
this.loadImage('summary_profile', 'ui');
|
|
|
|
this.loadImage('summary_moves', 'ui');
|
|
|
|
this.loadImage('summary_moves_effect', 'ui');
|
2023-04-07 02:24:13 +00:00
|
|
|
this.loadImage('summary_moves_overlay_row', 'ui');
|
2023-04-09 00:35:45 +00:00
|
|
|
this.loadImage('summary_moves_overlay_pp', 'ui');
|
2023-04-07 02:24:13 +00:00
|
|
|
this.loadAtlas('summary_moves_cursor', 'ui');
|
2023-04-05 12:35:15 +00:00
|
|
|
|
2023-03-28 18:54:52 +00:00
|
|
|
// Load arena images
|
2023-03-31 03:02:35 +00:00
|
|
|
Utils.getEnumValues(Biome).map(at => {
|
|
|
|
const atKey = Biome[at].toLowerCase();
|
2023-03-29 22:55:41 +00:00
|
|
|
this.loadImage(`${atKey}_bg`, 'arenas', `${atKey}_bg.png`);
|
|
|
|
this.loadImage(`${atKey}_a`, 'arenas', `${atKey}_a.png`);
|
|
|
|
this.loadImage(`${atKey}_b`, 'arenas', `${atKey}_b.png`);
|
|
|
|
});
|
2023-03-28 18:54:52 +00:00
|
|
|
|
|
|
|
// Load trainer images
|
|
|
|
this.loadImage('trainer_m', 'trainer');
|
|
|
|
this.loadAtlas('trainer_m_pb', 'trainer');
|
|
|
|
|
|
|
|
// Load pokemon-related images
|
|
|
|
this.loadImage(`pkmn__back__sub`, 'pokemon/back', 'sub.png');
|
|
|
|
this.loadImage(`pkmn__sub`, 'pokemon', 'sub.png');
|
2023-04-11 03:15:06 +00:00
|
|
|
this.loadAtlas('battle_stats', 'effects');
|
2023-04-10 20:52:27 +00:00
|
|
|
this.loadAtlas('shiny', 'effects');
|
2023-04-10 11:59:00 +00:00
|
|
|
this.loadImage('evo_sparkle', 'effects');
|
|
|
|
this.load.video('evo_bg', 'images/effects/evo_bg.mp4', null, false, true);
|
2023-03-28 18:54:52 +00:00
|
|
|
|
|
|
|
this.loadAtlas('pb', '');
|
|
|
|
this.loadAtlas('items', '');
|
2023-04-01 00:19:57 +00:00
|
|
|
this.loadAtlas('types', '');
|
|
|
|
this.loadAtlas('statuses', '');
|
2023-04-09 00:35:45 +00:00
|
|
|
this.loadAtlas('categories', '');
|
2023-03-28 18:54:52 +00:00
|
|
|
|
|
|
|
for (let i = 0; i < 6; i++)
|
|
|
|
this.loadAtlas(`pokemon_icons_${i}`, 'ui');
|
|
|
|
|
|
|
|
this.loadSe('select');
|
|
|
|
this.loadSe('menu_open');
|
|
|
|
this.loadSe('hit');
|
|
|
|
this.loadSe('hit_strong');
|
|
|
|
this.loadSe('hit_weak');
|
2023-04-11 03:15:06 +00:00
|
|
|
this.loadSe('stat_up');
|
|
|
|
this.loadSe('stat_down');
|
2023-03-28 18:54:52 +00:00
|
|
|
this.loadSe('faint');
|
|
|
|
this.loadSe('flee');
|
|
|
|
this.loadSe('exp');
|
|
|
|
this.loadSe('level_up');
|
2023-04-10 17:54:06 +00:00
|
|
|
this.loadSe('sparkle');
|
2023-03-28 18:54:52 +00:00
|
|
|
this.loadSe('restore');
|
2023-04-10 17:54:06 +00:00
|
|
|
this.loadSe('shine');
|
|
|
|
this.loadSe('charge');
|
|
|
|
this.loadSe('beam');
|
2023-03-28 18:54:52 +00:00
|
|
|
this.loadSe('error');
|
|
|
|
|
|
|
|
this.loadSe('pb');
|
|
|
|
this.loadSe('pb_rel');
|
|
|
|
this.loadSe('pb_throw');
|
|
|
|
this.loadSe('pb_bounce_1');
|
|
|
|
this.loadSe('pb_bounce_2');
|
|
|
|
this.loadSe('pb_move');
|
|
|
|
this.loadSe('pb_catch');
|
|
|
|
this.loadSe('pb_lock');
|
|
|
|
|
|
|
|
this.loadBgm('level_up_fanfare');
|
2023-04-10 11:59:00 +00:00
|
|
|
this.loadBgm('evolution');
|
|
|
|
this.loadBgm('evolution_fanfare');
|
2023-04-04 00:47:41 +00:00
|
|
|
|
2023-04-06 15:30:22 +00:00
|
|
|
//this.load.glsl('sprite', 'shaders/sprite.frag');
|
2023-04-04 00:47:41 +00:00
|
|
|
|
|
|
|
populateAnims();
|
2023-03-28 18:54:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
create() {
|
2023-04-11 04:24:55 +00:00
|
|
|
this.setupControls();
|
|
|
|
|
2023-03-28 18:54:52 +00:00
|
|
|
this.load.setBaseURL();
|
|
|
|
|
2023-04-04 00:47:41 +00:00
|
|
|
//this.spritePipeline = (this.renderer as Phaser.Renderer.WebGL.WebGLRenderer).pipelines.get('Sprite') as SpritePipeline;
|
|
|
|
|
2023-04-11 04:24:55 +00:00
|
|
|
this.time.delayedCall(20, () => this.launchBattle());
|
|
|
|
}
|
|
|
|
|
|
|
|
update() {
|
|
|
|
this.checkInput();
|
|
|
|
}
|
|
|
|
|
|
|
|
launchBattle() {
|
2023-03-28 18:54:52 +00:00
|
|
|
const field = this.add.container(0, 0);
|
|
|
|
field.setScale(6);
|
|
|
|
|
|
|
|
this.field = field;
|
|
|
|
|
2023-03-31 20:04:39 +00:00
|
|
|
this.newBiome();
|
2023-03-28 18:54:52 +00:00
|
|
|
|
2023-03-31 20:04:39 +00:00
|
|
|
const biomeKey = this.arena.getBiomeKey();
|
|
|
|
this.arenaBg = this.add.sprite(0, 0, `${biomeKey}_bg`);
|
|
|
|
this.arenaBgTransition = this.add.sprite(0, 0, `${biomeKey}_bg`);
|
|
|
|
this.arenaPlayer = this.add.sprite(340, 20, `${biomeKey}_a`);
|
|
|
|
this.arenaPlayerTransition = this.add.sprite(40, 20, `${biomeKey}_a`);
|
|
|
|
this.arenaEnemy = this.add.sprite(-240, 13, `${biomeKey}_b`);
|
|
|
|
this.arenaNextEnemy = this.add.sprite(-240, 13, `${biomeKey}_b`);
|
2023-03-28 18:54:52 +00:00
|
|
|
|
2023-03-31 20:04:39 +00:00
|
|
|
this.arenaBgTransition.setVisible(false);
|
|
|
|
this.arenaPlayerTransition.setVisible(false);
|
2023-03-28 18:54:52 +00:00
|
|
|
|
2023-03-31 20:04:39 +00:00
|
|
|
[this.arenaBg, this.arenaBgTransition, this.arenaPlayer, this.arenaPlayerTransition, this.arenaEnemy, this.arenaNextEnemy].forEach(a => {
|
2023-03-28 18:54:52 +00:00
|
|
|
a.setOrigin(0, 0);
|
|
|
|
field.add(a);
|
|
|
|
});
|
2023-03-31 20:04:39 +00:00
|
|
|
this.arena.playBgm();
|
2023-03-28 18:54:52 +00:00
|
|
|
|
|
|
|
const fieldUI = this.add.container(0, this.game.canvas.height);
|
2023-04-11 03:15:06 +00:00
|
|
|
fieldUI.setDepth(1);
|
2023-03-28 18:54:52 +00:00
|
|
|
fieldUI.setScale(6);
|
|
|
|
|
|
|
|
this.fieldUI = fieldUI;
|
|
|
|
|
|
|
|
const uiContainer = this.add.container(0, 0);
|
2023-04-11 03:15:06 +00:00
|
|
|
uiContainer.setDepth(2);
|
2023-03-28 18:54:52 +00:00
|
|
|
uiContainer.setScale(6);
|
|
|
|
|
|
|
|
this.uiContainer = uiContainer;
|
|
|
|
|
|
|
|
this.modifiers = [];
|
|
|
|
|
|
|
|
this.modifierBar = new ModifierBar(this);
|
2023-03-29 04:31:25 +00:00
|
|
|
this.add.existing(this.modifierBar);
|
|
|
|
uiContainer.add(this.modifierBar);
|
2023-03-28 18:54:52 +00:00
|
|
|
|
|
|
|
this.party = [];
|
|
|
|
|
2023-03-29 04:31:25 +00:00
|
|
|
let loadPokemonAssets = [];
|
|
|
|
|
2023-04-11 04:24:55 +00:00
|
|
|
const isRandom = this.isButtonPressed(Button.RANDOM); // For testing purposes
|
|
|
|
|
2023-03-28 18:54:52 +00:00
|
|
|
for (let s = 0; s < 3; s++) {
|
2023-04-11 04:24:55 +00:00
|
|
|
const playerSpecies = !isRandom ? getPokemonSpecies(s === 0 ? Species.TORCHIC : s === 1 ? Species.TREECKO : Species.MUDKIP) : this.randomSpecies(5);
|
2023-04-10 17:54:06 +00:00
|
|
|
const playerPokemon = new PlayerPokemon(this, playerSpecies, 5);
|
2023-03-28 18:54:52 +00:00
|
|
|
playerPokemon.setVisible(false);
|
2023-03-29 04:31:25 +00:00
|
|
|
loadPokemonAssets.push(playerPokemon.loadAssets());
|
2023-03-28 18:54:52 +00:00
|
|
|
|
|
|
|
this.party.push(playerPokemon);
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log(this.getPlayerPokemon().species.name, this.getPlayerPokemon().species.speciesId, this.getPlayerPokemon().stats);
|
|
|
|
|
|
|
|
const trainerPbFrameNames = this.anims.generateFrameNames('trainer_m_pb', { zeroPad: 2, start: 1, end: 12 });
|
|
|
|
this.anims.create({
|
|
|
|
key: 'trainer_m_pb',
|
|
|
|
frames: trainerPbFrameNames,
|
|
|
|
frameRate: 16
|
|
|
|
});
|
|
|
|
|
|
|
|
const trainer = this.add.sprite(406, 132, 'trainer_m');
|
|
|
|
trainer.setOrigin(0.5, 1);
|
|
|
|
|
|
|
|
field.add(trainer);
|
|
|
|
|
|
|
|
this.trainer = trainer;
|
|
|
|
|
|
|
|
this.anims.create({
|
|
|
|
key: 'prompt',
|
|
|
|
frames: this.anims.generateFrameNumbers('prompt', { start: 1, end: 4 }),
|
|
|
|
frameRate: 6,
|
|
|
|
repeat: -1,
|
|
|
|
showOnStart: true
|
|
|
|
});
|
|
|
|
|
|
|
|
const ui = new UI(this);
|
|
|
|
this.uiContainer.add(ui);
|
|
|
|
|
|
|
|
this.ui = ui;
|
|
|
|
|
|
|
|
ui.setup();
|
|
|
|
|
2023-04-11 23:08:03 +00:00
|
|
|
Promise.all([ Promise.all(loadPokemonAssets), initCommonAnims().then(() => loadCommonAnimAssets(this, true)) ]).then(() => {
|
2023-04-09 04:22:14 +00:00
|
|
|
if (enableAuto)
|
|
|
|
initAutoPlay.apply(this);
|
2023-04-02 02:59:07 +00:00
|
|
|
|
|
|
|
this.pokeballCounts[PokeballType.POKEBALL] += 5;
|
2023-03-29 04:31:25 +00:00
|
|
|
|
2023-03-31 20:04:39 +00:00
|
|
|
this.newBattle();
|
2023-03-29 04:31:25 +00:00
|
|
|
|
|
|
|
this.shiftPhase();
|
|
|
|
});
|
2023-03-28 18:54:52 +00:00
|
|
|
}
|
|
|
|
|
2023-04-11 04:24:55 +00:00
|
|
|
setupControls() {
|
|
|
|
const keyCodes = Phaser.Input.Keyboard.KeyCodes;
|
|
|
|
const keyConfig = {
|
|
|
|
[Button.UP]: [keyCodes.UP, keyCodes.W],
|
|
|
|
[Button.DOWN]: [keyCodes.DOWN, keyCodes.S],
|
|
|
|
[Button.LEFT]: [keyCodes.LEFT, keyCodes.A],
|
|
|
|
[Button.RIGHT]: [keyCodes.RIGHT, keyCodes.D],
|
|
|
|
[Button.ACTION]: [keyCodes.ENTER, keyCodes.SPACE, keyCodes.Z],
|
|
|
|
[Button.CANCEL]: [keyCodes.BACKSPACE, keyCodes.ESC, keyCodes.X],
|
|
|
|
[Button.RANDOM]: [keyCodes.R],
|
|
|
|
[Button.AUTO]: [keyCodes.F2],
|
|
|
|
[Button.SPEED_UP]: [keyCodes.PLUS],
|
|
|
|
[Button.SLOW_DOWN]: [keyCodes.MINUS]
|
|
|
|
};
|
|
|
|
this.buttonKeys = [];
|
|
|
|
for (let b of Utils.getEnumValues(Button)) {
|
|
|
|
const keys: Phaser.Input.Keyboard.Key[] = [];
|
|
|
|
if (keyConfig.hasOwnProperty(b)) {
|
|
|
|
for (let k of keyConfig[b])
|
|
|
|
keys.push(this.input.keyboard.addKey(k));
|
|
|
|
}
|
|
|
|
this.buttonKeys[b] = keys;
|
|
|
|
}
|
2023-03-28 18:54:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
getParty(): PlayerPokemon[] {
|
|
|
|
return this.party;
|
|
|
|
}
|
|
|
|
|
|
|
|
getPlayerPokemon(): PlayerPokemon {
|
|
|
|
return this.getParty()[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
getEnemyPokemon(): EnemyPokemon {
|
2023-03-31 03:02:35 +00:00
|
|
|
return this.currentBattle.enemyPokemon;
|
2023-03-28 18:54:52 +00:00
|
|
|
}
|
|
|
|
|
2023-03-31 20:04:39 +00:00
|
|
|
newBattle(): Battle {
|
|
|
|
if (this.currentBattle) {
|
|
|
|
console.log(this.getPlayerPokemon(), this.getParty().map(p => p.name), this.getPlayerPokemon().id)
|
|
|
|
|
|
|
|
this.getEnemyPokemon().destroy();
|
|
|
|
if (this.currentBattle.waveIndex % 10)
|
|
|
|
this.unshiftPhase(new NextEncounterPhase(this));
|
|
|
|
else {
|
|
|
|
this.unshiftPhase(new SwitchBiomePhase(this));
|
|
|
|
this.unshiftPhase(new NewBiomeEncounterPhase(this));
|
|
|
|
}
|
|
|
|
} else {
|
2023-04-09 23:15:21 +00:00
|
|
|
//this.pushPhase(new SelectStarterPhase(this));
|
2023-03-31 20:04:39 +00:00
|
|
|
this.pushPhase(new EncounterPhase(this));
|
|
|
|
this.pushPhase(new SummonPhase(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
this.currentBattle = new Battle((this.currentBattle?.waveIndex || 0) + 1);
|
2023-03-31 03:02:35 +00:00
|
|
|
return this.currentBattle;
|
2023-03-28 18:54:52 +00:00
|
|
|
}
|
|
|
|
|
2023-03-31 20:04:39 +00:00
|
|
|
newBiome(): BiomeArena {
|
2023-04-10 17:54:06 +00:00
|
|
|
const biome = this.currentBattle ? Utils.randInt(20) as Biome : Biome.PLAINS;
|
2023-03-31 20:04:39 +00:00
|
|
|
this.arena = new BiomeArena(this, biome, Biome[biome].toLowerCase());
|
|
|
|
return this.arena;
|
2023-03-28 18:54:52 +00:00
|
|
|
}
|
|
|
|
|
2023-03-31 20:04:39 +00:00
|
|
|
randomSpecies(level: integer, fromArenaPool?: boolean): PokemonSpecies {
|
|
|
|
return fromArenaPool
|
|
|
|
? this.arena.randomSpecies(1, level)
|
2023-04-11 04:24:55 +00:00
|
|
|
: getPokemonSpecies(allSpecies[(Utils.randInt(allSpecies.length)) - 1].getSpeciesForLevel(level));
|
2023-03-28 18:54:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
checkInput(): boolean {
|
|
|
|
if (this.blockInput)
|
|
|
|
return;
|
2023-04-11 04:24:55 +00:00
|
|
|
if (this.isButtonPressed(Button.UP))
|
|
|
|
this.ui.processInput(Button.UP);
|
|
|
|
else if (this.isButtonPressed(Button.DOWN))
|
|
|
|
this.ui.processInput(Button.DOWN);
|
|
|
|
else if (this.isButtonPressed(Button.LEFT))
|
|
|
|
this.ui.processInput(Button.LEFT);
|
|
|
|
else if (this.isButtonPressed(Button.RIGHT))
|
|
|
|
this.ui.processInput(Button.RIGHT);
|
|
|
|
else if (this.isButtonPressed(Button.ACTION))
|
|
|
|
this.ui.processInput(Button.ACTION);
|
|
|
|
else if (this.isButtonPressed(Button.CANCEL))
|
|
|
|
this.ui.processInput(Button.CANCEL);
|
2023-04-09 04:22:14 +00:00
|
|
|
else if (enableAuto) {
|
2023-04-11 04:24:55 +00:00
|
|
|
if (this.isButtonPressed(Button.AUTO))
|
2023-04-09 04:22:14 +00:00
|
|
|
this.auto = !this.auto;
|
2023-04-11 04:24:55 +00:00
|
|
|
else if (this.isButtonPressed(Button.SPEED_UP)) {
|
2023-04-09 04:22:14 +00:00
|
|
|
if (this.autoSpeed < 20)
|
|
|
|
this.autoSpeed++;
|
2023-04-11 04:24:55 +00:00
|
|
|
} else if (this.isButtonPressed(Button.SLOW_DOWN)) {
|
2023-04-09 04:22:14 +00:00
|
|
|
if (this.autoSpeed > 1)
|
|
|
|
this.autoSpeed--;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
} else
|
2023-03-28 18:54:52 +00:00
|
|
|
return;
|
|
|
|
this.blockInput = true;
|
|
|
|
this.time.delayedCall(250, () => {
|
|
|
|
this.blockInput = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-04-11 04:24:55 +00:00
|
|
|
isButtonPressed(button: Button): boolean {
|
|
|
|
return this.buttonKeys[button].filter(k => k.isDown).length >= 1;
|
|
|
|
}
|
|
|
|
|
2023-04-10 17:54:06 +00:00
|
|
|
playBgm(bgmName?: string): void {
|
|
|
|
if (!bgmName && this.bgm) {
|
|
|
|
this.bgm.play({
|
|
|
|
volume: 1
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
2023-03-31 20:04:39 +00:00
|
|
|
if (this.bgm && this.bgm.isPlaying)
|
2023-03-28 18:54:52 +00:00
|
|
|
this.bgm.stop();
|
|
|
|
this.bgm = this.sound.add(bgmName, { loop: true });
|
2023-04-11 04:24:55 +00:00
|
|
|
this.bgm.play();
|
2023-03-28 18:54:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pauseBgm(): void {
|
|
|
|
if (this.bgm)
|
|
|
|
this.bgm.pause();
|
|
|
|
}
|
|
|
|
|
|
|
|
resumeBgm(): void {
|
|
|
|
if (this.bgm && this.bgm.isPaused)
|
|
|
|
this.bgm.resume();
|
|
|
|
}
|
|
|
|
|
2023-04-10 17:54:06 +00:00
|
|
|
fadeOutBgm(destroy?: boolean): void {
|
|
|
|
this.arena.fadeOutBgm(500, destroy);
|
|
|
|
}
|
|
|
|
|
2023-03-28 18:54:52 +00:00
|
|
|
getCurrentPhase(): BattlePhase {
|
|
|
|
return this.currentPhase;
|
|
|
|
}
|
|
|
|
|
|
|
|
pushPhase(phase: BattlePhase): void {
|
|
|
|
this.phaseQueue.push(phase);
|
|
|
|
}
|
|
|
|
|
|
|
|
unshiftPhase(phase: BattlePhase): void {
|
|
|
|
this.phaseQueuePrepend.push(phase);
|
|
|
|
}
|
|
|
|
|
|
|
|
clearPhaseQueue(): void {
|
|
|
|
this.phaseQueue.splice(0, this.phaseQueue.length);
|
|
|
|
}
|
|
|
|
|
|
|
|
shiftPhase(): void {
|
|
|
|
if (this.phaseQueuePrepend.length) {
|
|
|
|
while (this.phaseQueuePrepend.length)
|
|
|
|
this.phaseQueue.unshift(this.phaseQueuePrepend.pop());
|
|
|
|
}
|
|
|
|
if (!this.phaseQueue.length)
|
|
|
|
this.populatePhaseQueue();
|
|
|
|
this.currentPhase = this.phaseQueue.shift();
|
|
|
|
this.currentPhase.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
populatePhaseQueue(): void {
|
|
|
|
this.phaseQueue.push(new CommandPhase(this));
|
|
|
|
}
|
|
|
|
|
2023-04-09 23:15:21 +00:00
|
|
|
addModifier(modifier: Modifier, virtual?: boolean): Promise<void> {
|
2023-04-04 22:28:21 +00:00
|
|
|
return new Promise(resolve => {
|
2023-04-09 23:15:21 +00:00
|
|
|
if (modifier instanceof PersistentModifier) {
|
|
|
|
if ((modifier as PersistentModifier).add(this.modifiers, !!virtual) && !virtual)
|
|
|
|
this.sound.play('restore');
|
2023-03-28 18:54:52 +00:00
|
|
|
|
2023-04-09 23:15:21 +00:00
|
|
|
if (!virtual)
|
|
|
|
this.updateModifiers().then(() => resolve());
|
|
|
|
} else if (modifier instanceof ConsumableModifier) {
|
|
|
|
this.sound.play('restore');
|
2023-03-28 18:54:52 +00:00
|
|
|
|
2023-04-09 23:15:21 +00:00
|
|
|
if (modifier instanceof ConsumablePokemonModifier) {
|
|
|
|
for (let p in this.party) {
|
|
|
|
const pokemon = this.party[p];
|
2023-04-04 22:28:21 +00:00
|
|
|
|
2023-04-09 23:15:21 +00:00
|
|
|
const args: any[] = [ pokemon ];
|
|
|
|
if (modifier instanceof PokemonHpRestoreModifier) {
|
|
|
|
const hpRestoreMultiplier = new Utils.IntegerHolder(1);
|
|
|
|
this.applyModifiers(HealingBoosterModifier, hpRestoreMultiplier);
|
|
|
|
args.push(hpRestoreMultiplier.value);
|
|
|
|
}
|
2023-04-11 15:04:39 +00:00
|
|
|
|
2023-04-04 22:28:21 +00:00
|
|
|
if (modifier.shouldApply(args))
|
|
|
|
modifier.apply(args);
|
|
|
|
}
|
2023-04-09 23:15:21 +00:00
|
|
|
|
|
|
|
Promise.allSettled(this.party.map(p => p.updateInfo())).then(() => resolve());
|
|
|
|
} else {
|
|
|
|
const args = [ this ];
|
|
|
|
if (modifier.shouldApply(args))
|
|
|
|
modifier.apply(args);
|
|
|
|
|
|
|
|
resolve();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2023-03-28 18:54:52 +00:00
|
|
|
|
2023-04-11 13:41:11 +00:00
|
|
|
removePartyMemberModifiers(partyMemberIndex: integer): Promise<void> {
|
2023-04-09 23:15:21 +00:00
|
|
|
return new Promise(resolve => {
|
2023-04-11 13:41:11 +00:00
|
|
|
const pokemonId = this.getParty()[partyMemberIndex].id;
|
|
|
|
const modifiersToRemove = this.modifiers.filter(m => (m instanceof PokemonHeldItemModifier) && (m as PokemonHeldItemModifier).pokemonId === pokemonId);
|
|
|
|
for (let m of modifiersToRemove)
|
|
|
|
this.modifiers.splice(this.modifiers.indexOf(m), 1);
|
|
|
|
this.updateModifiers().then(() => resolve());
|
2023-04-09 23:15:21 +00:00
|
|
|
});
|
|
|
|
}
|
2023-04-04 22:28:21 +00:00
|
|
|
|
2023-04-11 13:41:11 +00:00
|
|
|
|
|
|
|
|
2023-04-09 23:15:21 +00:00
|
|
|
updateModifiers(): Promise<void> {
|
|
|
|
return new Promise(resolve => {
|
|
|
|
for (let modifier of this.modifiers) {
|
|
|
|
if (modifier instanceof PersistentModifier)
|
|
|
|
(modifier as PersistentModifier).virtualStackCount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.applyModifiers(PartyShareModifier, this, this.modifiers);
|
|
|
|
|
|
|
|
const modifiers = this.modifiers.slice(0);
|
|
|
|
for (let modifier of modifiers) {
|
|
|
|
if (!modifier.getStackCount())
|
|
|
|
this.modifiers.splice(this.modifiers.indexOf(modifier), 1);
|
2023-03-28 18:54:52 +00:00
|
|
|
}
|
2023-04-04 22:28:21 +00:00
|
|
|
|
2023-04-09 23:15:21 +00:00
|
|
|
this.updatePartyForModifiers().then(() => {
|
|
|
|
this.modifierBar.updateModifiers(this.modifiers);
|
2023-04-04 22:28:21 +00:00
|
|
|
resolve();
|
2023-04-09 23:15:21 +00:00
|
|
|
});
|
2023-04-04 22:28:21 +00:00
|
|
|
});
|
2023-03-28 18:54:52 +00:00
|
|
|
}
|
|
|
|
|
2023-04-11 13:41:11 +00:00
|
|
|
updatePartyForModifiers(): Promise<void> {
|
|
|
|
return new Promise(resolve => {
|
|
|
|
Promise.allSettled(this.party.map(p => {
|
|
|
|
p.calculateStats();
|
|
|
|
return p.updateInfo();
|
|
|
|
})).then(() => resolve());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-03-31 03:02:35 +00:00
|
|
|
getModifier(modifierType: { new(...args: any[]): Modifier }): Modifier {
|
|
|
|
return this.modifiers.find(m => m instanceof modifierType);
|
|
|
|
}
|
|
|
|
|
2023-03-28 18:54:52 +00:00
|
|
|
applyModifiers(modifierType: { new(...args: any[]): Modifier }, ...args: any[]): void {
|
|
|
|
const modifiers = this.modifiers.filter(m => m instanceof modifierType && m.shouldApply(args));
|
|
|
|
for (let modifier of modifiers) {
|
|
|
|
if (modifier.apply(args))
|
|
|
|
console.log('Applied', modifier.type.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|