safari zone

This commit is contained in:
ImperialSympathizer 2024-07-12 17:33:55 -04:00
parent 5cb02df0e0
commit a72e76b6fd
3 changed files with 182 additions and 4 deletions

View File

@ -0,0 +1,172 @@
import {
getHighestLevelPlayerPokemon,
koPlayerPokemon,
leaveEncounterWithoutBattle,
queueEncounterMessage,
setEncounterRewards,
showEncounterText,
} from "#app/data/mystery-encounters/mystery-encounter-utils";
import { ModifierTier } from "#app/modifier/modifier-tier";
import { GameOverPhase } from "#app/phases";
import { randSeedInt } from "#app/utils";
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "../../../battle-scene";
import IMysteryEncounter, {
MysteryEncounterBuilder,
MysteryEncounterTier,
} from "../mystery-encounter";
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
/** the i18n namespace for the encounter */
const namespace = "mysteryEncounter:safari_zone";
export const SafariZoneEncounter: IMysteryEncounter =
MysteryEncounterBuilder.withEncounterType(
MysteryEncounterType.SAFARI_ZONE
)
.withEncounterTier(MysteryEncounterTier.GREAT)
.withSceneWaveRangeRequirement(10, 180) // waves 2 to 180
.withHideIntroVisuals(false)
.withIntroSpriteConfigs([
{
spriteKey: "chest_blue",
fileRoot: "mystery-encounters",
hasShadow: true,
x: 4,
y: 8,
disableAnimation: true, // Re-enabled after option select
},
])
.withIntroDialogue([
{
text: `mysteryEncounter:${namespace}_intro_message`,
},
])
.withTitle(`mysteryEncounter:${namespace}_title`)
.withDescription(`mysteryEncounter:${namespace}_description`)
.withQuery(`mysteryEncounter:${namespace}_query`)
.withOption(
new MysteryEncounterOptionBuilder()
.withOptionMode(EncounterOptionMode.DEFAULT)
.withDialogue({
buttonLabel: "mysteryEncounter:${namespace}_option_1_label",
buttonTooltip: "mysteryEncounter:${namespace}_option_1_tooltip",
selected: [
{
text: "mysteryEncounter:${namespace}_option_1_selected_message",
},
],
})
.withPreOptionPhase(async (scene: BattleScene) => {
// Play animation
const introVisuals =
scene.currentBattle.mysteryEncounter.introVisuals;
introVisuals.spriteConfigs[0].disableAnimation = false;
introVisuals.playAnim();
})
.withOptionPhase(async (scene: BattleScene) => {
// Open the chest
const roll = randSeedInt(100);
if (roll > 60) {
// Choose between 2 COMMON / 2 GREAT tier items (40%)
setEncounterRewards(scene, {
guaranteedModifierTiers: [
ModifierTier.COMMON,
ModifierTier.COMMON,
ModifierTier.GREAT,
ModifierTier.GREAT,
],
});
// Display result message then proceed to rewards
queueEncounterMessage(
scene,
"mysteryEncounter:${namespace}_option_1_normal_result"
);
leaveEncounterWithoutBattle(scene);
} else if (roll > 40) {
// Choose between 3 ULTRA tier items (20%)
setEncounterRewards(scene, {
guaranteedModifierTiers: [
ModifierTier.ULTRA,
ModifierTier.ULTRA,
ModifierTier.ULTRA,
],
});
// Display result message then proceed to rewards
queueEncounterMessage(
scene,
"mysteryEncounter:${namespace}_option_1_good_result"
);
leaveEncounterWithoutBattle(scene);
} else if (roll > 36) {
// Choose between 2 ROGUE tier items (4%)
setEncounterRewards(scene, {
guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE],
});
// Display result message then proceed to rewards
queueEncounterMessage(
scene,
"mysteryEncounter:${namespace}_option_1_great_result"
);
leaveEncounterWithoutBattle(scene);
} else if (roll > 35) {
// Choose 1 MASTER tier item (1%)
setEncounterRewards(scene, {
guaranteedModifierTiers: [ModifierTier.MASTER],
});
// Display result message then proceed to rewards
queueEncounterMessage(
scene,
"mysteryEncounter:${namespace}_option_1_amazing_result"
);
leaveEncounterWithoutBattle(scene);
} else {
// Your highest level unfainted Pok<6F>mon gets OHKO. Progress with no rewards (35%)
const highestLevelPokemon = getHighestLevelPlayerPokemon(
scene,
true
);
koPlayerPokemon(highestLevelPokemon);
scene.currentBattle.mysteryEncounter.setDialogueToken(
"pokeName",
highestLevelPokemon.name
);
// Show which Pokemon was KOed, then leave encounter with no rewards
// Does this synchronously so that game over doesn't happen over result message
await showEncounterText(
scene,
"mysteryEncounter:${namespace}_option_1_bad_result"
).then(() => {
if (
scene.getParty().filter((p) => p.isAllowedInBattle()).length ===
0
) {
// All pokemon fainted, game over
scene.clearPhaseQueue();
scene.unshiftPhase(new GameOverPhase(scene));
} else {
leaveEncounterWithoutBattle(scene);
}
});
}
})
.build()
)
.withSimpleOption(
{
buttonLabel: "mysteryEncounter:${namespace}_option_2_label",
buttonTooltip: "mysteryEncounter:${namespace}_option_2_tooltip",
selected: [
{
text: "mysteryEncounter:${namespace}_option_2_selected_message",
},
],
},
async (scene: BattleScene) => {
// Leave encounter with no rewards or exp
leaveEncounterWithoutBattle(scene, true);
return true;
}
)
.build();

View File

@ -162,10 +162,13 @@ export const mysteryEncountersByBiome = new Map<Biome, MysteryEncounterType[]>([
[Biome.TALL_GRASS, []], [Biome.TALL_GRASS, []],
[Biome.METROPOLIS, []], [Biome.METROPOLIS, []],
[Biome.FOREST, [ [Biome.FOREST, [
MysteryEncounterType.SLEEPING_SNORLAX MysteryEncounterType.SLEEPING_SNORLAX,
MysteryEncounterType.SAFARI_ZONE
]], ]],
[Biome.SEA, []], [Biome.SEA, []],
[Biome.SWAMP, []], [Biome.SWAMP, [
MysteryEncounterType.SAFARI_ZONE
]],
[Biome.BEACH, []], [Biome.BEACH, []],
[Biome.LAKE, []], [Biome.LAKE, []],
[Biome.SEABED, []], [Biome.SEABED, []],
@ -189,7 +192,9 @@ export const mysteryEncountersByBiome = new Map<Biome, MysteryEncounterType[]>([
[Biome.ABYSS, []], [Biome.ABYSS, []],
[Biome.SPACE, []], [Biome.SPACE, []],
[Biome.CONSTRUCTION_SITE, []], [Biome.CONSTRUCTION_SITE, []],
[Biome.JUNGLE, []], [Biome.JUNGLE, [
MysteryEncounterType.SAFARI_ZONE
]],
[Biome.FAIRY_CAVE, []], [Biome.FAIRY_CAVE, []],
[Biome.TEMPLE, []], [Biome.TEMPLE, []],
[Biome.SLUM, []], [Biome.SLUM, []],

View File

@ -7,5 +7,6 @@ export enum MysteryEncounterType {
TRAINING_SESSION, TRAINING_SESSION,
DEPARTMENT_STORE_SALE, DEPARTMENT_STORE_SALE,
SHADY_VITAMIN_DEALER, SHADY_VITAMIN_DEALER,
FIELD_TRIP FIELD_TRIP,
SAFARI_ZONE
} }