This commit is contained in:
Bertie690 2025-06-19 23:52:17 -05:00 committed by GitHub
commit cd79d1119a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -12,9 +12,11 @@ import { BattlerIndex } from "#enums/battler-index";
import { TrickRoomTag } from "#app/data/arena-tag";
import { SwitchType } from "#enums/switch-type";
import { globalScene } from "#app/global-scene";
import type { TurnCommand } from "#app/battle";
export class TurnStartPhase extends FieldPhase {
public readonly phaseName = "TurnStartPhase";
/**
* This orders the active Pokemon on the field by speed into an BattlerIndex array and returns that array.
* It also checks for Trick Room and reverses the array if it is present.
@ -132,8 +134,6 @@ export class TurnStartPhase extends FieldPhase {
const field = globalScene.getField();
const moveOrder = this.getCommandOrder();
let orderIndex = 0;
for (const o of this.getSpeedOrder()) {
const pokemon = field[o];
const preTurnCommand = globalScene.currentBattle.preTurnCommands[o];
@ -150,90 +150,22 @@ export class TurnStartPhase extends FieldPhase {
const phaseManager = globalScene.phaseManager;
for (const o of moveOrder) {
moveOrder.forEach((o, index) => {
const pokemon = field[o];
const turnCommand = globalScene.currentBattle.turnCommands[o];
if (turnCommand?.skip) {
continue;
if (!turnCommand || turnCommand.skip) {
return;
}
switch (turnCommand?.command) {
case Command.FIGHT: {
const queuedMove = turnCommand.move;
pokemon.turnData.order = orderIndex++;
if (!queuedMove) {
continue;
}
const move =
pokemon.getMoveset().find(m => m.moveId === queuedMove.move && m.ppUsed < m.getMovePp()) ??
new PokemonMove(queuedMove.move);
if (move.getMove().hasAttr("MoveHeaderAttr")) {
phaseManager.unshiftNew("MoveHeaderPhase", pokemon, move);
}
if (pokemon.isPlayer() && turnCommand.cursor === -1) {
phaseManager.pushNew(
"MovePhase",
pokemon,
turnCommand.targets || turnCommand.move!.targets,
move,
turnCommand.move!.useMode,
); //TODO: is the bang correct here?
} else {
phaseManager.pushNew(
"MovePhase",
pokemon,
turnCommand.targets || turnCommand.move!.targets,
move,
queuedMove.useMode,
); // TODO: is the bang correct here?
}
break;
}
case Command.BALL:
phaseManager.unshiftNew("AttemptCapturePhase", turnCommand.targets![0] % 2, turnCommand.cursor!); //TODO: is the bang correct here?
break;
case Command.POKEMON:
{
const switchType = turnCommand.args?.[0] ? SwitchType.BATON_PASS : SwitchType.SWITCH;
phaseManager.unshiftNew(
"SwitchSummonPhase",
switchType,
pokemon.getFieldIndex(),
turnCommand.cursor!,
true,
pokemon.isPlayer(),
);
}
break;
case Command.RUN:
{
let runningPokemon = pokemon;
if (globalScene.currentBattle.double) {
const playerActivePokemon = field.filter(pokemon => {
if (pokemon) {
return pokemon.isPlayer() && pokemon.isActive();
}
return;
});
// if only one pokemon is alive, use that one
if (playerActivePokemon.length > 1) {
// find which active pokemon has faster speed
const fasterPokemon =
playerActivePokemon[0].getStat(Stat.SPD) > playerActivePokemon[1].getStat(Stat.SPD)
? playerActivePokemon[0]
: playerActivePokemon[1];
// check if either active pokemon has the ability "Run Away"
const hasRunAway = playerActivePokemon.find(p => p.hasAbility(AbilityId.RUN_AWAY));
runningPokemon = hasRunAway !== undefined ? hasRunAway : fasterPokemon;
}
}
phaseManager.unshiftNew("AttemptRunPhase", runningPokemon.getFieldIndex());
}
break;
// TODO: Remove `turnData.order` -
// it is used exclusively for Fusion Flare/Bolt
// and uses a really jank implementation
if (turnCommand.command === Command.FIGHT) {
pokemon.turnData.order = index;
}
}
this.handleTurnCommand(turnCommand, pokemon);
});
phaseManager.pushNew("WeatherEffectPhase");
phaseManager.pushNew("BerryPhase");
@ -250,4 +182,67 @@ export class TurnStartPhase extends FieldPhase {
*/
this.end();
}
private handleTurnCommand(turnCommand: TurnCommand, pokemon: Pokemon) {
switch (turnCommand?.command) {
case Command.FIGHT:
this.handleFightCommand(turnCommand, pokemon);
break;
case Command.BALL:
globalScene.phaseManager.unshiftNew("AttemptCapturePhase", turnCommand.targets![0] % 2, turnCommand.cursor!); //TODO: is the bang correct here?
break;
case Command.POKEMON:
globalScene.phaseManager.unshiftNew(
"SwitchSummonPhase",
turnCommand.args?.[0] ? SwitchType.BATON_PASS : SwitchType.SWITCH,
pokemon.getFieldIndex(),
turnCommand.cursor!, // TODO: Is this bang correct?
true,
pokemon.isPlayer(),
);
break;
case Command.RUN:
{
const playerActivePokemon = globalScene.getPokemonAllowedInBattle();
if (!globalScene.currentBattle.double || playerActivePokemon.length === 1) {
// If not in doubles, attempt to run with the currently active Pokemon.
globalScene.phaseManager.unshiftNew("AttemptRunPhase", pokemon.getFieldIndex());
return;
}
// Use the fastest first pokemon we find with Run Away, or else the faster of the 2 player pokemon.
// This intentionally does not check for Trick Room.
// TODO: This phase should not take a pokemon at all
const sortedPkmn = playerActivePokemon.sort((p1, p2) => p1.getStat(Stat.SPD) - p2.getStat(Stat.SPD));
const runningPokemon = sortedPkmn.find(p => p.hasAbility(AbilityId.RUN_AWAY)) ?? sortedPkmn[0];
globalScene.phaseManager.unshiftNew("AttemptRunPhase", runningPokemon.getFieldIndex());
}
break;
}
}
private handleFightCommand(turnCommand: TurnCommand, pokemon: Pokemon) {
const queuedMove = turnCommand.move;
if (!queuedMove) {
return;
}
// TODO: This seems somewhat dubious
const move =
pokemon.getMoveset().find(m => m.moveId === queuedMove.move && m.ppUsed < m.getMovePp()) ??
new PokemonMove(queuedMove.move);
if (move.getMove().hasAttr("MoveHeaderAttr")) {
globalScene.phaseManager.unshiftNew("MoveHeaderPhase", pokemon, move);
}
globalScene.phaseManager.pushNew(
"MovePhase",
pokemon,
turnCommand.targets ?? queuedMove.targets,
move,
queuedMove.useMode,
);
}
}