Add WiP logic for double battles

This commit is contained in:
Flashfyre 2023-05-11 17:45:39 -04:00
parent 0757fd88a4
commit c123119d48
17 changed files with 616 additions and 420 deletions

View File

@ -161,7 +161,7 @@ export class Arena {
this.weather = weather ? new Weather(weather, viaMove ? 5 : 0) : null; this.weather = weather ? new Weather(weather, viaMove ? 5 : 0) : null;
if (this.weather) { if (this.weather) {
this.scene.unshiftPhase(new CommonAnimPhase(this.scene, true, CommonAnim.SUNNY + (weather - 1))); this.scene.unshiftPhase(new CommonAnimPhase(this.scene, true, 0, 0, CommonAnim.SUNNY + (weather - 1)));
this.scene.queueMessage(getWeatherStartMessage(weather)); this.scene.queueMessage(getWeatherStartMessage(weather));
} else } else
this.scene.queueMessage(getWeatherClearMessage(oldWeatherType)); this.scene.queueMessage(getWeatherClearMessage(oldWeatherType));

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
import Phaser from 'phaser'; import Phaser from 'phaser';
import { Biome } from './data/biome'; import { Biome } from './data/biome';
import UI from './ui/ui'; import UI from './ui/ui';
import { EncounterPhase, SummonPhase, CommandPhase, NextEncounterPhase, NewBiomeEncounterPhase, SelectBiomePhase, MessagePhase, CheckLoadPhase } from './battle-phases'; import { EncounterPhase, SummonPhase, NextEncounterPhase, NewBiomeEncounterPhase, SelectBiomePhase, MessagePhase, CheckLoadPhase, TurnInitPhase } from './battle-phases';
import Pokemon, { PlayerPokemon, EnemyPokemon } from './pokemon'; import Pokemon, { PlayerPokemon, EnemyPokemon } from './pokemon';
import PokemonSpecies, { allSpecies, getPokemonSpecies, initSpecies } from './data/pokemon-species'; import PokemonSpecies, { allSpecies, getPokemonSpecies, initSpecies } from './data/pokemon-species';
import * as Utils from './utils'; import * as Utils from './utils';
@ -9,7 +9,6 @@ import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, P
import { PokeballType } from './data/pokeball'; import { PokeballType } from './data/pokeball';
import { Species } from './data/species'; import { Species } from './data/species';
import { initAutoPlay } from './system/auto-play'; import { initAutoPlay } from './system/auto-play';
import { Battle } from './battle';
import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from './data/battle-anims'; import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from './data/battle-anims';
import { BattlePhase } from './battle-phase'; import { BattlePhase } from './battle-phase';
import { initGameSpeed } from './system/game-speed'; import { initGameSpeed } from './system/game-speed';
@ -21,6 +20,7 @@ import { Moves, initMoves } from './data/move';
import { getDefaultModifierTypeForTier, getEnemyModifierTypesForWave } from './modifier/modifier-type'; import { getDefaultModifierTypeForTier, getEnemyModifierTypesForWave } from './modifier/modifier-type';
import AbilityBar from './ui/ability-bar'; import AbilityBar from './ui/ability-bar';
import { BlockItemTheftAbAttr, applyAbAttrs, initAbilities } from './data/ability'; import { BlockItemTheftAbAttr, applyAbAttrs, initAbilities } from './data/ability';
import Battle from './battle';
const enableAuto = true; const enableAuto = true;
const quickStart = false; const quickStart = false;
@ -446,21 +446,35 @@ export default class BattleScene extends Phaser.Scene {
return this.party; return this.party;
} }
getEnemyParty(): EnemyPokemon[] {
return this.getEnemyPokemon() ? [ this.getEnemyPokemon() ] : [];
}
getPlayerPokemon(): PlayerPokemon { getPlayerPokemon(): PlayerPokemon {
return this.getParty()[0]; return this.getParty()[0];
} }
getPlayerField(): PlayerPokemon[] {
const party = this.getParty();
return party.slice(0, Math.min(party.length, this.currentBattle?.double ? 2 : 1));
}
getEnemyPokemon(): EnemyPokemon { getEnemyPokemon(): EnemyPokemon {
return this.currentBattle?.enemyPokemon; return this.currentBattle?.enemyField[0];
}
getEnemyField(): EnemyPokemon[] {
return this.currentBattle?.enemyField || [];
}
getField(): Pokemon[] {
const ret = new Array(4).fill(null);
const playerField = this.getPlayerField();
const enemyField = this.getEnemyField();
ret.splice(0, playerField.length, ...playerField);
ret.splice(2, enemyField.length, ...enemyField);
return ret;
} }
getPokemonById(pokemonId: integer): Pokemon { getPokemonById(pokemonId: integer): Pokemon {
const findInParty = (party: Pokemon[]) => party.find(p => p.id === pokemonId); const findInParty = (party: Pokemon[]) => party.find(p => p.id === pokemonId);
return findInParty(this.getParty()) || findInParty(this.getEnemyParty()); return findInParty(this.getParty()) || findInParty(this.getEnemyField());
} }
reset(): void { reset(): void {
@ -475,7 +489,7 @@ export default class BattleScene extends Phaser.Scene {
for (let p of this.getParty()) for (let p of this.getParty())
p.destroy(); p.destroy();
this.party = []; this.party = [];
for (let p of this.getEnemyParty()) for (let p of this.getEnemyField())
p.destroy(); p.destroy();
this.currentBattle = null; this.currentBattle = null;
@ -493,10 +507,10 @@ export default class BattleScene extends Phaser.Scene {
this.trainer.setPosition(406, 132); this.trainer.setPosition(406, 132);
} }
newBattle(waveIndex?: integer): Battle { newBattle(waveIndex?: integer, double?: boolean): Battle {
if (!waveIndex) { if (!waveIndex) {
if (this.currentBattle) { if (this.currentBattle) {
this.getEnemyPokemon().destroy(); this.getEnemyField().forEach(enemyPokemon => enemyPokemon.destroy());
if (this.currentBattle.waveIndex % 10) if (this.currentBattle.waveIndex % 10)
this.pushPhase(new NextEncounterPhase(this)); this.pushPhase(new NextEncounterPhase(this));
else { else {
@ -509,12 +523,14 @@ export default class BattleScene extends Phaser.Scene {
else { else {
this.arena.playBgm(); this.arena.playBgm();
this.pushPhase(new EncounterPhase(this)); this.pushPhase(new EncounterPhase(this));
this.pushPhase(new SummonPhase(this)); this.pushPhase(new SummonPhase(this, 0));
if (double === undefined || double)
this.pushPhase(new SummonPhase(this, 1));
} }
} }
} }
this.currentBattle = new Battle(waveIndex || ((this.currentBattle?.waveIndex || (startingWave - 1)) + 1)); this.currentBattle = new Battle(waveIndex || ((this.currentBattle?.waveIndex || (startingWave - 1)) + 1), double === undefined || double);
return this.currentBattle; return this.currentBattle;
} }
@ -699,7 +715,7 @@ export default class BattleScene extends Phaser.Scene {
} }
populatePhaseQueue(): void { populatePhaseQueue(): void {
this.phaseQueue.push(new CommandPhase(this)); this.phaseQueue.push(new TurnInitPhase(this));
} }
addModifier(modifier: Modifier, playSound?: boolean, virtual?: boolean): Promise<void> { addModifier(modifier: Modifier, playSound?: boolean, virtual?: boolean): Promise<void> {
@ -828,7 +844,9 @@ export default class BattleScene extends Phaser.Scene {
} }
if (isBoss) if (isBoss)
count = Math.max(count, Math.floor(chances / 2)); count = Math.max(count, Math.floor(chances / 2));
getEnemyModifierTypesForWave(waveIndex, count, this.getEnemyParty()).map(mt => mt.newModifier(this.getEnemyPokemon()).add(this.enemyModifiers, false)); const enemyField = this.getEnemyField();
getEnemyModifierTypesForWave(waveIndex, count, this.getEnemyField())
.map(mt => mt.newModifier(enemyField[enemyField.length === 1 ? 0 : Utils.randInt(enemyField.length)]).add(this.enemyModifiers, false));
this.updateModifiers(false).then(() => resolve()); this.updateModifiers(false).then(() => resolve());
}); });
@ -855,7 +873,7 @@ export default class BattleScene extends Phaser.Scene {
modifiers.splice(modifiers.indexOf(modifier), 1); modifiers.splice(modifiers.indexOf(modifier), 1);
} }
this.updatePartyForModifiers(player ? this.getParty() : this.getEnemyParty()).then(() => { this.updatePartyForModifiers(player ? this.getParty() : this.getEnemyField()).then(() => {
(player ? this.modifierBar : this.enemyModifierBar).updateModifiers(modifiers); (player ? this.modifierBar : this.enemyModifierBar).updateModifiers(modifiers);
if (!player) if (!player)
this.updateWaveCountPosition(); this.updateWaveCountPosition();

View File

@ -1,18 +1,44 @@
import { EnemyPokemon, PlayerPokemon } from "./pokemon"; import { EnemyPokemon, PlayerPokemon, QueuedMove } from "./pokemon";
import { Command } from "./ui/command-ui-handler";
import * as Utils from "./utils"; import * as Utils from "./utils";
export class Battle { export enum BattleTarget {
PLAYER,
PLAYER_2,
ENEMY,
ENEMY_2
}
interface TurnCommand {
command: Command;
cursor?: integer;
move?: QueuedMove;
targetIndex?: integer;
args?: any[];
};
interface TurnCommands {
[key: integer]: TurnCommand
}
export default class Battle {
public waveIndex: integer; public waveIndex: integer;
public enemyLevel: integer; public enemyLevels: integer[];
public enemyPokemon: EnemyPokemon; public enemyField: EnemyPokemon[];
public double: boolean;
public turn: integer; public turn: integer;
public turnCommands: TurnCommands;
public playerParticipantIds: Set<integer> = new Set<integer>(); public playerParticipantIds: Set<integer> = new Set<integer>();
public escapeAttempts: integer = 0; public escapeAttempts: integer = 0;
constructor(waveIndex: integer) { constructor(waveIndex: integer, double: boolean) {
this.waveIndex = waveIndex; this.waveIndex = waveIndex;
this.enemyLevel = this.getLevelForWave(); this.enemyLevels = new Array(double ? 2 : 1).fill(null).map(() => this.getLevelForWave());
this.turn = 1; this.enemyField = [];
this.double = double;
this.turn = 0;
this.incrementTurn();
} }
private getLevelForWave(): number { private getLevelForWave(): number {
@ -31,6 +57,7 @@ export class Battle {
incrementTurn() { incrementTurn() {
this.turn++; this.turn++;
this.turnCommands = Object.fromEntries(Utils.getEnumValues(BattleTarget).map(bt => [ bt, null ]));
} }
addParticipant(playerPokemon: PlayerPokemon): void { addParticipant(playerPokemon: PlayerPokemon): void {

View File

@ -157,7 +157,7 @@ export class TypeImmunityHealAbAttr extends TypeImmunityAbAttr {
if (ret && pokemon.getHpRatio() < 1) { if (ret && pokemon.getHpRatio() < 1) {
const scene = pokemon.scene; const scene = pokemon.scene;
scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.isPlayer(), Math.max(Math.floor(pokemon.getMaxHp() / 4), 1), getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nrestored its HP a little!`), true)); scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.isPlayer(), pokemon.getFieldIndex(), Math.max(Math.floor(pokemon.getMaxHp() / 4), 1), getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nrestored its HP a little!`), true));
return true; return true;
} }
@ -181,7 +181,7 @@ class TypeImmunityStatChangeAbAttr extends TypeImmunityAbAttr {
if (ret) { if (ret) {
cancelled.value = true; cancelled.value = true;
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.isPlayer(), true, [ this.stat ], this.levels)); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(), true, [ this.stat ], this.levels));
} }
return ret; return ret;
@ -406,9 +406,9 @@ export class PostSummonStatChangeAbAttr extends PostSummonAbAttr {
} }
applyPostSummon(pokemon: Pokemon, args: any[]): boolean { applyPostSummon(pokemon: Pokemon, args: any[]): boolean {
const statChangePhase = new StatChangePhase(pokemon.scene, pokemon.isPlayer() === this.selfTarget, this.selfTarget, this.stats, this.levels); const statChangePhase = new StatChangePhase(pokemon.scene, pokemon.isPlayer() === this.selfTarget, pokemon.getFieldIndex(), this.selfTarget, this.stats, this.levels);
if (!this.selfTarget && !pokemon.getOpponent()?.summonData) if (!this.selfTarget && !pokemon.getOpponent(0)?.summonData)
pokemon.scene.pushPhase(statChangePhase); // TODO: This causes the ability bar to be shown at the wrong time pokemon.scene.pushPhase(statChangePhase); // TODO: This causes the ability bar to be shown at the wrong time
else else
pokemon.scene.unshiftPhase(statChangePhase); pokemon.scene.unshiftPhase(statChangePhase);
@ -576,7 +576,7 @@ export class PostTurnAbAttr extends AbAttr {
export class PostTurnSpeedBoostAbAttr extends PostTurnAbAttr { export class PostTurnSpeedBoostAbAttr extends PostTurnAbAttr {
applyPostTurn(pokemon: Pokemon, args: any[]): boolean { applyPostTurn(pokemon: Pokemon, args: any[]): boolean {
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.isPlayer(), true, [ BattleStat.SPD ], 1)); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(), true, [ BattleStat.SPD ], 1));
return true; return true;
} }
} }
@ -594,7 +594,8 @@ export class PostTurnHealAbAttr extends PostTurnAbAttr {
applyPostTurn(pokemon: Pokemon, args: any[]): boolean { applyPostTurn(pokemon: Pokemon, args: any[]): boolean {
if (pokemon.getHpRatio() < 1) { if (pokemon.getHpRatio() < 1) {
const scene = pokemon.scene; const scene = pokemon.scene;
scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.isPlayer(), Math.max(Math.floor(pokemon.getMaxHp() / 16), 1), getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nrestored its HP a little!`), true)); scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.isPlayer(), pokemon.getFieldIndex(),
Math.max(Math.floor(pokemon.getMaxHp() / 16), 1), getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nrestored its HP a little!`), true));
return true; return true;
} }
@ -632,7 +633,7 @@ export class PostWeatherLapseHealAbAttr extends PostWeatherLapseAbAttr {
applyPostWeatherLapse(pokemon: Pokemon, weather: Weather, args: any[]): boolean { applyPostWeatherLapse(pokemon: Pokemon, weather: Weather, args: any[]): boolean {
if (pokemon.getHpRatio() < 1) { if (pokemon.getHpRatio() < 1) {
const scene = pokemon.scene; const scene = pokemon.scene;
scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.isPlayer(), Math.max(Math.floor(pokemon.getMaxHp() / (16 / this.healFactor)), 1), getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nrestored its HP a little!`), true)); scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.isPlayer(), pokemon.getFieldIndex(), Math.max(Math.floor(pokemon.getMaxHp() / (16 / this.healFactor)), 1), getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nrestored its HP a little!`), true));
return true; return true;
} }
@ -988,7 +989,7 @@ function canApplyAttr(pokemon: Pokemon, attr: AbAttr): boolean {
} }
function queueShowAbility(pokemon: Pokemon): void { function queueShowAbility(pokemon: Pokemon): void {
pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.isPlayer())); pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex()));
pokemon.scene.clearPhaseQueueSplice(); pokemon.scene.clearPhaseQueueSplice();
} }
@ -1232,8 +1233,8 @@ export function initAbilities() {
new Ability(Abilities.MAGMA_ARMOR, "Magma Armor", "Prevents the POKéMON from becoming frozen.", 3) new Ability(Abilities.MAGMA_ARMOR, "Magma Armor", "Prevents the POKéMON from becoming frozen.", 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.FREEZE), .attr(StatusEffectImmunityAbAttr, StatusEffect.FREEZE),
new Ability(Abilities.MAGNET_PULL, "Magnet Pull", "Prevents STEEL-type POKéMON from escaping.", 3) new Ability(Abilities.MAGNET_PULL, "Magnet Pull", "Prevents STEEL-type POKéMON from escaping.", 3)
.attr(ArenaTrapAbAttr) /*.attr(ArenaTrapAbAttr)
.condition((pokemon: Pokemon) => pokemon.getOpponent()?.isOfType(Type.STEEL)), .condition((pokemon: Pokemon) => pokemon.getOpponent()?.isOfType(Type.STEEL))*/, // TODO: Rework
new Ability(Abilities.MARVEL_SCALE, "Marvel Scale (N)", "Ups DEFENSE if there is a status problem.", 3), new Ability(Abilities.MARVEL_SCALE, "Marvel Scale (N)", "Ups DEFENSE if there is a status problem.", 3),
new Ability(Abilities.MINUS, "Minus (N)", "Ups SP. ATK if another POKéMON has PLUS or MINUS.", 3), new Ability(Abilities.MINUS, "Minus (N)", "Ups SP. ATK if another POKéMON has PLUS or MINUS.", 3),
new Ability(Abilities.NATURAL_CURE, "Natural Cure (N)", "All status problems heal when it switches out.", 3), new Ability(Abilities.NATURAL_CURE, "Natural Cure (N)", "All status problems heal when it switches out.", 3),

View File

@ -143,8 +143,7 @@ class SpikesTag extends ArenaTrapTag {
super.onAdd(arena); super.onAdd(arena);
const source = arena.scene.getPokemonById(this.sourceId); const source = arena.scene.getPokemonById(this.sourceId);
const target = source.getOpponent(); arena.scene.queueMessage(`${this.getMoveName()} were scattered\nall around ${source.getOpponentDescriptor()}'s feet!`);
arena.scene.queueMessage(`${this.getMoveName()} were scattered\nall around ${target.name}'s feet!`);
} }
activateTrap(pokemon: Pokemon): boolean { activateTrap(pokemon: Pokemon): boolean {
@ -170,15 +169,14 @@ class ToxicSpikesTag extends ArenaTrapTag {
super.onAdd(arena); super.onAdd(arena);
const source = arena.scene.getPokemonById(this.sourceId); const source = arena.scene.getPokemonById(this.sourceId);
const target = source.getOpponent(); arena.scene.queueMessage(`${this.getMoveName()} were scattered\nall around ${source.getOpponentDescriptor()}'s feet!`);
arena.scene.queueMessage(`${this.getMoveName()} were scattered\nall around ${target.name}'s feet!`);
} }
activateTrap(pokemon: Pokemon): boolean { activateTrap(pokemon: Pokemon): boolean {
if (!pokemon.status && (!pokemon.isOfType(Type.FLYING) || pokemon.getTag(BattlerTagType.IGNORE_FLYING) || pokemon.scene.arena.getTag(ArenaTagType.GRAVITY))) { if (!pokemon.status && (!pokemon.isOfType(Type.FLYING) || pokemon.getTag(BattlerTagType.IGNORE_FLYING) || pokemon.scene.arena.getTag(ArenaTagType.GRAVITY))) {
const toxic = this.layers > 1; const toxic = this.layers > 1;
pokemon.scene.unshiftPhase(new ObtainStatusEffectPhase(pokemon.scene, pokemon.isPlayer(), pokemon.scene.unshiftPhase(new ObtainStatusEffectPhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(),
!toxic ? StatusEffect.POISON : StatusEffect.TOXIC, null, `the ${this.getMoveName()}`)); !toxic ? StatusEffect.POISON : StatusEffect.TOXIC, null, `the ${this.getMoveName()}`));
return true; return true;
} }
@ -196,8 +194,7 @@ class StealthRockTag extends ArenaTrapTag {
super.onAdd(arena); super.onAdd(arena);
const source = arena.scene.getPokemonById(this.sourceId); const source = arena.scene.getPokemonById(this.sourceId);
const target = source.getOpponent(); arena.scene.queueMessage(`Pointed stones float in the air\naround ${source.getOpponentDescriptor()}!`);
arena.scene.queueMessage(`Pointed stones float in the air\naround ${target.name}!`);
} }
activateTrap(pokemon: Pokemon): boolean { activateTrap(pokemon: Pokemon): boolean {
@ -242,8 +239,8 @@ export class TrickRoomTag extends ArenaTag {
} }
apply(args: any[]): boolean { apply(args: any[]): boolean {
const speedDelayed = args[0] as Utils.BooleanHolder; const speedReversed = args[0] as Utils.BooleanHolder;
speedDelayed.value = !speedDelayed.value; speedReversed.value = !speedReversed.value;
return true; return true;
} }

View File

@ -831,8 +831,8 @@ export class CommonBattleAnim extends BattleAnim {
export class MoveAnim extends BattleAnim { export class MoveAnim extends BattleAnim {
public move: Moves; public move: Moves;
constructor(move: Moves, user: Pokemon) { constructor(move: Moves, user: Pokemon, targetIndex: integer) {
super(user, getMoveTarget(user, move)); super(user, getMoveTarget(user, targetIndex, move));
this.move = move; this.move = move;
} }
@ -852,7 +852,7 @@ export class MoveChargeAnim extends MoveAnim {
private chargeAnim: ChargeAnim; private chargeAnim: ChargeAnim;
constructor(chargeAnim: ChargeAnim, move: Moves, user: Pokemon) { constructor(chargeAnim: ChargeAnim, move: Moves, user: Pokemon) {
super(move, user); super(move, user, 0);
this.chargeAnim = chargeAnim; this.chargeAnim = chargeAnim;
} }

View File

@ -177,7 +177,7 @@ export class ConfusedTag extends BattlerTag {
onAdd(pokemon: Pokemon): void { onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon); super.onAdd(pokemon);
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), CommonAnim.CONFUSION)); pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(), 0, CommonAnim.CONFUSION));
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' became\nconfused!')); pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' became\nconfused!'));
} }
@ -198,14 +198,14 @@ export class ConfusedTag extends BattlerTag {
if (ret) { if (ret) {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nconfused!')); pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nconfused!'));
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), CommonAnim.CONFUSION)); pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(), 0, CommonAnim.CONFUSION));
if (Utils.randInt(2)) { if (Utils.randInt(2)) {
const atk = pokemon.getBattleStat(Stat.ATK); const atk = pokemon.getBattleStat(Stat.ATK);
const def = pokemon.getBattleStat(Stat.DEF); const def = pokemon.getBattleStat(Stat.DEF);
const damage = Math.ceil(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * ((Utils.randInt(15) + 85) / 100)); const damage = Math.ceil(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * ((Utils.randInt(15) + 85) / 100));
pokemon.scene.queueMessage('It hurt itself in its\nconfusion!'); pokemon.scene.queueMessage('It hurt itself in its\nconfusion!');
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer())); pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex()));
pokemon.damage(damage); pokemon.damage(damage);
(pokemon.scene.getCurrentPhase() as MovePhase).cancel(); (pokemon.scene.getCurrentPhase() as MovePhase).cancel();
} }
@ -245,7 +245,7 @@ export class InfatuatedTag extends BattlerTag {
if (ret) { if (ret) {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` is in love\nwith ${pokemon.scene.getPokemonById(this.sourceId).name}!`)); pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` is in love\nwith ${pokemon.scene.getPokemonById(this.sourceId).name}!`));
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), CommonAnim.ATTRACT)); pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(), 0, CommonAnim.ATTRACT));
if (Utils.randInt(2)) { if (Utils.randInt(2)) {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nimmobilized by love!')); pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nimmobilized by love!'));
@ -282,12 +282,13 @@ export class SeedTag extends BattlerTag {
const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType); const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
if (ret) { if (ret) {
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, !pokemon.isPlayer(), CommonAnim.LEECH_SEED)); const source = pokemon.scene.getPokemonById(this.sourceId);
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, source.isPlayer(), source.getFieldIndex(), pokemon.getFieldIndex(), CommonAnim.LEECH_SEED));
const damage = Math.max(Math.floor(pokemon.getMaxHp() / 8), 1); const damage = Math.max(Math.floor(pokemon.getMaxHp() / 8), 1);
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer())); pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex()));
pokemon.damage(damage); pokemon.damage(damage);
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, !pokemon.isPlayer(), damage, getPokemonMessage(pokemon, '\'s health is\nsapped by LEECH SEED!'), false, true)); pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, !source.isPlayer(), source.getFieldIndex(), damage, getPokemonMessage(pokemon, '\'s health is\nsapped by LEECH SEED!'), false, true));
} }
return ret; return ret;
@ -320,10 +321,10 @@ export class NightmareTag extends BattlerTag {
if (ret) { if (ret) {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is locked\nin a NIGHTMARE!')); pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is locked\nin a NIGHTMARE!'));
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), CommonAnim.CURSE)); // TODO: Update animation type pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(), 0, CommonAnim.CURSE)); // TODO: Update animation type
const damage = Math.ceil(pokemon.getMaxHp() / 4); const damage = Math.ceil(pokemon.getMaxHp() / 4);
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer())); pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex()));
pokemon.damage(damage); pokemon.damage(damage);
} }
@ -344,7 +345,7 @@ export class IngrainTag extends TrappedTag {
const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType); const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
if (ret) if (ret)
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.isPlayer(), Math.floor(pokemon.getMaxHp() / 16), pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(), Math.floor(pokemon.getMaxHp() / 16),
getPokemonMessage(pokemon, ` absorbed\nnutrients with its roots!`), true)); getPokemonMessage(pokemon, ` absorbed\nnutrients with its roots!`), true));
return ret; return ret;
@ -374,7 +375,8 @@ export class AquaRingTag extends BattlerTag {
const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType); const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
if (ret) if (ret)
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.isPlayer(), Math.floor(pokemon.getMaxHp() / 16), `${this.getMoveName()} restored\n${pokemon.name}\'s HP!`, true)); pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(),
Math.floor(pokemon.getMaxHp() / 16), `${this.getMoveName()} restored\n${pokemon.name}\'s HP!`, true));
return ret; return ret;
} }
@ -393,7 +395,7 @@ export class DrowsyTag extends BattlerTag {
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
if (!super.lapse(pokemon, lapseType)) { if (!super.lapse(pokemon, lapseType)) {
pokemon.scene.unshiftPhase(new ObtainStatusEffectPhase(pokemon.scene, pokemon.isPlayer(), StatusEffect.SLEEP)); pokemon.scene.unshiftPhase(new ObtainStatusEffectPhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(), StatusEffect.SLEEP));
return false; return false;
} }
@ -423,10 +425,10 @@ export abstract class DamagingTrapTag extends TrappedTag {
if (ret) { if (ret) {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` is hurt\nby ${this.getMoveName()}!`)); pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` is hurt\nby ${this.getMoveName()}!`));
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), this.commonAnim)); pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(), 0, this.commonAnim));
const damage = Math.ceil(pokemon.getMaxHp() / 16); const damage = Math.ceil(pokemon.getMaxHp() / 16);
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer())); pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex()));
pokemon.damage(damage); pokemon.damage(damage);
} }
@ -541,7 +543,7 @@ export class TruantTag extends BattlerTag {
if (lastMove && lastMove.move !== Moves.NONE) { if (lastMove && lastMove.move !== Moves.NONE) {
(pokemon.scene.getCurrentPhase() as MovePhase).cancel(); (pokemon.scene.getCurrentPhase() as MovePhase).cancel();
pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.isPlayer())); pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex()));
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nloafing around!')); pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nloafing around!'));
} }

View File

@ -54,12 +54,7 @@ export function getBerryPredicate(berryType: BerryType): BerryPredicate {
case BerryType.LUM: case BerryType.LUM:
return (pokemon: Pokemon) => !!pokemon.status || !!pokemon.getTag(BattlerTagType.CONFUSED); return (pokemon: Pokemon) => !!pokemon.status || !!pokemon.getTag(BattlerTagType.CONFUSED);
case BerryType.ENIGMA: case BerryType.ENIGMA:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => !!pokemon.turnData.attacksReceived.filter(a => a.result === MoveResult.SUPER_EFFECTIVE).length;
const opponent = pokemon.getOpponent();
const opponentLastMove = opponent ? opponent.getLastXMoves(1).find(() => true) : null; // TODO: Update so this works even if opponent has fainted
return opponentLastMove && opponentLastMove.turn === pokemon.scene.currentBattle?.turn - 1 && opponentLastMove.result === MoveResult.SUPER_EFFECTIVE;
};
case BerryType.LIECHI: case BerryType.LIECHI:
case BerryType.GANLON: case BerryType.GANLON:
case BerryType.SALAC: case BerryType.SALAC:
@ -83,7 +78,7 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
case BerryType.SITRUS: case BerryType.SITRUS:
case BerryType.ENIGMA: case BerryType.ENIGMA:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.isPlayer(), Math.floor(pokemon.getMaxHp() / 4), getPokemonMessage(pokemon, `'s ${getBerryName(berryType)}\nrestored its HP!`), true)); pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(), Math.floor(pokemon.getMaxHp() / 4), getPokemonMessage(pokemon, `'s ${getBerryName(berryType)}\nrestored its HP!`), true));
}; };
case BerryType.LUM: case BerryType.LUM:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
@ -101,13 +96,13 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
case BerryType.APICOT: case BerryType.APICOT:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
const battleStat = (berryType - BerryType.LIECHI) as BattleStat; const battleStat = (berryType - BerryType.LIECHI) as BattleStat;
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.isPlayer(), true, [ battleStat ], 1)); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(), true, [ battleStat ], 1));
}; };
case BerryType.LANSAT: case BerryType.LANSAT:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
pokemon.addTag(BattlerTagType.CRIT_BOOST); pokemon.addTag(BattlerTagType.CRIT_BOOST);
}; };
case BerryType.STARF: case BerryType.STARF:
return (pokemon: Pokemon) => pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.isPlayer(), true, [ BattleStat.RAND ], 2)); return (pokemon: Pokemon) => pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.isPlayer(), pokemon.getFieldIndex(), true, [ BattleStat.RAND ], 2));
} }
} }

View File

@ -936,7 +936,8 @@ export class HealAttr extends MoveEffectAttr {
} }
addHealPhase(user: Pokemon, healRatio: number) { addHealPhase(user: Pokemon, healRatio: number) {
user.scene.unshiftPhase(new PokemonHealPhase(user.scene, user.isPlayer(), Math.max(Math.floor(user.getMaxHp() * healRatio), 1), getPokemonMessage(user, ' regained\nhealth!'), true, !this.showAnim)); user.scene.unshiftPhase(new PokemonHealPhase(user.scene, user.isPlayer(), user.getFieldIndex(),
Math.max(Math.floor(user.getMaxHp() * healRatio), 1), getPokemonMessage(user, ' regained\nhealth!'), true, !this.showAnim));
} }
} }
@ -977,7 +978,8 @@ export class HitHealAttr extends MoveHitEffectAttr {
} }
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
user.scene.unshiftPhase(new PokemonHealPhase(user.scene, user.isPlayer(), Math.max(Math.floor(user.turnData.damageDealt * this.healRatio), 1), getPokemonMessage(target, ` had its\nenergy drained!`), false, true)); user.scene.unshiftPhase(new PokemonHealPhase(user.scene, user.isPlayer(), user.getFieldIndex(),
Math.max(Math.floor(user.turnData.damageDealt * this.healRatio), 1), getPokemonMessage(target, ` had its\nenergy drained!`), false, true));
return true; return true;
} }
} }
@ -1214,7 +1216,7 @@ export class StatChangeAttr extends MoveEffectAttr {
if (move.chance < 0 || move.chance === 100 || Utils.randInt(100) < move.chance) { if (move.chance < 0 || move.chance === 100 || Utils.randInt(100) < move.chance) {
const levels = this.getLevels(user); const levels = this.getLevels(user);
user.scene.unshiftPhase(new StatChangePhase(user.scene, user.isPlayer() === this.selfTarget, this.selfTarget, this.stats, levels)); user.scene.unshiftPhase(new StatChangePhase(user.scene, user.isPlayer() === this.selfTarget, user.getFieldIndex(), this.selfTarget, this.stats, levels));
return true; return true;
} }
@ -1770,8 +1772,8 @@ export class RandomMovesetMoveAttr extends OverrideMoveEffectAttr {
const moveIndex = moveset.findIndex(m => m.moveId === move.moveId); const moveIndex = moveset.findIndex(m => m.moveId === move.moveId);
user.getMoveQueue().push({ move: move.moveId, ignorePP: this.enemyMoveset }); user.getMoveQueue().push({ move: move.moveId, ignorePP: this.enemyMoveset });
user.scene.unshiftPhase(user.isPlayer() user.scene.unshiftPhase(user.isPlayer()
? new PlayerMovePhase(user.scene, user as PlayerPokemon, moveset[moveIndex], true) ? new PlayerMovePhase(user.scene, user as PlayerPokemon, target.getFieldIndex(), moveset[moveIndex], true)
: new EnemyMovePhase(user.scene, user as EnemyPokemon, moveset[moveIndex], true)); : new EnemyMovePhase(user.scene, user as EnemyPokemon, target.getFieldIndex(), moveset[moveIndex], true));
return true; return true;
} }
@ -1786,8 +1788,8 @@ export class RandomMoveAttr extends OverrideMoveEffectAttr {
const moveId = moveIds[Utils.randInt(moveIds.length)]; const moveId = moveIds[Utils.randInt(moveIds.length)];
user.getMoveQueue().push({ move: moveId, ignorePP: true }); user.getMoveQueue().push({ move: moveId, ignorePP: true });
user.scene.unshiftPhase(user.isPlayer() user.scene.unshiftPhase(user.isPlayer()
? new PlayerMovePhase(user.scene, user as PlayerPokemon, new PokemonMove(moveId, 0, 0, true), true) ? new PlayerMovePhase(user.scene, user as PlayerPokemon, target.getFieldIndex(), new PokemonMove(moveId, 0, 0, true), true)
: new EnemyMovePhase(user.scene, user as EnemyPokemon, new PokemonMove(moveId, 0, 0, true), true)); : new EnemyMovePhase(user.scene, user as EnemyPokemon, target.getFieldIndex(), new PokemonMove(moveId, 0, 0, true), true));
initMoveAnim(moveId).then(() => { initMoveAnim(moveId).then(() => {
loadMoveAnimAssets(user.scene, [ moveId ], true) loadMoveAnimAssets(user.scene, [ moveId ], true)
.then(() => resolve(true)); .then(() => resolve(true));
@ -1824,8 +1826,8 @@ export class CopyMoveAttr extends OverrideMoveEffectAttr {
user.getMoveQueue().push({ move: copiedMove.move, ignorePP: true }); user.getMoveQueue().push({ move: copiedMove.move, ignorePP: true });
user.scene.unshiftPhase(user.isPlayer() user.scene.unshiftPhase(user.isPlayer()
? new PlayerMovePhase(user.scene, user as PlayerPokemon, new PokemonMove(copiedMove.move, 0, 0, true), true) ? new PlayerMovePhase(user.scene, user as PlayerPokemon, target.getFieldIndex(), new PokemonMove(copiedMove.move, 0, 0, true), true)
: new EnemyMovePhase(user.scene, user as EnemyPokemon, new PokemonMove(copiedMove.move, 0, 0, true), true)); : new EnemyMovePhase(user.scene, user as EnemyPokemon, target.getFieldIndex(), new PokemonMove(copiedMove.move, 0, 0, true), true));
return true; return true;
} }
@ -1932,10 +1934,10 @@ export function applyFilteredMoveAttrs(attrFilter: MoveAttrFilter, user: Pokemon
return applyMoveAttrsInternal(attrFilter, user, target, move, args); return applyMoveAttrsInternal(attrFilter, user, target, move, args);
} }
export function getMoveTarget(user: Pokemon, move: Moves): Pokemon { export function getMoveTarget(user: Pokemon, targetIndex: integer, move: Moves): Pokemon {
const moveTarget = allMoves[move].moveTarget; const moveTarget = allMoves[move].moveTarget;
const other = user.getOpponent(); const other = user.getOpponent(targetIndex);
switch (moveTarget) { switch (moveTarget) {
case MoveTarget.USER: case MoveTarget.USER:

View File

@ -100,17 +100,10 @@ export class Weather {
} }
isEffectSuppressed(scene: BattleScene): boolean { isEffectSuppressed(scene: BattleScene): boolean {
const playerPokemon = scene.getPlayerPokemon(); const field = scene.getField().filter(p => p);
const enemyPokemon = scene.getEnemyPokemon();
if (playerPokemon) { for (let pokemon of field) {
const suppressWeatherEffectAbAttr = playerPokemon.getAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr; const suppressWeatherEffectAbAttr = pokemon.getAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr;
if (suppressWeatherEffectAbAttr && (!this.isImmutable() || suppressWeatherEffectAbAttr.affectsImmutable))
return true;
}
if (enemyPokemon) {
const suppressWeatherEffectAbAttr = enemyPokemon.getAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr;
if (suppressWeatherEffectAbAttr && (!this.isImmutable() || suppressWeatherEffectAbAttr.affectsImmutable)) if (suppressWeatherEffectAbAttr && (!this.isImmutable() || suppressWeatherEffectAbAttr.affectsImmutable))
return true; return true;
} }

View File

@ -179,6 +179,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
abstract isPlayer(): boolean; abstract isPlayer(): boolean;
abstract getFieldIndex(): integer;
loadAssets(): Promise<void> { loadAssets(): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
const moveIds = this.getMoveset().map(m => m.getMove().id); const moveIds = this.getMoveset().map(m => m.getMove().id);
@ -496,13 +498,24 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.levelExp = this.exp - getLevelTotalExp(this.level, this.getSpeciesForm().growthRate); this.levelExp = this.exp - getLevelTotalExp(this.level, this.getSpeciesForm().growthRate);
} }
getOpponent(): Pokemon { getOpponent(targetIndex: integer): Pokemon {
const ret = this.isPlayer() ? this.scene.getEnemyPokemon() : this.scene.getPlayerPokemon(); const ret = this.getOpponents()[targetIndex];
if (ret.summonData) if (ret.summonData)
return ret; return ret;
return null; return null;
} }
getOpponents(): Pokemon[] {
return this.isPlayer() ? this.scene.getEnemyField() : this.scene.getPlayerField();
}
getOpponentDescriptor(): string {
const opponents = this.getOpponents();
if (opponents.length === 1)
return opponents[0].name;
return this.isPlayer() ? 'the opposing team' : 'your team';
}
apply(source: Pokemon, battlerMove: PokemonMove): MoveResult { apply(source: Pokemon, battlerMove: PokemonMove): MoveResult {
let result: MoveResult; let result: MoveResult;
const move = battlerMove.getMove(); const move = battlerMove.getMove();
@ -626,9 +639,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.hp = Math.max(this.hp - damage, 0); this.hp = Math.max(this.hp - damage, 0);
if (!this.hp) { if (!this.hp) {
this.scene.pushPhase(new FaintPhase(this.scene, this.isPlayer())); this.scene.pushPhase(new FaintPhase(this.scene, this.isPlayer(), this.getFieldIndex()));
this.resetSummonData(); this.resetSummonData();
this.getOpponent()?.resetBattleSummonData();
} }
} }
@ -946,6 +958,10 @@ export class PlayerPokemon extends Pokemon {
return true; return true;
} }
getFieldIndex(): integer {
return this.scene.getPlayerField().indexOf(this);
}
generateCompatibleTms(): void { generateCompatibleTms(): void {
this.compatibleTms = []; this.compatibleTms = [];
@ -1127,6 +1143,10 @@ export class EnemyPokemon extends Pokemon {
return false; return false;
} }
getFieldIndex(): integer {
return this.scene.getEnemyField().indexOf(this);
}
addToParty() { addToParty() {
const party = this.scene.getParty(); const party = this.scene.getParty();
let ret: PlayerPokemon = null; let ret: PlayerPokemon = null;

View File

@ -21,7 +21,7 @@ interface SystemSaveData {
interface SessionSaveData { interface SessionSaveData {
party: PokemonData[]; party: PokemonData[];
enemyParty: PokemonData[]; enemyField: PokemonData[];
modifiers: PersistentModifierData[]; modifiers: PersistentModifierData[];
enemyModifiers: PersistentModifierData[]; enemyModifiers: PersistentModifierData[];
arena: ArenaData; arena: ArenaData;
@ -126,7 +126,7 @@ export class GameData {
saveSession(scene: BattleScene): boolean { saveSession(scene: BattleScene): boolean {
const sessionData = { const sessionData = {
party: scene.getParty().map(p => new PokemonData(p)), party: scene.getParty().map(p => new PokemonData(p)),
enemyParty: scene.getEnemyParty().map(p => new PokemonData(p)), enemyField: scene.getEnemyField().map(p => new PokemonData(p)),
modifiers: scene.findModifiers(m => true).map(m => new PersistentModifierData(m, true)), modifiers: scene.findModifiers(m => true).map(m => new PersistentModifierData(m, true)),
enemyModifiers: scene.findModifiers(m => true, false).map(m => new PersistentModifierData(m, false)), enemyModifiers: scene.findModifiers(m => true, false).map(m => new PersistentModifierData(m, false)),
arena: new ArenaData(scene.arena), arena: new ArenaData(scene.arena),
@ -188,16 +188,19 @@ export class GameData {
party.push(pokemon); party.push(pokemon);
} }
const enemyPokemon = sessionData.enemyParty[0].toPokemon(scene) as EnemyPokemon;
Object.keys(scene.pokeballCounts).forEach((key: string) => { Object.keys(scene.pokeballCounts).forEach((key: string) => {
scene.pokeballCounts[key] = sessionData.pokeballCounts[key] || 0; scene.pokeballCounts[key] = sessionData.pokeballCounts[key] || 0;
}); });
scene.newArena(sessionData.arena.biome, true); scene.newArena(sessionData.arena.biome, sessionData.enemyField.length > 1);
scene.newBattle(sessionData.waveIndex).enemyPokemon = enemyPokemon; const battle = scene.newBattle(sessionData.waveIndex, sessionData.enemyField.length > 1);
loadPokemonAssets.push(enemyPokemon.loadAssets()); sessionData.enemyField.forEach((enemyData, e) => {
const enemyPokemon = enemyData.toPokemon(scene) as EnemyPokemon;
battle.enemyField[e] = enemyPokemon;
loadPokemonAssets.push(enemyPokemon.loadAssets());
});
scene.arena.weather = sessionData.arena.weather; scene.arena.weather = sessionData.arena.weather;
// TODO // TODO

View File

@ -37,7 +37,7 @@ export default class ModifierData {
type.generatorId = this.typeGeneratorId; type.generatorId = this.typeGeneratorId;
if (type instanceof ModifierTypeGenerator) if (type instanceof ModifierTypeGenerator)
type = (type as ModifierTypeGenerator).generateType(this.player ? scene.getParty() : scene.getEnemyParty(), this.typePregenArgs); type = (type as ModifierTypeGenerator).generateType(this.player ? scene.getParty() : scene.getEnemyField(), this.typePregenArgs);
const ret = Reflect.construct(constructor, ([ type ] as any[]).concat(this.args).concat(this.stackCount)) as PersistentModifier const ret = Reflect.construct(constructor, ([ type ] as any[]).concat(this.args).concat(this.stackCount)) as PersistentModifier

View File

@ -43,7 +43,7 @@ export default class CommandUiHandler extends UiHandler {
const messageHandler = this.getUi().getMessageHandler(); const messageHandler = this.getUi().getMessageHandler();
messageHandler.bg.setTexture('bg_command'); messageHandler.bg.setTexture('bg_command');
messageHandler.message.setWordWrapWidth(1110); messageHandler.message.setWordWrapWidth(1110);
messageHandler.showText(`What will\n${this.scene.getPlayerPokemon().name} do?`, 0); messageHandler.showText(`What will\n${(this.scene.getCurrentPhase() as CommandPhase).getPokemon().name} do?`, 0);
this.setCursor(this.cursor); this.setCursor(this.cursor);
} }
@ -65,7 +65,7 @@ export default class CommandUiHandler extends UiHandler {
success = true; success = true;
break; break;
case 2: case 2:
ui.setMode(Mode.PARTY, PartyUiMode.SWITCH); ui.setMode(Mode.PARTY, PartyUiMode.SWITCH, (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getFieldIndex());
success = true; success = true;
break; break;
case 3: case 3:

View File

@ -91,7 +91,7 @@ export default class FightUiHandler extends UiHandler {
ui.add(this.cursorObj); ui.add(this.cursorObj);
} }
const moveset = this.scene.getPlayerPokemon().getMoveset(); const moveset = (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getMoveset();
const hasMove = cursor < moveset.length; const hasMove = cursor < moveset.length;
@ -114,7 +114,7 @@ export default class FightUiHandler extends UiHandler {
} }
displayMoves() { displayMoves() {
const moveset = this.scene.getPlayerPokemon().getMoveset(); const moveset = (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getMoveset();
for (let m = 0; m < 4; m++) { for (let m = 0; m < 4; m++) {
const moveText = addTextObject(this.scene, m % 2 === 0 ? 0 : 100, m < 2 ? 0 : 16, '-', TextStyle.WINDOW); const moveText = addTextObject(this.scene, m % 2 === 0 ? 0 : 100, m < 2 ? 0 : 16, '-', TextStyle.WINDOW);
if (m < moveset.length) if (m < moveset.length)

View File

@ -42,6 +42,7 @@ export type PokemonMoveSelectFilter = (pokemonMove: PokemonMove) => string;
export default class PartyUiHandler extends MessageUiHandler { export default class PartyUiHandler extends MessageUiHandler {
private partyUiMode: PartyUiMode; private partyUiMode: PartyUiMode;
private fieldIndex: integer;
private partyContainer: Phaser.GameObjects.Container; private partyContainer: Phaser.GameObjects.Container;
private partySlotsContainer: Phaser.GameObjects.Container; private partySlotsContainer: Phaser.GameObjects.Container;
@ -143,17 +144,19 @@ export default class PartyUiHandler extends MessageUiHandler {
this.partyUiMode = args[0] as PartyUiMode; this.partyUiMode = args[0] as PartyUiMode;
this.fieldIndex = args.length > 1 ? args[1] as integer : -1;
this.partyContainer.setVisible(true); this.partyContainer.setVisible(true);
this.populatePartySlots(); this.populatePartySlots();
this.setCursor(this.cursor < 6 ? this.cursor : 0); this.setCursor(this.cursor < 6 ? this.cursor : 0);
if (args.length > 1 && args[1] instanceof Function) if (args.length > 2 && args[2] instanceof Function)
this.selectCallback = args[1]; this.selectCallback = args[2];
this.selectFilter = args.length > 2 && args[2] instanceof Function this.selectFilter = args.length > 3 && args[3] instanceof Function
? args[2] as PokemonSelectFilter ? args[3] as PokemonSelectFilter
: PartyUiHandler.FilterAll; : PartyUiHandler.FilterAll;
this.moveSelectFilter = args.length > 3 && args[3] instanceof Function this.moveSelectFilter = args.length > 4 && args[4] instanceof Function
? args[3] as PokemonMoveSelectFilter ? args[4] as PokemonMoveSelectFilter
: PartyUiHandler.FilterAllMoves; : PartyUiHandler.FilterAllMoves;
} }
@ -414,7 +417,8 @@ export default class PartyUiHandler extends MessageUiHandler {
if (this.cursor) { if (this.cursor) {
this.options.push(PartyOption.SEND_OUT); this.options.push(PartyOption.SEND_OUT);
if (this.partyUiMode !== PartyUiMode.FAINT_SWITCH if (this.partyUiMode !== PartyUiMode.FAINT_SWITCH
&& this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && (m as SwitchEffectTransferModifier).pokemonId === this.scene.getPlayerPokemon().id)) && this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier
&& (m as SwitchEffectTransferModifier).pokemonId === this.scene.getPlayerField()[this.fieldIndex].id))
this.options.push(PartyOption.PASS_BATON); this.options.push(PartyOption.PASS_BATON);
} }
break; break;