migrate training session encounter
This commit is contained in:
parent
2d42697321
commit
39f98222a6
|
@ -1,50 +0,0 @@
|
||||||
import MysteryEncounterDialogue from "#app/data/mystery-encounters/mystery-encounter-dialogue";
|
|
||||||
|
|
||||||
export const TrainingSessionDialogue: MysteryEncounterDialogue = {
|
|
||||||
intro: [
|
|
||||||
{
|
|
||||||
text: "mysteryEncounter:training_session_intro_message"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
encounterOptionsDialogue: {
|
|
||||||
title: "mysteryEncounter:training_session_title",
|
|
||||||
description: "mysteryEncounter:training_session_description",
|
|
||||||
query: "mysteryEncounter:training_session_query",
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
buttonLabel: "mysteryEncounter:training_session_option_1_label",
|
|
||||||
buttonTooltip: "mysteryEncounter:training_session_option_1_tooltip",
|
|
||||||
selected: [
|
|
||||||
{
|
|
||||||
text: "mysteryEncounter:training_session_option_selected_message"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
buttonLabel: "mysteryEncounter:training_session_option_2_label",
|
|
||||||
buttonTooltip: "mysteryEncounter:training_session_option_2_tooltip",
|
|
||||||
secondOptionPrompt: "mysteryEncounter:training_session_option_2_select_prompt",
|
|
||||||
selected: [
|
|
||||||
{
|
|
||||||
text: "mysteryEncounter:training_session_option_selected_message"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
buttonLabel: "mysteryEncounter:training_session_option_3_label",
|
|
||||||
buttonTooltip: "mysteryEncounter:training_session_option_3_tooltip",
|
|
||||||
secondOptionPrompt: "mysteryEncounter:training_session_option_3_select_prompt",
|
|
||||||
selected: [
|
|
||||||
{
|
|
||||||
text: "mysteryEncounter:training_session_option_selected_message"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
outro: [
|
|
||||||
{
|
|
||||||
text: "mysteryEncounter:training_session_outro_win"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
getEncounterText,
|
getEncounterText,
|
||||||
initBattleWithEnemyConfig,
|
initBattleWithEnemyConfig,
|
||||||
selectPokemonForOption,
|
selectPokemonForOption,
|
||||||
setEncounterRewards
|
setEncounterRewards,
|
||||||
} from "#app/data/mystery-encounters/mystery-encounter-utils";
|
} from "#app/data/mystery-encounters/mystery-encounter-utils";
|
||||||
import { getNatureName, Nature } from "#app/data/nature";
|
import { getNatureName, Nature } from "#app/data/nature";
|
||||||
import { speciesStarters } from "#app/data/pokemon-species";
|
import { speciesStarters } from "#app/data/pokemon-species";
|
||||||
|
@ -20,270 +20,414 @@ import { randSeedShuffle } from "#app/utils";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "../../../battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier } from "../mystery-encounter";
|
import MysteryEncounter, {
|
||||||
|
MysteryEncounterBuilder,
|
||||||
|
MysteryEncounterTier,
|
||||||
|
} from "../mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||||
|
|
||||||
export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilder
|
export const TrainingSessionEncounter: MysteryEncounter =
|
||||||
.withEncounterType(MysteryEncounterType.TRAINING_SESSION)
|
MysteryEncounterBuilder.withEncounterType(
|
||||||
.withEncounterTier(MysteryEncounterTier.ULTRA)
|
MysteryEncounterType.TRAINING_SESSION
|
||||||
.withIntroSpriteConfigs([
|
|
||||||
{
|
|
||||||
spriteKey: "training_gear",
|
|
||||||
fileRoot: "mystery-encounters",
|
|
||||||
hasShadow: true,
|
|
||||||
y: 3
|
|
||||||
}
|
|
||||||
])
|
|
||||||
.withSceneWaveRangeRequirement(10, 180) // waves 10 to 180
|
|
||||||
.withHideWildIntroMessage(true)
|
|
||||||
.withOption(new MysteryEncounterOptionBuilder()
|
|
||||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
|
||||||
const encounter = scene.currentBattle.mysteryEncounter;
|
|
||||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
|
||||||
encounter.misc = {
|
|
||||||
playerPokemon: pokemon
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return selectPokemonForOption(scene, onPokemonSelected);
|
|
||||||
})
|
|
||||||
.withOptionPhase(async (scene: BattleScene) => {
|
|
||||||
const encounter = scene.currentBattle.mysteryEncounter;
|
|
||||||
const playerPokemon: PlayerPokemon = encounter.misc.playerPokemon;
|
|
||||||
|
|
||||||
// Spawn light training session with chosen pokemon
|
|
||||||
// Every 50 waves, add +1 boss segment, capping at 5
|
|
||||||
const segments = Math.min(2 + Math.floor(scene.currentBattle.waveIndex / 50), 5);
|
|
||||||
const modifiers = new ModifiersHolder();
|
|
||||||
const config = getEnemyConfig(scene, playerPokemon, segments, modifiers);
|
|
||||||
scene.removePokemonFromPlayerParty(playerPokemon, false);
|
|
||||||
|
|
||||||
const getIvName = (index: number) => {
|
|
||||||
switch (index) {
|
|
||||||
case Stat.HP:
|
|
||||||
return pokemonInfo.Stat["HPshortened"];
|
|
||||||
case Stat.ATK:
|
|
||||||
return pokemonInfo.Stat["ATKshortened"];
|
|
||||||
case Stat.DEF:
|
|
||||||
return pokemonInfo.Stat["DEFshortened"];
|
|
||||||
case Stat.SPATK:
|
|
||||||
return pokemonInfo.Stat["SPATKshortened"];
|
|
||||||
case Stat.SPDEF:
|
|
||||||
return pokemonInfo.Stat["SPDEFshortened"];
|
|
||||||
case Stat.SPD:
|
|
||||||
return pokemonInfo.Stat["SPDshortened"];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onBeforeRewardsPhase = () => {
|
|
||||||
encounter.setDialogueToken("stat1", "-");
|
|
||||||
encounter.setDialogueToken("stat2", "-");
|
|
||||||
// Add the pokemon back to party with IV boost
|
|
||||||
const ivIndexes = [];
|
|
||||||
playerPokemon.ivs.forEach((iv, index) => {
|
|
||||||
if (iv < 31) {
|
|
||||||
ivIndexes.push({ iv: iv, index: index });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Improves 2 random non-maxed IVs
|
|
||||||
// +10 if IV is < 10, +5 if between 10-20, and +3 if > 20
|
|
||||||
// A 0-4 starting IV will cap in 6 encounters (assuming you always rolled that IV)
|
|
||||||
// 5-14 starting IV caps in 5 encounters
|
|
||||||
// 15-19 starting IV caps in 4 encounters
|
|
||||||
// 20-24 starting IV caps in 3 encounters
|
|
||||||
// 25-27 starting IV caps in 2 encounters
|
|
||||||
let improvedCount = 0;
|
|
||||||
while (ivIndexes.length > 0 && improvedCount < 2) {
|
|
||||||
randSeedShuffle(ivIndexes);
|
|
||||||
const ivToChange = ivIndexes.pop();
|
|
||||||
let newVal = ivToChange.iv;
|
|
||||||
if (improvedCount === 0) {
|
|
||||||
encounter.setDialogueToken("stat1", getIvName(ivToChange.index));
|
|
||||||
} else {
|
|
||||||
encounter.setDialogueToken("stat2", getIvName(ivToChange.index));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Corrects required encounter breakpoints to be continuous for all IV values
|
|
||||||
if (ivToChange.iv <= 21 && ivToChange.iv - 1 % 5 === 0) {
|
|
||||||
newVal += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
newVal += ivToChange.iv <= 10 ? 10 : ivToChange.iv <= 20 ? 5 : 3;
|
|
||||||
newVal = Math.min(newVal, 31);
|
|
||||||
playerPokemon.ivs[ivToChange.index] = newVal;
|
|
||||||
improvedCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (improvedCount > 0) {
|
|
||||||
playerPokemon.calculateStats();
|
|
||||||
scene.gameData.updateSpeciesDexIvs(playerPokemon.species.getRootSpeciesId(true), playerPokemon.ivs);
|
|
||||||
scene.gameData.setPokemonCaught(playerPokemon, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add pokemon and mods back
|
|
||||||
scene.getParty().push(playerPokemon);
|
|
||||||
for (const mod of modifiers.value) {
|
|
||||||
scene.addModifier(mod, true, false, false, true);
|
|
||||||
}
|
|
||||||
scene.updateModifiers(true);
|
|
||||||
scene.queueMessage(getEncounterText(scene, "mysteryEncounter:training_session_battle_finished_1"), null, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
setEncounterRewards(scene, { fillRemaining: true }, null, onBeforeRewardsPhase);
|
|
||||||
|
|
||||||
return initBattleWithEnemyConfig(scene, config);
|
|
||||||
})
|
|
||||||
.build()
|
|
||||||
)
|
)
|
||||||
.withOption(new MysteryEncounterOptionBuilder()
|
.withEncounterTier(MysteryEncounterTier.ULTRA)
|
||||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
.withSceneWaveRangeRequirement(10, 180) // waves 10 to 180
|
||||||
// Open menu for selecting pokemon and Nature
|
.withHideWildIntroMessage(true)
|
||||||
const encounter = scene.currentBattle.mysteryEncounter;
|
.withIntroSpriteConfigs([
|
||||||
const natures = new Array(25).fill(null).map((val, i) => i as Nature);
|
{
|
||||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
spriteKey: "training_gear",
|
||||||
// Return the options for nature selection
|
fileRoot: "mystery-encounters",
|
||||||
return natures.map((nature: Nature) => {
|
hasShadow: true,
|
||||||
const option: OptionSelectItem = {
|
y: 3,
|
||||||
label: getNatureName(nature, true, true, true, scene.uiTheme),
|
},
|
||||||
handler: () => {
|
])
|
||||||
// Pokemon and second option selected
|
.withIntroDialogue([
|
||||||
encounter.setDialogueToken("nature", getNatureName(nature));
|
{
|
||||||
encounter.misc = {
|
text: "mysteryEncounter:training_session_intro_message",
|
||||||
playerPokemon: pokemon,
|
},
|
||||||
chosenNature: nature
|
])
|
||||||
};
|
.withTitle("mysteryEncounter:training_session_title")
|
||||||
return true;
|
.withDescription("mysteryEncounter:training_session_description")
|
||||||
}
|
.withQuery("mysteryEncounter:training_session_query")
|
||||||
};
|
.withOption(
|
||||||
return option;
|
new MysteryEncounterOptionBuilder()
|
||||||
});
|
.withDialogue({
|
||||||
};
|
buttonLabel: "mysteryEncounter:training_session_option_1_label",
|
||||||
|
buttonTooltip: "mysteryEncounter:training_session_option_1_tooltip",
|
||||||
return selectPokemonForOption(scene, onPokemonSelected);
|
selected: [
|
||||||
})
|
{
|
||||||
.withOptionPhase(async (scene: BattleScene) => {
|
text: "mysteryEncounter:training_session_option_selected_message",
|
||||||
const encounter = scene.currentBattle.mysteryEncounter;
|
|
||||||
const playerPokemon: PlayerPokemon = encounter.misc.playerPokemon;
|
|
||||||
|
|
||||||
// Spawn medium training session with chosen pokemon
|
|
||||||
// Every 40 waves, add +1 boss segment, capping at 6
|
|
||||||
const segments = Math.min(2 + Math.floor(scene.currentBattle.waveIndex / 40), 6);
|
|
||||||
const modifiers = new ModifiersHolder();
|
|
||||||
const config = getEnemyConfig(scene, playerPokemon, segments, modifiers);
|
|
||||||
scene.removePokemonFromPlayerParty(playerPokemon, false);
|
|
||||||
|
|
||||||
const onBeforeRewardsPhase = () => {
|
|
||||||
scene.queueMessage(getEncounterText(scene, "mysteryEncounter:training_session_battle_finished_2"), null, true);
|
|
||||||
// Add the pokemon back to party with Nature change
|
|
||||||
playerPokemon.setNature(encounter.misc.chosenNature);
|
|
||||||
scene.gameData.setPokemonCaught(playerPokemon, false);
|
|
||||||
|
|
||||||
// Add pokemon and mods back
|
|
||||||
scene.getParty().push(playerPokemon);
|
|
||||||
for (const mod of modifiers.value) {
|
|
||||||
scene.addModifier(mod, true, false, false, true);
|
|
||||||
}
|
|
||||||
scene.updateModifiers(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
setEncounterRewards(scene, { fillRemaining: true }, null, onBeforeRewardsPhase);
|
|
||||||
|
|
||||||
return initBattleWithEnemyConfig(scene, config);
|
|
||||||
})
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
.withOption(new MysteryEncounterOptionBuilder()
|
|
||||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
|
||||||
// Open menu for selecting pokemon and ability to learn
|
|
||||||
const encounter = scene.currentBattle.mysteryEncounter;
|
|
||||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
|
||||||
// Return the options for ability selection
|
|
||||||
const speciesForm = !!pokemon.getFusionSpeciesForm() ? pokemon.getFusionSpeciesForm() : pokemon.getSpeciesForm();
|
|
||||||
const abilityCount = speciesForm.getAbilityCount();
|
|
||||||
const abilities = new Array(abilityCount).fill(null).map((val, i) => allAbilities[speciesForm.getAbility(i)]);
|
|
||||||
return abilities.map((ability: Ability, index) => {
|
|
||||||
const option: OptionSelectItem = {
|
|
||||||
label: ability.name,
|
|
||||||
handler: () => {
|
|
||||||
// Pokemon and ability selected
|
|
||||||
encounter.setDialogueToken("ability", ability.name);
|
|
||||||
encounter.misc = {
|
|
||||||
playerPokemon: pokemon,
|
|
||||||
abilityIndex: index
|
|
||||||
};
|
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
onHover: () => {
|
],
|
||||||
scene.ui.showText(ability.description);
|
})
|
||||||
|
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||||
|
encounter.misc = {
|
||||||
|
playerPokemon: pokemon,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return selectPokemonForOption(scene, onPokemonSelected);
|
||||||
|
})
|
||||||
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
const playerPokemon: PlayerPokemon = encounter.misc.playerPokemon;
|
||||||
|
|
||||||
|
// Spawn light training session with chosen pokemon
|
||||||
|
// Every 50 waves, add +1 boss segment, capping at 5
|
||||||
|
const segments = Math.min(
|
||||||
|
2 + Math.floor(scene.currentBattle.waveIndex / 50),
|
||||||
|
5
|
||||||
|
);
|
||||||
|
const modifiers = new ModifiersHolder();
|
||||||
|
const config = getEnemyConfig(
|
||||||
|
scene,
|
||||||
|
playerPokemon,
|
||||||
|
segments,
|
||||||
|
modifiers
|
||||||
|
);
|
||||||
|
scene.removePokemonFromPlayerParty(playerPokemon, false);
|
||||||
|
|
||||||
|
const getIvName = (index: number) => {
|
||||||
|
switch (index) {
|
||||||
|
case Stat.HP:
|
||||||
|
return pokemonInfo.Stat["HPshortened"];
|
||||||
|
case Stat.ATK:
|
||||||
|
return pokemonInfo.Stat["ATKshortened"];
|
||||||
|
case Stat.DEF:
|
||||||
|
return pokemonInfo.Stat["DEFshortened"];
|
||||||
|
case Stat.SPATK:
|
||||||
|
return pokemonInfo.Stat["SPATKshortened"];
|
||||||
|
case Stat.SPDEF:
|
||||||
|
return pokemonInfo.Stat["SPDEFshortened"];
|
||||||
|
case Stat.SPD:
|
||||||
|
return pokemonInfo.Stat["SPDshortened"];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return option;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return selectPokemonForOption(scene, onPokemonSelected);
|
const onBeforeRewardsPhase = () => {
|
||||||
})
|
encounter.setDialogueToken("stat1", "-");
|
||||||
.withOptionPhase(async (scene: BattleScene) => {
|
encounter.setDialogueToken("stat2", "-");
|
||||||
const encounter = scene.currentBattle.mysteryEncounter;
|
// Add the pokemon back to party with IV boost
|
||||||
const playerPokemon: PlayerPokemon = encounter.misc.playerPokemon;
|
const ivIndexes = [];
|
||||||
|
playerPokemon.ivs.forEach((iv, index) => {
|
||||||
|
if (iv < 31) {
|
||||||
|
ivIndexes.push({ iv: iv, index: index });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Spawn hard training session with chosen pokemon
|
// Improves 2 random non-maxed IVs
|
||||||
// Every 30 waves, add +1 boss segment, capping at 6
|
// +10 if IV is < 10, +5 if between 10-20, and +3 if > 20
|
||||||
// Also starts with +1 to all stats
|
// A 0-4 starting IV will cap in 6 encounters (assuming you always rolled that IV)
|
||||||
const segments = Math.min(2 + Math.floor(scene.currentBattle.waveIndex / 30), 6);
|
// 5-14 starting IV caps in 5 encounters
|
||||||
const modifiers = new ModifiersHolder();
|
// 15-19 starting IV caps in 4 encounters
|
||||||
const config = getEnemyConfig(scene, playerPokemon, segments, modifiers);
|
// 20-24 starting IV caps in 3 encounters
|
||||||
config.pokemonConfigs[0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
|
// 25-27 starting IV caps in 2 encounters
|
||||||
scene.removePokemonFromPlayerParty(playerPokemon, false);
|
let improvedCount = 0;
|
||||||
|
while (ivIndexes.length > 0 && improvedCount < 2) {
|
||||||
|
randSeedShuffle(ivIndexes);
|
||||||
|
const ivToChange = ivIndexes.pop();
|
||||||
|
let newVal = ivToChange.iv;
|
||||||
|
if (improvedCount === 0) {
|
||||||
|
encounter.setDialogueToken(
|
||||||
|
"stat1",
|
||||||
|
getIvName(ivToChange.index)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
encounter.setDialogueToken(
|
||||||
|
"stat2",
|
||||||
|
getIvName(ivToChange.index)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const onBeforeRewardsPhase = () => {
|
// Corrects required encounter breakpoints to be continuous for all IV values
|
||||||
scene.queueMessage(getEncounterText(scene, "mysteryEncounter:training_session_battle_finished_3"), null, true);
|
if (ivToChange.iv <= 21 && ivToChange.iv - (1 % 5) === 0) {
|
||||||
// Add the pokemon back to party with ability change
|
newVal += 1;
|
||||||
const abilityIndex = encounter.misc.abilityIndex;
|
}
|
||||||
if (!!playerPokemon.getFusionSpeciesForm()) {
|
|
||||||
playerPokemon.fusionAbilityIndex = abilityIndex;
|
|
||||||
if (speciesStarters.hasOwnProperty(playerPokemon.fusionSpecies.speciesId)) {
|
|
||||||
scene.gameData.starterData[playerPokemon.fusionSpecies.speciesId].abilityAttr |= abilityIndex !== 1 || playerPokemon.fusionSpecies.ability2
|
|
||||||
? Math.pow(2, playerPokemon.fusionAbilityIndex)
|
|
||||||
: AbilityAttr.ABILITY_HIDDEN;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
playerPokemon.abilityIndex = abilityIndex;
|
|
||||||
if (speciesStarters.hasOwnProperty(playerPokemon.species.speciesId)) {
|
|
||||||
scene.gameData.starterData[playerPokemon.species.speciesId].abilityAttr |= abilityIndex !== 1 || playerPokemon.species.ability2
|
|
||||||
? Math.pow(2, playerPokemon.abilityIndex)
|
|
||||||
: AbilityAttr.ABILITY_HIDDEN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
playerPokemon.getAbility();
|
newVal += ivToChange.iv <= 10 ? 10 : ivToChange.iv <= 20 ? 5 : 3;
|
||||||
playerPokemon.calculateStats();
|
newVal = Math.min(newVal, 31);
|
||||||
scene.gameData.setPokemonCaught(playerPokemon, false);
|
playerPokemon.ivs[ivToChange.index] = newVal;
|
||||||
|
improvedCount++;
|
||||||
|
}
|
||||||
|
|
||||||
// Add pokemon and mods back
|
if (improvedCount > 0) {
|
||||||
scene.getParty().push(playerPokemon);
|
playerPokemon.calculateStats();
|
||||||
for (const mod of modifiers.value) {
|
scene.gameData.updateSpeciesDexIvs(
|
||||||
scene.addModifier(mod, true, false, false, true);
|
playerPokemon.species.getRootSpeciesId(true),
|
||||||
}
|
playerPokemon.ivs
|
||||||
scene.updateModifiers(true);
|
);
|
||||||
};
|
scene.gameData.setPokemonCaught(playerPokemon, false);
|
||||||
|
}
|
||||||
|
|
||||||
setEncounterRewards(scene, { fillRemaining: true }, null, onBeforeRewardsPhase);
|
// Add pokemon and mods back
|
||||||
|
scene.getParty().push(playerPokemon);
|
||||||
|
for (const mod of modifiers.value) {
|
||||||
|
scene.addModifier(mod, true, false, false, true);
|
||||||
|
}
|
||||||
|
scene.updateModifiers(true);
|
||||||
|
scene.queueMessage(
|
||||||
|
getEncounterText(
|
||||||
|
scene,
|
||||||
|
"mysteryEncounter:training_session_battle_finished_1"
|
||||||
|
),
|
||||||
|
null,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return initBattleWithEnemyConfig(scene, config);
|
setEncounterRewards(
|
||||||
})
|
scene,
|
||||||
.build()
|
{ fillRemaining: true },
|
||||||
)
|
null,
|
||||||
.build();
|
onBeforeRewardsPhase
|
||||||
|
);
|
||||||
|
|
||||||
function getEnemyConfig(scene: BattleScene, playerPokemon: PlayerPokemon, segments: number, modifiers: ModifiersHolder): EnemyPartyConfig {
|
return initBattleWithEnemyConfig(scene, config);
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.withOption(
|
||||||
|
new MysteryEncounterOptionBuilder()
|
||||||
|
.withDialogue({
|
||||||
|
buttonLabel: "mysteryEncounter:training_session_option_2_label",
|
||||||
|
buttonTooltip: "mysteryEncounter:training_session_option_2_tooltip",
|
||||||
|
secondOptionPrompt:
|
||||||
|
"mysteryEncounter:training_session_option_2_select_prompt",
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:training_session_option_selected_message",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||||
|
// Open menu for selecting pokemon and Nature
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
const natures = new Array(25).fill(null).map((val, i) => i as Nature);
|
||||||
|
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||||
|
// Return the options for nature selection
|
||||||
|
return natures.map((nature: Nature) => {
|
||||||
|
const option: OptionSelectItem = {
|
||||||
|
label: getNatureName(nature, true, true, true, scene.uiTheme),
|
||||||
|
handler: () => {
|
||||||
|
// Pokemon and second option selected
|
||||||
|
encounter.setDialogueToken("nature", getNatureName(nature));
|
||||||
|
encounter.misc = {
|
||||||
|
playerPokemon: pokemon,
|
||||||
|
chosenNature: nature,
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return option;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return selectPokemonForOption(scene, onPokemonSelected);
|
||||||
|
})
|
||||||
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
const playerPokemon: PlayerPokemon = encounter.misc.playerPokemon;
|
||||||
|
|
||||||
|
// Spawn medium training session with chosen pokemon
|
||||||
|
// Every 40 waves, add +1 boss segment, capping at 6
|
||||||
|
const segments = Math.min(
|
||||||
|
2 + Math.floor(scene.currentBattle.waveIndex / 40),
|
||||||
|
6
|
||||||
|
);
|
||||||
|
const modifiers = new ModifiersHolder();
|
||||||
|
const config = getEnemyConfig(
|
||||||
|
scene,
|
||||||
|
playerPokemon,
|
||||||
|
segments,
|
||||||
|
modifiers
|
||||||
|
);
|
||||||
|
scene.removePokemonFromPlayerParty(playerPokemon, false);
|
||||||
|
|
||||||
|
const onBeforeRewardsPhase = () => {
|
||||||
|
scene.queueMessage(
|
||||||
|
getEncounterText(
|
||||||
|
scene,
|
||||||
|
"mysteryEncounter:training_session_battle_finished_2"
|
||||||
|
),
|
||||||
|
null,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
// Add the pokemon back to party with Nature change
|
||||||
|
playerPokemon.setNature(encounter.misc.chosenNature);
|
||||||
|
scene.gameData.setPokemonCaught(playerPokemon, false);
|
||||||
|
|
||||||
|
// Add pokemon and mods back
|
||||||
|
scene.getParty().push(playerPokemon);
|
||||||
|
for (const mod of modifiers.value) {
|
||||||
|
scene.addModifier(mod, true, false, false, true);
|
||||||
|
}
|
||||||
|
scene.updateModifiers(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
setEncounterRewards(
|
||||||
|
scene,
|
||||||
|
{ fillRemaining: true },
|
||||||
|
null,
|
||||||
|
onBeforeRewardsPhase
|
||||||
|
);
|
||||||
|
|
||||||
|
return initBattleWithEnemyConfig(scene, config);
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.withOption(
|
||||||
|
new MysteryEncounterOptionBuilder()
|
||||||
|
.withDialogue({
|
||||||
|
buttonLabel: "mysteryEncounter:training_session_option_3_label",
|
||||||
|
buttonTooltip: "mysteryEncounter:training_session_option_3_tooltip",
|
||||||
|
secondOptionPrompt:
|
||||||
|
"mysteryEncounter:training_session_option_3_select_prompt",
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:training_session_option_selected_message",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||||
|
// Open menu for selecting pokemon and ability to learn
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||||
|
// Return the options for ability selection
|
||||||
|
const speciesForm = !!pokemon.getFusionSpeciesForm()
|
||||||
|
? pokemon.getFusionSpeciesForm()
|
||||||
|
: pokemon.getSpeciesForm();
|
||||||
|
const abilityCount = speciesForm.getAbilityCount();
|
||||||
|
const abilities = new Array(abilityCount)
|
||||||
|
.fill(null)
|
||||||
|
.map((val, i) => allAbilities[speciesForm.getAbility(i)]);
|
||||||
|
return abilities.map((ability: Ability, index) => {
|
||||||
|
const option: OptionSelectItem = {
|
||||||
|
label: ability.name,
|
||||||
|
handler: () => {
|
||||||
|
// Pokemon and ability selected
|
||||||
|
encounter.setDialogueToken("ability", ability.name);
|
||||||
|
encounter.misc = {
|
||||||
|
playerPokemon: pokemon,
|
||||||
|
abilityIndex: index,
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
onHover: () => {
|
||||||
|
scene.ui.showText(ability.description);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return option;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return selectPokemonForOption(scene, onPokemonSelected);
|
||||||
|
})
|
||||||
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
const playerPokemon: PlayerPokemon = encounter.misc.playerPokemon;
|
||||||
|
|
||||||
|
// Spawn hard training session with chosen pokemon
|
||||||
|
// Every 30 waves, add +1 boss segment, capping at 6
|
||||||
|
// Also starts with +1 to all stats
|
||||||
|
const segments = Math.min(
|
||||||
|
2 + Math.floor(scene.currentBattle.waveIndex / 30),
|
||||||
|
6
|
||||||
|
);
|
||||||
|
const modifiers = new ModifiersHolder();
|
||||||
|
const config = getEnemyConfig(
|
||||||
|
scene,
|
||||||
|
playerPokemon,
|
||||||
|
segments,
|
||||||
|
modifiers
|
||||||
|
);
|
||||||
|
config.pokemonConfigs[0].tags = [
|
||||||
|
BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON,
|
||||||
|
];
|
||||||
|
scene.removePokemonFromPlayerParty(playerPokemon, false);
|
||||||
|
|
||||||
|
const onBeforeRewardsPhase = () => {
|
||||||
|
scene.queueMessage(
|
||||||
|
getEncounterText(
|
||||||
|
scene,
|
||||||
|
"mysteryEncounter:training_session_battle_finished_3"
|
||||||
|
),
|
||||||
|
null,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
// Add the pokemon back to party with ability change
|
||||||
|
const abilityIndex = encounter.misc.abilityIndex;
|
||||||
|
if (!!playerPokemon.getFusionSpeciesForm()) {
|
||||||
|
playerPokemon.fusionAbilityIndex = abilityIndex;
|
||||||
|
if (
|
||||||
|
speciesStarters.hasOwnProperty(
|
||||||
|
playerPokemon.fusionSpecies.speciesId
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
scene.gameData.starterData[
|
||||||
|
playerPokemon.fusionSpecies.speciesId
|
||||||
|
].abilityAttr |=
|
||||||
|
abilityIndex !== 1 || playerPokemon.fusionSpecies.ability2
|
||||||
|
? Math.pow(2, playerPokemon.fusionAbilityIndex)
|
||||||
|
: AbilityAttr.ABILITY_HIDDEN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
playerPokemon.abilityIndex = abilityIndex;
|
||||||
|
if (
|
||||||
|
speciesStarters.hasOwnProperty(playerPokemon.species.speciesId)
|
||||||
|
) {
|
||||||
|
scene.gameData.starterData[
|
||||||
|
playerPokemon.species.speciesId
|
||||||
|
].abilityAttr |=
|
||||||
|
abilityIndex !== 1 || playerPokemon.species.ability2
|
||||||
|
? Math.pow(2, playerPokemon.abilityIndex)
|
||||||
|
: AbilityAttr.ABILITY_HIDDEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
playerPokemon.getAbility();
|
||||||
|
playerPokemon.calculateStats();
|
||||||
|
scene.gameData.setPokemonCaught(playerPokemon, false);
|
||||||
|
|
||||||
|
// Add pokemon and mods back
|
||||||
|
scene.getParty().push(playerPokemon);
|
||||||
|
for (const mod of modifiers.value) {
|
||||||
|
scene.addModifier(mod, true, false, false, true);
|
||||||
|
}
|
||||||
|
scene.updateModifiers(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
setEncounterRewards(
|
||||||
|
scene,
|
||||||
|
{ fillRemaining: true },
|
||||||
|
null,
|
||||||
|
onBeforeRewardsPhase
|
||||||
|
);
|
||||||
|
|
||||||
|
return initBattleWithEnemyConfig(scene, config);
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
function getEnemyConfig(
|
||||||
|
scene: BattleScene,
|
||||||
|
playerPokemon: PlayerPokemon,
|
||||||
|
segments: number,
|
||||||
|
modifiers: ModifiersHolder
|
||||||
|
): EnemyPartyConfig {
|
||||||
playerPokemon.resetSummonData();
|
playerPokemon.resetSummonData();
|
||||||
|
|
||||||
// Passes modifiers by reference
|
// Passes modifiers by reference
|
||||||
modifiers.value = scene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
modifiers.value = scene.findModifiers(
|
||||||
&& (m as PokemonHeldItemModifier).pokemonId === playerPokemon.id) as PokemonHeldItemModifier[];
|
(m) =>
|
||||||
const modifierTypes = modifiers.value.map(mod => mod.type) as PokemonHeldItemModifierType[];
|
m instanceof PokemonHeldItemModifier &&
|
||||||
|
(m as PokemonHeldItemModifier).pokemonId === playerPokemon.id
|
||||||
|
) as PokemonHeldItemModifier[];
|
||||||
|
const modifierTypes = modifiers.value.map(
|
||||||
|
(mod) => mod.type
|
||||||
|
) as PokemonHeldItemModifierType[];
|
||||||
|
|
||||||
const data = new PokemonData(playerPokemon);
|
const data = new PokemonData(playerPokemon);
|
||||||
return {
|
return {
|
||||||
|
@ -295,15 +439,14 @@ function getEnemyConfig(scene: BattleScene, playerPokemon: PlayerPokemon, segmen
|
||||||
formIndex: playerPokemon.formIndex,
|
formIndex: playerPokemon.formIndex,
|
||||||
level: playerPokemon.level,
|
level: playerPokemon.level,
|
||||||
dataSource: data,
|
dataSource: data,
|
||||||
modifierTypes: modifierTypes
|
modifierTypes: modifierTypes,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class ModifiersHolder {
|
class ModifiersHolder {
|
||||||
public value: PokemonHeldItemModifier[] = [];
|
public value: PokemonHeldItemModifier[] = [];
|
||||||
|
|
||||||
constructor() {
|
constructor() {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
|
||||||
import { TrainingSessionDialogue } from "#app/data/mystery-encounters/dialogue/training-session-dialogue";
|
|
||||||
import { TextStyle } from "#app/ui/text";
|
import { TextStyle } from "#app/ui/text";
|
||||||
|
|
||||||
export class TextDisplay {
|
export class TextDisplay {
|
||||||
|
@ -77,5 +75,4 @@ export default class MysteryEncounterDialogue {
|
||||||
export const allMysteryEncounterDialogue: { [encounterType: number]: MysteryEncounterDialogue } = {};
|
export const allMysteryEncounterDialogue: { [encounterType: number]: MysteryEncounterDialogue } = {};
|
||||||
|
|
||||||
export function initMysteryEncounterDialogue() {
|
export function initMysteryEncounterDialogue() {
|
||||||
allMysteryEncounterDialogue[MysteryEncounterType.TRAINING_SESSION] = TrainingSessionDialogue;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue