mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-21 00:52:47 +02:00
* Move trainer-config.ts * move TeraAIMode enum to its own file * Move TrainerPoolTier enum to its own file * Move TrainerSlot enum to its own file * Reorder and group imports * Move TrainerPartyTemplate to its own file * Remove speciesPoolPerEvilTeamAdmin method * Apply kev's suggestions from code review Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Fix typo in zinzolin's name --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
228 lines
8.4 KiB
TypeScript
228 lines
8.4 KiB
TypeScript
import type { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
|
import {
|
|
initBattleWithEnemyConfig,
|
|
setEncounterRewards,
|
|
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
|
import { trainerConfigs } from "#app/data/trainers/trainer-config";
|
|
import { trainerPartyTemplates } from "#app/data/trainers/TrainerPartyTemplate";
|
|
import { TrainerPartyCompoundTemplate } from "#app/data/trainers/TrainerPartyTemplate";
|
|
import { TrainerPartyTemplate } from "#app/data/trainers/TrainerPartyTemplate";
|
|
import { ModifierTier } from "#app/modifier/modifier-tier";
|
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
|
import { PartyMemberStrength } from "#enums/party-member-strength";
|
|
import { globalScene } from "#app/global-scene";
|
|
import * as Utils from "#app/utils";
|
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
|
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
|
|
|
/** the i18n namespace for the encounter */
|
|
const namespace = "mysteryEncounters/mysteriousChallengers";
|
|
|
|
/**
|
|
* Mysterious Challengers encounter.
|
|
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3801 | GitHub Issue #3801}
|
|
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
|
*/
|
|
export const MysteriousChallengersEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(
|
|
MysteryEncounterType.MYSTERIOUS_CHALLENGERS,
|
|
)
|
|
.withEncounterTier(MysteryEncounterTier.GREAT)
|
|
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
|
.withIntroSpriteConfigs([]) // These are set in onInit()
|
|
.withIntroDialogue([
|
|
{
|
|
text: `${namespace}:intro`,
|
|
},
|
|
])
|
|
.withOnInit(() => {
|
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
|
// Calculates what trainers are available for battle in the encounter
|
|
|
|
// Normal difficulty trainer is randomly pulled from biome
|
|
const normalTrainerType = globalScene.arena.randomTrainerType(globalScene.currentBattle.waveIndex);
|
|
const normalConfig = trainerConfigs[normalTrainerType].clone();
|
|
let female = false;
|
|
if (normalConfig.hasGenders) {
|
|
female = !!Utils.randSeedInt(2);
|
|
}
|
|
const normalSpriteKey = normalConfig.getSpriteKey(female, normalConfig.doubleOnly);
|
|
encounter.enemyPartyConfigs.push({
|
|
trainerConfig: normalConfig,
|
|
female: female,
|
|
});
|
|
|
|
// Hard difficulty trainer is another random trainer, but with AVERAGE_BALANCED config
|
|
// Number of mons is based off wave: 1-20 is 2, 20-40 is 3, etc. capping at 6 after wave 100
|
|
let retries = 0;
|
|
let hardTrainerType = globalScene.arena.randomTrainerType(globalScene.currentBattle.waveIndex);
|
|
while (retries < 5 && hardTrainerType === normalTrainerType) {
|
|
// Will try to use a different trainer from the normal trainer type
|
|
hardTrainerType = globalScene.arena.randomTrainerType(globalScene.currentBattle.waveIndex);
|
|
retries++;
|
|
}
|
|
const hardTemplate = new TrainerPartyCompoundTemplate(
|
|
new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER, false, true),
|
|
new TrainerPartyTemplate(
|
|
Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 20), 5),
|
|
PartyMemberStrength.AVERAGE,
|
|
false,
|
|
true,
|
|
),
|
|
);
|
|
const hardConfig = trainerConfigs[hardTrainerType].clone();
|
|
hardConfig.setPartyTemplates(hardTemplate);
|
|
female = false;
|
|
if (hardConfig.hasGenders) {
|
|
female = !!Utils.randSeedInt(2);
|
|
}
|
|
const hardSpriteKey = hardConfig.getSpriteKey(female, hardConfig.doubleOnly);
|
|
encounter.enemyPartyConfigs.push({
|
|
trainerConfig: hardConfig,
|
|
levelAdditiveModifier: 1,
|
|
female: female,
|
|
});
|
|
|
|
// Brutal trainer is pulled from pool of boss trainers (gym leaders) for the biome
|
|
// They are given an E4 template team, so will be stronger than usual boss encounter and always have 6 mons
|
|
const brutalTrainerType = globalScene.arena.randomTrainerType(globalScene.currentBattle.waveIndex, true);
|
|
const e4Template = trainerPartyTemplates.ELITE_FOUR;
|
|
const brutalConfig = trainerConfigs[brutalTrainerType].clone();
|
|
brutalConfig.title = trainerConfigs[brutalTrainerType].title;
|
|
brutalConfig.setPartyTemplates(e4Template);
|
|
// @ts-ignore
|
|
brutalConfig.partyTemplateFunc = null; // Overrides gym leader party template func
|
|
female = false;
|
|
if (brutalConfig.hasGenders) {
|
|
female = !!Utils.randSeedInt(2);
|
|
}
|
|
const brutalSpriteKey = brutalConfig.getSpriteKey(female, brutalConfig.doubleOnly);
|
|
encounter.enemyPartyConfigs.push({
|
|
trainerConfig: brutalConfig,
|
|
levelAdditiveModifier: 1.5,
|
|
female: female,
|
|
});
|
|
|
|
encounter.spriteConfigs = [
|
|
{
|
|
spriteKey: normalSpriteKey,
|
|
fileRoot: "trainer",
|
|
hasShadow: true,
|
|
tint: 1,
|
|
},
|
|
{
|
|
spriteKey: hardSpriteKey,
|
|
fileRoot: "trainer",
|
|
hasShadow: true,
|
|
tint: 1,
|
|
},
|
|
{
|
|
spriteKey: brutalSpriteKey,
|
|
fileRoot: "trainer",
|
|
hasShadow: true,
|
|
tint: 1,
|
|
},
|
|
];
|
|
|
|
return true;
|
|
})
|
|
.setLocalizationKey(`${namespace}`)
|
|
.withTitle(`${namespace}:title`)
|
|
.withDescription(`${namespace}:description`)
|
|
.withQuery(`${namespace}:query`)
|
|
.withSimpleOption(
|
|
{
|
|
buttonLabel: `${namespace}:option.1.label`,
|
|
buttonTooltip: `${namespace}:option.1.tooltip`,
|
|
selected: [
|
|
{
|
|
text: `${namespace}:option.selected`,
|
|
},
|
|
],
|
|
},
|
|
async () => {
|
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
|
// Spawn standard trainer battle with memory mushroom reward
|
|
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
|
|
|
|
setEncounterRewards({
|
|
guaranteedModifierTypeFuncs: [modifierTypes.TM_COMMON, modifierTypes.TM_GREAT, modifierTypes.MEMORY_MUSHROOM],
|
|
fillRemaining: true,
|
|
});
|
|
|
|
// Seed offsets to remove possibility of different trainers having exact same teams
|
|
let initBattlePromise: Promise<void>;
|
|
globalScene.executeWithSeedOffset(() => {
|
|
initBattlePromise = initBattleWithEnemyConfig(config);
|
|
}, globalScene.currentBattle.waveIndex * 10);
|
|
await initBattlePromise!;
|
|
},
|
|
)
|
|
.withSimpleOption(
|
|
{
|
|
buttonLabel: `${namespace}:option.2.label`,
|
|
buttonTooltip: `${namespace}:option.2.tooltip`,
|
|
selected: [
|
|
{
|
|
text: `${namespace}:option.selected`,
|
|
},
|
|
],
|
|
},
|
|
async () => {
|
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
|
// Spawn hard fight
|
|
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[1];
|
|
|
|
setEncounterRewards({
|
|
guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT],
|
|
fillRemaining: true,
|
|
});
|
|
|
|
// Seed offsets to remove possibility of different trainers having exact same teams
|
|
let initBattlePromise: Promise<void>;
|
|
globalScene.executeWithSeedOffset(() => {
|
|
initBattlePromise = initBattleWithEnemyConfig(config);
|
|
}, globalScene.currentBattle.waveIndex * 100);
|
|
await initBattlePromise!;
|
|
},
|
|
)
|
|
.withSimpleOption(
|
|
{
|
|
buttonLabel: `${namespace}:option.3.label`,
|
|
buttonTooltip: `${namespace}:option.3.tooltip`,
|
|
selected: [
|
|
{
|
|
text: `${namespace}:option.selected`,
|
|
},
|
|
],
|
|
},
|
|
async () => {
|
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
|
// Spawn brutal fight
|
|
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[2];
|
|
|
|
// To avoid player level snowballing from picking this option
|
|
encounter.expMultiplier = 0.9;
|
|
|
|
setEncounterRewards({
|
|
guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT],
|
|
fillRemaining: true,
|
|
});
|
|
|
|
// Seed offsets to remove possibility of different trainers having exact same teams
|
|
let initBattlePromise: Promise<void>;
|
|
globalScene.executeWithSeedOffset(() => {
|
|
initBattlePromise = initBattleWithEnemyConfig(config);
|
|
}, globalScene.currentBattle.waveIndex * 1000);
|
|
await initBattlePromise!;
|
|
},
|
|
)
|
|
.withOutroDialogue([
|
|
{
|
|
text: `${namespace}:outro`,
|
|
},
|
|
])
|
|
.build();
|