migrate fight-or-flight encounter

This commit is contained in:
Felix Staud 2024-07-11 13:54:44 -07:00
parent ce73c38e33
commit 1713395091
3 changed files with 202 additions and 142 deletions

View File

@ -1,38 +0,0 @@
import MysteryEncounterDialogue from "#app/data/mystery-encounters/mystery-encounter-dialogue";
export const FightOrFlightDialogue: MysteryEncounterDialogue = {
intro: [
{
text: "mysteryEncounter:fight_or_flight_intro_message"
}
],
encounterOptionsDialogue: {
title: "mysteryEncounter:fight_or_flight_title",
description: "mysteryEncounter:fight_or_flight_description",
query: "mysteryEncounter:fight_or_flight_query",
options: [
{
buttonLabel: "mysteryEncounter:fight_or_flight_option_1_label",
buttonTooltip: "mysteryEncounter:fight_or_flight_option_1_tooltip",
selected: [
{
text: "mysteryEncounter:fight_or_flight_option_1_selected_message"
}
]
},
{
buttonLabel: "mysteryEncounter:fight_or_flight_option_2_label",
buttonTooltip: "mysteryEncounter:fight_or_flight_option_2_tooltip"
},
{
buttonLabel: "mysteryEncounter:fight_or_flight_option_3_label",
buttonTooltip: "mysteryEncounter:fight_or_flight_option_3_tooltip",
selected: [
{
text: "mysteryEncounter:fight_or_flight_option_3_selected"
}
]
}
]
}
};

View File

@ -1,11 +1,14 @@
import { BattleStat } from "#app/data/battle-stat"; import { BattleStat } from "#app/data/battle-stat";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
import { import {
EnemyPartyConfig, EnemyPartyConfig,
initBattleWithEnemyConfig, initBattleWithEnemyConfig,
leaveEncounterWithoutBattle, queueEncounterMessage, leaveEncounterWithoutBattle,
queueEncounterMessage,
setEncounterRewards, setEncounterRewards,
showEncounterText showEncounterText,
} from "#app/data/mystery-encounters/mystery-encounter-utils"; } from "#app/data/mystery-encounters/mystery-encounter-utils";
import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
import Pokemon from "#app/field/pokemon"; import Pokemon from "#app/field/pokemon";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import { import {
@ -13,41 +16,71 @@ import {
getPlayerModifierTypeOptions, getPlayerModifierTypeOptions,
ModifierPoolType, ModifierPoolType,
ModifierTypeOption, ModifierTypeOption,
regenerateModifierPoolThresholds regenerateModifierPoolThresholds,
} from "#app/modifier/modifier-type"; } from "#app/modifier/modifier-type";
import { StatChangePhase } from "#app/phases"; import { StatChangePhase } from "#app/phases";
import { randSeedInt } from "#app/utils"; import { randSeedInt } 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 { MoveRequirement } from "../mystery-encounter-requirements"; import { MoveRequirement } from "../mystery-encounter-requirements";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder /** the i18n namespace for the encounter */
.withEncounterType(MysteryEncounterType.FIGHT_OR_FLIGHT) const namespace = "mysteryEncounter:fight_or_flight";
export const FightOrFlightEncounter: MysteryEncounter =
MysteryEncounterBuilder.withEncounterType(
MysteryEncounterType.FIGHT_OR_FLIGHT
)
.withEncounterTier(MysteryEncounterTier.COMMON) .withEncounterTier(MysteryEncounterTier.COMMON)
.withIntroSpriteConfigs([]) // Set in onInit()
.withSceneWaveRangeRequirement(10, 180) // waves 10 to 180 .withSceneWaveRangeRequirement(10, 180) // waves 10 to 180
.withCatchAllowed(true) .withCatchAllowed(true)
.withHideWildIntroMessage(true) .withHideWildIntroMessage(true)
.withIntroSpriteConfigs([]) // Set in onInit()
.withIntroDialogue([
{
text: `${namespace}_intro_message`,
},
])
.withOnInit((scene: BattleScene) => { .withOnInit((scene: BattleScene) => {
const encounter = scene.currentBattle.mysteryEncounter; const encounter = scene.currentBattle.mysteryEncounter;
// Calculate boss mon // Calculate boss mon
const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, scene.currentBattle.waveIndex, 0, getPartyLuckValue(scene.getParty()), true); const bossSpecies = scene.arena.randomSpecies(
scene.currentBattle.waveIndex,
scene.currentBattle.waveIndex,
0,
getPartyLuckValue(scene.getParty()),
true
);
const config: EnemyPartyConfig = { const config: EnemyPartyConfig = {
levelAdditiveMultiplier: 1, levelAdditiveMultiplier: 1,
pokemonConfigs: [{ species: bossSpecies, isBoss: true }] pokemonConfigs: [{ species: bossSpecies, isBoss: true }],
}; };
encounter.enemyPartyConfigs = [config]; encounter.enemyPartyConfigs = [config];
// Calculate item // Calculate item
// 10-60 GREAT, 60-110 ULTRA, 110-160 ROGUE, 160-180 MASTER // 10-60 GREAT, 60-110 ULTRA, 110-160 ROGUE, 160-180 MASTER
const tier = scene.currentBattle.waveIndex > 160 ? ModifierTier.MASTER : scene.currentBattle.waveIndex > 110 ? ModifierTier.ROGUE : scene.currentBattle.waveIndex > 60 ? ModifierTier.ULTRA : ModifierTier.GREAT; const tier =
regenerateModifierPoolThresholds(scene.getParty(), ModifierPoolType.PLAYER, 0); // refresh player item pool scene.currentBattle.waveIndex > 160
const item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [tier] })[0]; ? ModifierTier.MASTER
: scene.currentBattle.waveIndex > 110
? ModifierTier.ROGUE
: scene.currentBattle.waveIndex > 60
? ModifierTier.ULTRA
: ModifierTier.GREAT;
regenerateModifierPoolThresholds(
scene.getParty(),
ModifierPoolType.PLAYER,
0
); // refresh player item pool
const item = getPlayerModifierTypeOptions(1, scene.getParty(), [], {
guaranteedModifierTiers: [tier],
})[0];
encounter.setDialogueToken("itemName", item.type.name); encounter.setDialogueToken("itemName", item.type.name);
encounter.misc = item; encounter.misc = item;
@ -59,7 +92,7 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder
x: 35, x: 35,
y: -5, y: -5,
scale: 0.75, scale: 0.75,
isItem: true isItem: true,
}, },
{ {
spriteKey: bossSpecies.speciesId.toString(), spriteKey: bossSpecies.speciesId.toString(),
@ -67,8 +100,8 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder
hasShadow: true, hasShadow: true,
tint: 0.25, tint: 0.25,
x: -5, x: -5,
repeat: true repeat: true,
} },
]; ];
// If player has a stealing move, they succeed automatically // If player has a stealing move, they succeed automatically
@ -76,33 +109,66 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder
const primaryPokemon = encounter.options[1].primaryPokemon; const primaryPokemon = encounter.options[1].primaryPokemon;
if (primaryPokemon) { if (primaryPokemon) {
// Use primaryPokemon to execute the thievery // Use primaryPokemon to execute the thievery
encounter.dialogue.encounterOptionsDialogue.options[1].buttonTooltip = "mysteryEncounter:fight_or_flight_option_2_steal_tooltip"; encounter.options[1].dialogue.buttonTooltip = `${namespace}_option_2_steal_tooltip`;
} else { } else {
encounter.dialogue.encounterOptionsDialogue.options[1].buttonTooltip = "mysteryEncounter:fight_or_flight_option_2_tooltip"; encounter.options[1].dialogue.buttonTooltip = `${namespace}_option_2_tooltip`;
} }
return true; return true;
}) })
.withSimpleOption(async (scene: BattleScene) => { .withTitle(`${namespace}_title`)
.withDescription(`${namespace}_description`)
.withQuery(`${namespace}_query`)
.withSimpleOption(
{
buttonLabel: `${namespace}_option_1_label`,
buttonTooltip: `${namespace}_option_1_tooltip`,
selected: [
{
text: `${namespace}_option_1_selected_message`,
},
],
},
async (scene: BattleScene) => {
// Pick battle // Pick battle
const item = scene.currentBattle.mysteryEncounter.misc as ModifierTypeOption; const item = scene.currentBattle.mysteryEncounter
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false }); .misc as ModifierTypeOption;
await initBattleWithEnemyConfig(scene, scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0]); setEncounterRewards(scene, {
}) guaranteedModifierTypeOptions: [item],
.withOption(new MysteryEncounterOptionBuilder() fillRemaining: false,
});
await initBattleWithEnemyConfig(
scene,
scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0]
);
}
)
.withOption(
new MysteryEncounterOptionBuilder()
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically .withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
.withDisabledOnRequirementsNotMet(false) .withDisabledOnRequirementsNotMet(false)
.withDialogue({
buttonLabel: `${namespace}_option_2_label`,
buttonTooltip: `${namespace}_option_2_tooltip`,
})
.withOptionPhase(async (scene: BattleScene) => { .withOptionPhase(async (scene: BattleScene) => {
// Pick steal // Pick steal
const encounter = scene.currentBattle.mysteryEncounter; const encounter = scene.currentBattle.mysteryEncounter;
const item = scene.currentBattle.mysteryEncounter.misc as ModifierTypeOption; const item = scene.currentBattle.mysteryEncounter
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false }); .misc as ModifierTypeOption;
setEncounterRewards(scene, {
guaranteedModifierTypeOptions: [item],
fillRemaining: false,
});
// If player has a stealing move, they succeed automatically // If player has a stealing move, they succeed automatically
const primaryPokemon = encounter.options[1].primaryPokemon; const primaryPokemon = encounter.options[1].primaryPokemon;
if (primaryPokemon) { if (primaryPokemon) {
// Use primaryPokemon to execute the thievery // Use primaryPokemon to execute the thievery
await showEncounterText(scene, "mysteryEncounter:fight_or_flight_option_2_steal_result"); await showEncounterText(
scene,
`${namespace}_option_2_steal_result`
);
leaveEncounterWithoutBattle(scene); leaveEncounterWithoutBattle(scene);
return; return;
} }
@ -110,26 +176,60 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder
const roll = randSeedInt(16); const roll = randSeedInt(16);
if (roll > 6) { if (roll > 6) {
// Noticed and attacked by boss, gets +1 to all stats at start of fight (62.5%) // Noticed and attacked by boss, gets +1 to all stats at start of fight (62.5%)
const config = scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0]; const config =
config.pokemonConfigs[0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON]; scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0];
config.pokemonConfigs[0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => { config.pokemonConfigs[0].tags = [
pokemon.scene.currentBattle.mysteryEncounter.setDialogueToken("enemyPokemon", pokemon.name); BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON,
queueEncounterMessage(pokemon.scene, "mysteryEncounter:fight_or_flight_boss_enraged"); ];
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD], 1)); config.pokemonConfigs[0].mysteryEncounterBattleEffects = (
pokemon: Pokemon
) => {
pokemon.scene.currentBattle.mysteryEncounter.setDialogueToken(
"enemyPokemon",
pokemon.name
);
queueEncounterMessage(pokemon.scene, `${namespace}_boss_enraged`);
pokemon.scene.unshiftPhase(
new StatChangePhase(
pokemon.scene,
pokemon.getBattlerIndex(),
true,
[
BattleStat.ATK,
BattleStat.DEF,
BattleStat.SPATK,
BattleStat.SPDEF,
BattleStat.SPD,
],
1
)
);
}; };
await showEncounterText(scene, "mysteryEncounter:fight_or_flight_option_2_bad_result"); await showEncounterText(scene, `${namespace}_option_2_bad_result`);
await initBattleWithEnemyConfig(scene, config); await initBattleWithEnemyConfig(scene, config);
} else { } else {
// Steal item (37.5%) // Steal item (37.5%)
// Display result message then proceed to rewards // Display result message then proceed to rewards
await showEncounterText(scene, "mysteryEncounter:fight_or_flight_option_2_good_result"); await showEncounterText(scene, `${namespace}_option_2_good_result`);
leaveEncounterWithoutBattle(scene); leaveEncounterWithoutBattle(scene);
} }
}) })
.build()) .build()
.withSimpleOption(async (scene: BattleScene) => { )
.withSimpleOption(
{
buttonLabel: `${namespace}_option_3_label`,
buttonTooltip: `${namespace}_option_3_tooltip`,
selected: [
{
text: `${namespace}_option_3_selected`,
},
],
},
async (scene: BattleScene) => {
// Leave encounter with no rewards or exp // Leave encounter with no rewards or exp
leaveEncounterWithoutBattle(scene, true); leaveEncounterWithoutBattle(scene, true);
return true; return true;
}) }
)
.build(); .build();

View File

@ -1,7 +1,6 @@
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { MysteriousChallengersDialogue } from "#app/data/mystery-encounters/dialogue/mysterious-challengers-dialogue"; import { MysteriousChallengersDialogue } from "#app/data/mystery-encounters/dialogue/mysterious-challengers-dialogue";
import { MysteriousChestDialogue } from "#app/data/mystery-encounters/dialogue/mysterious-chest-dialogue"; import { MysteriousChestDialogue } from "#app/data/mystery-encounters/dialogue/mysterious-chest-dialogue";
import { FightOrFlightDialogue } from "#app/data/mystery-encounters/dialogue/fight-or-flight-dialogue";
import { TrainingSessionDialogue } from "#app/data/mystery-encounters/dialogue/training-session-dialogue"; import { TrainingSessionDialogue } from "#app/data/mystery-encounters/dialogue/training-session-dialogue";
import { SleepingSnorlaxDialogue } from "./dialogue/sleeping-snorlax-dialogue"; import { SleepingSnorlaxDialogue } from "./dialogue/sleeping-snorlax-dialogue";
import { ShadyVitaminDealerDialogue } from "#app/data/mystery-encounters/dialogue/shady-vitamin-dealer"; import { ShadyVitaminDealerDialogue } from "#app/data/mystery-encounters/dialogue/shady-vitamin-dealer";
@ -84,7 +83,6 @@ export const allMysteryEncounterDialogue: { [encounterType: number]: MysteryEnco
export function initMysteryEncounterDialogue() { export function initMysteryEncounterDialogue() {
allMysteryEncounterDialogue[MysteryEncounterType.MYSTERIOUS_CHALLENGERS] = MysteriousChallengersDialogue; allMysteryEncounterDialogue[MysteryEncounterType.MYSTERIOUS_CHALLENGERS] = MysteriousChallengersDialogue;
allMysteryEncounterDialogue[MysteryEncounterType.MYSTERIOUS_CHEST] = MysteriousChestDialogue; allMysteryEncounterDialogue[MysteryEncounterType.MYSTERIOUS_CHEST] = MysteriousChestDialogue;
allMysteryEncounterDialogue[MysteryEncounterType.FIGHT_OR_FLIGHT] = FightOrFlightDialogue;
allMysteryEncounterDialogue[MysteryEncounterType.TRAINING_SESSION] = TrainingSessionDialogue; allMysteryEncounterDialogue[MysteryEncounterType.TRAINING_SESSION] = TrainingSessionDialogue;
allMysteryEncounterDialogue[MysteryEncounterType.SLEEPING_SNORLAX] = SleepingSnorlaxDialogue; allMysteryEncounterDialogue[MysteryEncounterType.SLEEPING_SNORLAX] = SleepingSnorlaxDialogue;
allMysteryEncounterDialogue[MysteryEncounterType.SHADY_VITAMIN_DEALER] = ShadyVitaminDealerDialogue; allMysteryEncounterDialogue[MysteryEncounterType.SHADY_VITAMIN_DEALER] = ShadyVitaminDealerDialogue;