diff --git a/src/battle-phases.ts b/src/battle-phases.ts index f112df3fdaf..771159346af 100644 --- a/src/battle-phases.ts +++ b/src/battle-phases.ts @@ -75,7 +75,7 @@ export class CheckLoadPhase extends BattlePhase { this.scene.pushPhase(new EncounterPhase(this.scene, this.loaded)); this.scene.pushPhase(new SummonPhase(this.scene, 0)); - if (this.scene.currentBattle.double) + if (this.scene.currentBattle.double && this.scene.getParty().filter(p => !p.isFainted()).length > 1) this.scene.pushPhase(new SummonPhase(this.scene, 1)); super.end(); @@ -320,10 +320,6 @@ export class NextEncounterPhase extends EncounterPhase { this.scene.unshiftPhase(new ShinySparklePhase(this.scene, BattlerIndex.ENEMY + e)); }); - this.scene.unshiftPhase(new CheckSwitchPhase(this.scene, 0)); - if (this.scene.currentBattle.double) - this.scene.unshiftPhase(new CheckSwitchPhase(this.scene, 1)); - super.end(); } } @@ -475,34 +471,35 @@ export class SummonPhase extends PartyMemberPokemonPhase { const playerPokemon = this.getPokemon(); - if (this.fieldIndex === 1) { - this.scene.getPlayerField()[0].setFieldPosition(FieldPosition.LEFT, 250); + if (this.fieldIndex === 1) playerPokemon.setFieldPosition(FieldPosition.RIGHT, 0); - } else + else playerPokemon.setFieldPosition(!this.scene.currentBattle.double ? FieldPosition.CENTER : FieldPosition.LEFT); - const xOffset = playerPokemon.getFieldPositionOffset()[0]; + const fpOffset = playerPokemon.getFieldPositionOffset(); + + console.log(fpOffset); pokeball.setVisible(true); this.scene.tweens.add({ targets: pokeball, duration: 650, - x: 100 + xOffset + x: 100 + fpOffset[0] }); this.scene.tweens.add({ targets: pokeball, duration: 150, ease: 'Cubic.easeOut', - y: 70, + y: 70 + fpOffset[1], onComplete: () => { this.scene.tweens.add({ targets: pokeball, duration: 500, ease: 'Cubic.easeIn', angle: 1440, - y: 132, + y: 132 + fpOffset[1], onComplete: () => { this.scene.sound.play('pb_rel'); pokeball.destroy(); @@ -565,10 +562,6 @@ export class SwitchSummonPhase extends SummonPhase { this.batonPass = batonPass; } - start() { - super.start(); - } - preSummon(): void { if (!this.doReturn) { this.switchAndSummon(); @@ -619,12 +612,48 @@ export class SwitchSummonPhase extends SummonPhase { if (this.batonPass) this.getPokemon().transferSummon(this.lastPokemon); - this.lastPokemon.resetSummonData(); + this.lastPokemon?.resetSummonData(); super.end(); } } +export class ReturnPhase extends SwitchSummonPhase { + constructor(scene: BattleScene, fieldIndex: integer) { + super(scene, fieldIndex, -1, true, false); + } + + switchAndSummon(): void { + this.end(); + } + + summon(): void { } +} + +export class ToggleDoublePositionPhase extends BattlePhase { + private double: boolean; + + constructor(scene: BattleScene, double: boolean) { + super(scene); + + this.double = double; + } + + start() { + super.start(); + + const playerPokemon = this.scene.getPlayerPokemon(); + playerPokemon.setFieldPosition(this.double ? FieldPosition.LEFT : FieldPosition.CENTER, 500).then(() => { + if (!this.double && playerPokemon.getFieldIndex() === 1) { + const party = this.scene.getParty(); + party[1] = party[0]; + party[0] = playerPokemon; + } + this.end(); + }); + } +} + export class CheckSwitchPhase extends BattlePhase { protected fieldIndex: integer; @@ -788,8 +817,13 @@ export class CommandPhase extends FieldPhase { this.scene.ui.setMode(Mode.COMMAND); }, null, true); } else if (cursor < 4) { + const targets = this.scene.getEnemyField().filter(p => p.isActive()).map(p => p.getBattlerIndex()); this.scene.currentBattle.turnCommands[this.fieldIndex] = { command: Command.BALL, cursor: cursor }; - this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)) + this.scene.currentBattle.turnPokeballCounts[cursor as PokeballType]--; + if (targets.length > 1) + this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); + else + this.scene.currentBattle.turnCommands[this.fieldIndex].targets = targets; success = true; } break; @@ -859,14 +893,17 @@ export class SelectTargetPhase extends PokemonPhase { start() { super.start(); - const move = this.scene.currentBattle.turnCommands[this.fieldIndex].move?.move; + const turnCommand = this.scene.currentBattle.turnCommands[this.fieldIndex]; + const move = turnCommand.move?.move; this.scene.ui.setMode(Mode.TARGET_SELECT, this.fieldIndex, move, (cursor: integer) => { this.scene.ui.setMode(Mode.MESSAGE); if (cursor === -1) { + if (turnCommand.command === Command.BALL) + this.scene.currentBattle.turnPokeballCounts[turnCommand.cursor]++; this.scene.currentBattle.turnCommands[this.fieldIndex] = null; this.scene.unshiftPhase(new CommandPhase(this.scene, this.fieldIndex)); } else - this.scene.currentBattle.turnCommands[this.fieldIndex].targets = [ cursor ]; + turnCommand.targets = [ cursor ]; this.end(); }); } @@ -965,7 +1002,7 @@ export class TurnEndPhase extends FieldPhase { start() { super.start(); - this.scene.currentBattle.incrementTurn(); + this.scene.currentBattle.incrementTurn(this.scene); const handlePokemon = (pokemon: Pokemon) => { pokemon.lapseTags(BattlerTagLapseType.TURN_END); @@ -1001,10 +1038,6 @@ export class TurnEndPhase extends FieldPhase { } export class BattleEndPhase extends BattlePhase { - constructor(scene: BattleScene) { - super(scene); - } - start() { super.start(); @@ -1025,6 +1058,16 @@ export class BattleEndPhase extends BattlePhase { } } +export class NewBattlePhase extends BattlePhase { + start() { + super.start(); + + this.scene.newBattle(); + + this.end(); + } +} + export class CommonAnimPhase extends PokemonPhase { private anim: CommonAnim; private targetIndex: integer; @@ -1331,7 +1374,7 @@ class MoveEffectPhase extends PokemonPhase { } getTargets(): Pokemon[] { - return this.scene.getField().filter(p => this.targets.indexOf(p.getBattlerIndex()) > -1); + return this.scene.getField().filter(p => p?.isActive() && this.targets.indexOf(p.getBattlerIndex()) > -1); } getTarget(): Pokemon { @@ -1789,7 +1832,7 @@ export class VictoryPhase extends PokemonPhase { this.scene.pushPhase(new BattleEndPhase(this.scene)); if (this.scene.currentBattle.waveIndex < this.scene.finalWave) { this.scene.pushPhase(new SelectModifierPhase(this.scene)); - this.scene.newBattle(); + this.scene.pushPhase(new NewBattlePhase(this.scene)); } else this.scene.pushPhase(new GameOverPhase(this.scene, true)); } @@ -2330,7 +2373,7 @@ export class AttemptRunPhase extends PokemonPhase { enemyField.forEach(enemyPokemon => enemyPokemon.hp = 0); this.scene.pushPhase(new BattleEndPhase(this.scene)); - this.scene.newBattle(); + this.scene.pushPhase(new NewBattlePhase(this.scene)); } else this.scene.queueMessage('You can\'t escape!', null, true); @@ -2350,7 +2393,7 @@ export class SelectModifierPhase extends BattlePhase { regenerateModifierPoolThresholds(party); const modifierCount = new Utils.IntegerHolder(3); this.scene.applyModifiers(ExtraModifierModifier, true, modifierCount); - const typeOptions: Array = getPlayerModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex - 1, modifierCount.value, party); + const typeOptions: Array = getPlayerModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, modifierCount.value, party); const modifierSelectCallback = (cursor: integer) => { if (cursor < 0) { diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 771272167e4..4a5512caf16 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1,8 +1,8 @@ import Phaser from 'phaser'; import { Biome } from './data/biome'; import UI from './ui/ui'; -import { EncounterPhase, SummonPhase, NextEncounterPhase, NewBiomeEncounterPhase, SelectBiomePhase, MessagePhase, CheckLoadPhase, TurnInitPhase } from './battle-phases'; -import Pokemon, { PlayerPokemon, EnemyPokemon } from './pokemon'; +import { EncounterPhase, SummonPhase, NextEncounterPhase, NewBiomeEncounterPhase, SelectBiomePhase, MessagePhase, CheckLoadPhase, TurnInitPhase, ReturnPhase, ToggleDoublePositionPhase, CheckSwitchPhase } from './battle-phases'; +import Pokemon, { PlayerPokemon, EnemyPokemon, FieldPosition } from './pokemon'; import PokemonSpecies, { allSpecies, getPokemonSpecies, initSpecies } from './data/pokemon-species'; import * as Utils from './utils'; import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate } from './modifier/modifier'; @@ -510,10 +510,21 @@ export default class BattleScene extends Phaser.Scene { } newBattle(waveIndex?: integer, double?: boolean): Battle { + double = (waveIndex || ((this.currentBattle?.waveIndex || (startingWave - 1)) + 1)) % 2 === 0; + + const isDouble = double === undefined || double; + + console.log(this.currentBattle?.waveIndex); + + const lastBattle = this.currentBattle; + + this.currentBattle = new Battle(waveIndex || ((this.currentBattle?.waveIndex || (startingWave - 1)) + 1), isDouble); + this.currentBattle.incrementTurn(this); + if (!waveIndex) { - if (this.currentBattle) { + if (lastBattle) { this.getEnemyField().forEach(enemyPokemon => enemyPokemon.destroy()); - if (this.currentBattle.waveIndex % 10) + if (lastBattle.waveIndex % 10) this.pushPhase(new NextEncounterPhase(this)); else { this.pushPhase(new SelectBiomePhase(this)); @@ -526,13 +537,28 @@ export default class BattleScene extends Phaser.Scene { this.arena.playBgm(); this.pushPhase(new EncounterPhase(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), double === undefined || double); + if ((lastBattle?.double || false) !== isDouble) { + const availablePartyMemberCount = this.getParty().filter(p => !p.isFainted()).length; + if (isDouble) { + this.pushPhase(new ToggleDoublePositionPhase(this, true)); + if (availablePartyMemberCount > 1) + this.pushPhase(new SummonPhase(this, 1)); + } else { + if (availablePartyMemberCount > 1) + this.pushPhase(new ReturnPhase(this, 1)); + this.pushPhase(new ToggleDoublePositionPhase(this, false)); + } + } + + if (lastBattle) { + this.pushPhase(new CheckSwitchPhase(this, 0)); + if (lastBattle.double && isDouble) + this.pushPhase(new CheckSwitchPhase(this, 1)); + } + } return this.currentBattle; } @@ -875,7 +901,7 @@ export default class BattleScene extends Phaser.Scene { modifiers.splice(modifiers.indexOf(modifier), 1); } - this.updatePartyForModifiers(player ? this.getParty() : this.getEnemyField()).then(() => { + this.updatePartyForModifiers(player ? this.getParty() : this.getEnemyField().filter(p => p.isActive())).then(() => { (player ? this.modifierBar : this.enemyModifierBar).updateModifiers(modifiers); if (!player) this.updateWaveCountPosition(); diff --git a/src/battle.ts b/src/battle.ts index ccf99d5c536..ae086b6e7e6 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -1,3 +1,4 @@ +import BattleScene, { PokeballCounts } from "./battle-scene"; import { EnemyPokemon, PlayerPokemon, QueuedMove } from "./pokemon"; import { Command } from "./ui/command-ui-handler"; import * as Utils from "./utils"; @@ -28,6 +29,7 @@ export default class Battle { public double: boolean; public turn: integer; public turnCommands: TurnCommands; + public turnPokeballCounts: PokeballCounts; public playerParticipantIds: Set = new Set(); public escapeAttempts: integer = 0; @@ -37,8 +39,6 @@ export default class Battle { this.enemyField = []; this.double = double; this.turn = 0; - - this.incrementTurn(); } private getLevelForWave(): number { @@ -59,9 +59,10 @@ export default class Battle { return this.double ? 2 : 1; } - incrementTurn(): void { + incrementTurn(scene: BattleScene): void { this.turn++; this.turnCommands = Object.fromEntries(Utils.getEnumValues(BattlerIndex).map(bt => [ bt, null ])); + this.turnPokeballCounts = Object.assign({}, scene.pokeballCounts); } addParticipant(playerPokemon: PlayerPokemon): void { diff --git a/src/data/move.ts b/src/data/move.ts index 12957ddb91a..351396ab476 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2130,7 +2130,7 @@ export type MoveTargetSet = { } export function getMoveTargets(user: Pokemon, move: Moves): MoveTargetSet { - const moveTarget = move ? allMoves[move].moveTarget : move === undefined ? undefined : MoveTarget.NEAR_ENEMY; + const moveTarget = move ? allMoves[move].moveTarget : move === undefined ? MoveTarget.NEAR_ENEMY : []; const opponents = user.getOpponents(); let set: BattlerIndex[] = []; diff --git a/src/pokemon.ts b/src/pokemon.ts index 821fb912b0c..59cb2397329 100644 --- a/src/pokemon.ts +++ b/src/pokemon.ts @@ -474,7 +474,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { setMove(moveIndex: integer, moveId: Moves): void { const move = moveId ? new PokemonMove(moveId) : null; this.moveset[moveIndex] = move; - if (this.summonData.moveset) + if (this.summonData?.moveset) this.summonData.moveset[moveIndex] = move; } diff --git a/src/ui/ball-ui-handler.ts b/src/ui/ball-ui-handler.ts index 5ebf7553dd2..8cc8d9679f3 100644 --- a/src/ui/ball-ui-handler.ts +++ b/src/ui/ball-ui-handler.ts @@ -60,12 +60,12 @@ export default class BallUiHandler extends UiHandler { let success = false; - const pokeballTypeCount = Object.keys(this.scene.pokeballCounts).length; + const pokeballTypeCount = Object.keys(this.scene.currentBattle.turnPokeballCounts).length; if (button === Button.ACTION || button === Button.CANCEL) { success = true; if (button === Button.ACTION && this.cursor < pokeballTypeCount) { - if (this.scene.pokeballCounts[this.cursor]) { + if (this.scene.currentBattle.turnPokeballCounts[this.cursor]) { if ((this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.BALL, this.cursor)) { this.scene.ui.setMode(Mode.COMMAND); this.scene.ui.setMode(Mode.MESSAGE); @@ -93,7 +93,7 @@ export default class BallUiHandler extends UiHandler { } updateCounts() { - this.countsText.setText(Object.values(this.scene.pokeballCounts).map(c => `x${c}`).join('\n')); + this.countsText.setText(Object.values(this.scene.currentBattle.turnPokeballCounts).map(c => `x${c}`).join('\n')); } setCursor(cursor: integer): boolean { diff --git a/src/ui/battle-info.ts b/src/ui/battle-info.ts index 85402c88da9..7b5f5fb5d1a 100644 --- a/src/ui/battle-info.ts +++ b/src/ui/battle-info.ts @@ -120,10 +120,11 @@ export default class BattleInfo extends Phaser.GameObjects.Container { } this.hpBar.setScale(pokemon.getHpRatio(), 1); + this.lastHpFrame = this.hpBar.scaleX > 0.5 ? 'high' : this.hpBar.scaleX > 0.25 ? 'medium' : 'low'; + this.hpBar.setFrame(this.lastHpFrame); if (this.player) this.setHpNumbers(pokemon.hp, pokemon.getMaxHp()); this.lastHp = pokemon.hp; - this.lastHpFrame = this.hpBar.scaleX > 0.5 ? 'high' : this.hpBar.scaleX > 0.25 ? 'medium' : 'low'; this.lastMaxHp = pokemon.getMaxHp(); this.setLevel(pokemon.level);