pokerogue/src/battle.ts
Madmadness65 f342ea8e67 Fix minor champion oversight
Iris is no longer listed twice for wave 190, and Geeta has been added for the future
2024-01-04 19:28:24 -06:00

231 lines
9.5 KiB
TypeScript

import BattleScene from "./battle-scene";
import { EnemyPokemon, PlayerPokemon, QueuedMove } from "./pokemon";
import { Command } from "./ui/command-ui-handler";
import * as Utils from "./utils";
import Trainer from "./trainer";
import { Species } from "./data/species";
import { Moves } from "./data/move";
import { TrainerType } from "./data/trainer-type";
import { GameMode } from "./game-mode";
export enum BattleType {
WILD,
TRAINER
}
export enum BattlerIndex {
ATTACKER = -1,
PLAYER,
PLAYER_2,
ENEMY,
ENEMY_2
}
export interface TurnCommand {
command: Command;
cursor?: integer;
move?: QueuedMove;
targets?: BattlerIndex[];
skip?: boolean;
args?: any[];
};
interface TurnCommands {
[key: integer]: TurnCommand
}
export default class Battle {
public waveIndex: integer;
public battleType: BattleType;
public trainer: Trainer;
public enemyLevels: integer[];
public enemyParty: EnemyPokemon[];
public seenEnemyPartyMemberIds: Set<integer>;
public double: boolean;
public started: boolean;
public turn: integer;
public turnCommands: TurnCommands;
public playerParticipantIds: Set<integer> = new Set<integer>();
public escapeAttempts: integer = 0;
public lastMove: Moves;
public battleSeed: string;
private battleSeedState: string;
constructor(waveIndex: integer, battleType: BattleType, trainer: Trainer, double: boolean) {
this.waveIndex = waveIndex;
this.battleType = battleType;
this.trainer = trainer;
this.enemyLevels = battleType !== BattleType.TRAINER
? new Array(double ? 2 : 1).fill(null).map(() => this.getLevelForWave())
: trainer.getPartyLevels(this.waveIndex);
this.enemyParty = [];
this.seenEnemyPartyMemberIds = new Set<integer>();
this.double = double;
this.turn = 0;
this.started = false;
this.battleSeed = Utils.randomString(16, true);
this.battleSeedState = null;
}
private getLevelForWave(): integer {
let baseLevel = 1 + this.waveIndex / 2 + Math.pow(this.waveIndex / 25, 2);
const bossMultiplier = 1.2;
if (!(this.waveIndex % 10)) {
const ret = Math.floor(baseLevel * bossMultiplier);
if (this.waveIndex === 200 || !(this.waveIndex % 250))
return Math.ceil(ret / 25) * 25;
return ret + Math.round(Phaser.Math.RND.realInRange(-1, 1) * Math.floor(this.waveIndex / 10));
}
const deviation = 10 / this.waveIndex;
return Math.max(Math.round(baseLevel + Math.abs(Utils.randSeedGauss(deviation))), 1);
}
getBattlerCount(): integer {
return this.double ? 2 : 1;
}
incrementTurn(scene: BattleScene): void {
this.turn++;
this.turnCommands = Object.fromEntries(Utils.getEnumValues(BattlerIndex).map(bt => [ bt, null ]));
this.battleSeedState = null;
}
addParticipant(playerPokemon: PlayerPokemon): void {
this.playerParticipantIds.add(playerPokemon.id);
}
removeFaintedParticipant(playerPokemon: PlayerPokemon): void {
this.playerParticipantIds.delete(playerPokemon.id);
}
getBgmOverride(scene: BattleScene): string {
const battlers = this.enemyParty.slice(0, this.getBattlerCount());
if (this.battleType === BattleType.TRAINER) {
if (!this.started && this.trainer.config.encounterBgm && this.trainer.config.encounterMessages.length)
return `encounter_${this.trainer.getEncounterBgm()}`;
return this.trainer.getBattleBgm();
}
for (let pokemon of battlers) {
if (pokemon.species.speciesId === Species.ETERNATUS)
return 'battle_final';
if (pokemon.species.legendary || pokemon.species.pseudoLegendary || pokemon.species.mythical) {
if (pokemon.species.speciesId === Species.KYUREM)
return 'battle_legendary_z';
if (pokemon.species.legendary)
return 'battle_legendary_rz';
return 'battle_legendary';
}
}
if (scene.gameMode === GameMode.CLASSIC && this.waveIndex <= 4)
return 'battle_wild';
return null;
}
randSeedInt(range: integer, min: integer = 0): integer {
let ret: integer;
const state = Phaser.Math.RND.state();
if (this.battleSeedState)
Phaser.Math.RND.state(this.battleSeedState);
else
Phaser.Math.RND.sow([ Utils.shiftCharCodes(this.battleSeed, this.turn << 6) ]);
ret = Utils.randSeedInt(range, min);
this.battleSeedState = Phaser.Math.RND.state();
Phaser.Math.RND.state(state);
return ret;
}
}
export class FixedBattle extends Battle {
constructor(scene: BattleScene, waveIndex: integer, config: FixedBattleConfig) {
super(waveIndex, config.battleType, config.battleType === BattleType.TRAINER ? config.getTrainer(scene) : null, config.double);
if (config.getEnemyParty)
this.enemyParty = config.getEnemyParty(scene);
}
}
type GetTrainerFunc = (scene: BattleScene) => Trainer;
type GetEnemyPartyFunc = (scene: BattleScene) => EnemyPokemon[];
export class FixedBattleConfig {
public battleType: BattleType;
public double: boolean;
public getTrainer: GetTrainerFunc;
public getEnemyParty: GetEnemyPartyFunc;
public seedOffsetWaveIndex: integer;
setBattleType(battleType: BattleType): FixedBattleConfig {
this.battleType = battleType;
return this;
}
setDouble(double: boolean): FixedBattleConfig {
this.double = double;
return this;
}
setGetTrainerFunc(getTrainerFunc: GetTrainerFunc): FixedBattleConfig {
this.getTrainer = getTrainerFunc;
return this;
}
setGetEnemyPartyFunc(getEnemyPartyFunc: GetEnemyPartyFunc): FixedBattleConfig {
this.getEnemyParty = getEnemyPartyFunc;
return this;
}
setSeedOffsetWave(seedOffsetWaveIndex: integer): FixedBattleConfig {
this.seedOffsetWaveIndex = seedOffsetWaveIndex;
return this;
}
}
function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[]): GetTrainerFunc {
return (scene: BattleScene) => {
const rand = Utils.randSeedInt(trainerPool.length);
console.log(rand);
const trainerTypes: TrainerType[] = [];
for (let trainerPoolEntry of trainerPool) {
const trainerType = Array.isArray(trainerPoolEntry)
? Phaser.Math.RND.pick(trainerPoolEntry)
: trainerPoolEntry;
trainerTypes.push(trainerType);
}
return new Trainer(scene, trainerTypes[rand]);
};
}
interface FixedBattleConfigs {
[key: integer]: FixedBattleConfig
}
export const fixedBattles: FixedBattleConfigs = {
[5]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.YOUNGSTER, !!Utils.randSeedInt(2))),
[8]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, true)),
[25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_2, true)),
[55]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_3, true)),
[95]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_4, true)),
[145]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, true)),
[186]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ]/*, TrainerType.RIKA, TrainerType.CRISPIN*/ ])),
[187]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(186)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA/*, TrainerType.POPPY, TrainerType.AMARYS*/ ])),
[188]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(186)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA/*, TrainerType.LARRY_ELITE, TrainerType.LACEY*/ ])),
[189]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(186)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI/*, TrainerType.HASSEL, TrainerType.DRAYTON*/ ])),
[190]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(186)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BLUE, TrainerType.RED, TrainerType.LANCE_CHAMPION, TrainerType.STEVEN, TrainerType.WALLACE, TrainerType.CYNTHIA, TrainerType.ALDER, TrainerType.IRIS, TrainerType.DIANTHA, TrainerType.LEON/*, TrainerType.GEETA, TrainerType.NEMONA, TrainerType.KIERAN*/ ])),
[195]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_6, true))
};