start clowning around encounter

This commit is contained in:
ImperialSympathizer 2024-08-03 13:38:06 -04:00
parent e3ec09f88b
commit de8a5b8987
8 changed files with 239 additions and 9 deletions

View File

@ -1430,7 +1430,7 @@ export default class BattleScene extends SceneBase {
const wave = waveIndex || this.currentBattle?.waveIndex || 0;
this.waveSeed = Utils.shiftCharCodes(this.seed, wave);
Phaser.Math.RND.sow([ this.waveSeed ]);
// console.log("Wave Seed:", this.waveSeed, wave);
console.log("Wave Seed:", this.waveSeed, wave);
this.rngCounter = 0;
}

View File

@ -0,0 +1,181 @@
import {
EnemyPartyConfig,
initBattleWithEnemyConfig,
setEncounterRewards,
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import {
trainerConfigs,
TrainerPartyCompoundTemplate,
TrainerPartyTemplate,
} from "#app/data/trainer-config";
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 BattleScene from "#app/battle-scene";
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { Species } from "#enums/species";
import { TrainerType } from "#enums/trainer-type";
import { getPokemonSpecies } from "#app/data/pokemon-species";
/** the i18n namespace for the encounter */
const namespace = "mysteryEncounter:clowningAround";
/**
* Clowning Around encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/69 | GitHub Issue #69}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/
export const ClowningAroundEncounter: IMysteryEncounter =
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.CLOWNING_AROUND)
.withEncounterTier(MysteryEncounterTier.ULTRA)
.withSceneWaveRangeRequirement(10, 180) // waves 10 to 180
.withIntroSpriteConfigs([
{
spriteKey: Species.MR_MIME.toString(),
fileRoot: "pokemon",
hasShadow: true,
repeat: true,
x: -25,
tint: 0.3,
y: -3,
yShadow: -3
},
{
spriteKey: Species.BLACEPHALON.toString(),
fileRoot: "pokemon/exp",
hasShadow: true,
repeat: true,
x: 25,
tint: 0.3,
y: -3,
yShadow: -3
},
{
spriteKey: "harlequin",
fileRoot: "trainer",
hasShadow: true,
x: 0
},
])
.withIntroDialogue([
{
text: `${namespace}.intro`,
},
{
text: `${namespace}.intro_dialogue`,
speaker: `${namespace}.speaker`
},
])
.withOnInit((scene: BattleScene) => {
const encounter = scene.currentBattle.mysteryEncounter;
// Clown 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 clownTrainerType = TrainerType.HARLEQUIN;
const clownPartyTemplate = new TrainerPartyCompoundTemplate(
new TrainerPartyTemplate(1, PartyMemberStrength.STRONG),
new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER),
new TrainerPartyTemplate(1, PartyMemberStrength.STRONG));
const clownConfig = trainerConfigs[clownTrainerType].copy();
clownConfig.setPartyTemplates(clownPartyTemplate);
clownConfig.partyTemplateFunc = null; // Overrides party template func
encounter.enemyPartyConfigs.push({
trainerConfig: clownConfig,
pokemonConfigs: [ // Overrides first 2 pokemon to be Mr. Mime and Blacephalon
{
species: getPokemonSpecies(Species.MR_MIME),
isBoss: false
},
{
species: getPokemonSpecies(Species.BLACEPHALON),
isBoss: true
},
]
});
return true;
})
.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 (scene: BattleScene) => {
const encounter = scene.currentBattle.mysteryEncounter;
// Spawn battle
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.TM_COMMON, modifierTypes.TM_GREAT, modifierTypes.MEMORY_MUSHROOM], fillRemaining: true });
await initBattleWithEnemyConfig(scene, config);
}
)
.withSimpleOption(
{
buttonLabel: `${namespace}.option.2.label`,
buttonTooltip: `${namespace}.option.2.tooltip`,
selected: [
{
text: `${namespace}.option.selected`,
},
],
},
async (scene: BattleScene) => {
const encounter = scene.currentBattle.mysteryEncounter;
// Spawn hard fight with ULTRA/GREAT reward (can improve with luck)
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[1];
setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], fillRemaining: true });
// Seed offsets to remove possibility of different trainers having exact same teams
let ret;
scene.executeWithSeedOffset(() => {
ret = initBattleWithEnemyConfig(scene, config);
}, scene.currentBattle.waveIndex * 100);
return ret;
}
)
.withSimpleOption(
{
buttonLabel: `${namespace}.option.3.label`,
buttonTooltip: `${namespace}.option.3.tooltip`,
selected: [
{
text: `${namespace}.option.selected`,
},
],
},
async (scene: BattleScene) => {
const encounter = scene.currentBattle.mysteryEncounter;
// Spawn brutal fight with ROGUE/ULTRA/GREAT reward (can improve with luck)
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[2];
// To avoid player level snowballing from picking this option
encounter.expMultiplier = 0.9;
setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT], fillRemaining: true });
// Seed offsets to remove possibility of different trainers having exact same teams
let ret;
scene.executeWithSeedOffset(() => {
ret = initBattleWithEnemyConfig(scene, config);
}, scene.currentBattle.waveIndex * 1000);
return ret;
}
)
.withOutroDialogue([
{
text: `${namespace}.outro`,
},
])
.build();

View File

@ -21,6 +21,7 @@ import { AbsoluteAvariceEncounter } from "#app/data/mystery-encounters/encounter
import { ATrainersTestEncounter } from "#app/data/mystery-encounters/encounters/a-trainers-test-encounter";
import { TrashToTreasureEncounter } from "#app/data/mystery-encounters/encounters/trash-to-treasure-encounter";
import { BerriesAboundEncounter } from "#app/data/mystery-encounters/encounters/berries-abound-encounter";
import { ClowningAroundEncounter } from "#app/data/mystery-encounters/encounters/clowing-around-encounter";
// Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / 256
export const BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT = 1;
@ -141,7 +142,7 @@ const humanTransitableBiomeEncounters: MysteryEncounterType[] = [
MysteryEncounterType.MYSTERIOUS_CHALLENGERS,
MysteryEncounterType.SHADY_VITAMIN_DEALER,
MysteryEncounterType.THE_POKEMON_SALESMAN,
MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE
MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE,
];
const civilizationBiomeEncounters: MysteryEncounterType[] = [
@ -159,7 +160,8 @@ const anyBiomeEncounters: MysteryEncounterType[] = [
MysteryEncounterType.DELIBIRDY,
MysteryEncounterType.A_TRAINERS_TEST,
MysteryEncounterType.TRASH_TO_TREASURE,
MysteryEncounterType.BERRIES_ABOUND
MysteryEncounterType.BERRIES_ABOUND,
MysteryEncounterType.CLOWNING_AROUND
];
/**
@ -249,6 +251,7 @@ export function initMysteryEncounters() {
allMysteryEncounters[MysteryEncounterType.A_TRAINERS_TEST] = ATrainersTestEncounter;
allMysteryEncounters[MysteryEncounterType.TRASH_TO_TREASURE] = TrashToTreasureEncounter;
allMysteryEncounters[MysteryEncounterType.BERRIES_ABOUND] = BerriesAboundEncounter;
allMysteryEncounters[MysteryEncounterType.CLOWNING_AROUND] = ClowningAroundEncounter;
// Add extreme encounters to biome map
extremeBiomeEncounters.forEach(encounter => {

View File

@ -12,6 +12,7 @@ import PokemonData from "#app/system/pokemon-data";
import { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import { PartyOption, PartyUiMode } from "#app/ui/party-ui-handler";
import { Mode } from "#app/ui/ui";
import * as Utils from "#app/utils";
import { isNullOrUndefined } from "#app/utils";
import { BattlerTagType } from "#enums/battler-tag-type";
import { Biome } from "#enums/biome";
@ -19,7 +20,6 @@ import { TrainerType } from "#enums/trainer-type";
import i18next from "i18next";
import BattleScene from "#app/battle-scene";
import Trainer, { TrainerVariant } from "#app/field/trainer";
import * as Utils from "#app/utils";
import { Gender } from "#app/data/gender";
import { Nature } from "#app/data/nature";
import { Moves } from "#enums/moves";
@ -152,7 +152,17 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
let isBoss = false;
if (!loaded) {
if (trainerType || trainerConfig) {
battle.enemyParty[e] = battle.trainer.genPartyMember(e);
// Allows overriding a trainer's pokemon to use specific species/data
if (e < partyConfig?.pokemonConfigs?.length) {
const config = partyConfig?.pokemonConfigs?.[e];
level = config.level ? config.level : level;
dataSource = config.dataSource;
enemySpecies = config.species;
isBoss = config.isBoss;
battle.enemyParty[e] = scene.addEnemyPokemon(enemySpecies, level, TrainerSlot.TRAINER, isBoss, dataSource);
} else {
battle.enemyParty[e] = battle.trainer.genPartyMember(e);
}
} else {
if (e < partyConfig?.pokemonConfigs?.length) {
const config = partyConfig?.pokemonConfigs?.[e];

View File

@ -18,5 +18,6 @@ export enum MysteryEncounterType {
ABSOLUTE_AVARICE,
A_TRAINERS_TEST,
TRASH_TO_TREASURE,
BERRIES_ABOUND
BERRIES_ABOUND,
CLOWNING_AROUND
}

View File

@ -18,6 +18,7 @@ import { absoluteAvariceDialogue } from "#app/locales/en/mystery-encounters/abso
import { aTrainersTestDialogue } from "#app/locales/en/mystery-encounters/a-trainers-test-dialogue";
import { trashToTreasureDialogue } from "#app/locales/en/mystery-encounters/trash-to-treasure-dialogue";
import { berriesAboundDialogue } from "#app/locales/en/mystery-encounters/berries-abound-dialogue";
import { clowningAroundDialogue } from "#app/locales/en/mystery-encounters/clowning-around-dialogue";
/**
* Patterns that can be used:
@ -60,5 +61,6 @@ export const mysteryEncounter = {
absoluteAvarice: absoluteAvariceDialogue,
aTrainersTest: aTrainersTestDialogue,
trashToTreasure: trashToTreasureDialogue,
berriesAbound: berriesAboundDialogue
berriesAbound: berriesAboundDialogue,
clowningAround: clowningAroundDialogue
} as const;

View File

@ -0,0 +1,33 @@
export const clowningAroundDialogue = {
intro: "It's...@d{64} a clown?",
speaker: "Clown",
intro_dialogue: `Bumbling buffoon,\nbrace for a brilliant battle!
$Youll be beaten by this brawling busker!\nBring it!`,
title: "Clowning Around",
description: "The clown seems eager to goad you into a battle, but to what end?\n\nSomething is off about this encounter.",
query: "What will you do?",
option: {
1: {
label: "Battle the Clown",
tooltip: "(-) Strange Battle\n(?) Affects Pokémon Abilities",
selected: "Your pitiful Pokémon are poised for a pathetic performance!"
},
2: {
label: "Remain Unprovoked",
tooltip: "(-) Upsets the Clown\n(?) Affects Pokémon Items",
selected: "Dismal dodger, you deny a delightful duel?\nFeel my fury!",
selected_2: `The clown's Blacephalon uses Trick!
All of your {{switchPokemon}}'s items were randomly swapped!`,
selected_3: "Flustered fool, fall for my flawless deception!",
},
3: {
label: "Return the Insults",
tooltip: "(-) Upsets the Clown\n(?) Affects Pokémon Types",
selected: "I'm appalled at your absurd antics!\nTaste my temper!",
selected_2: `The clown's Blacephalon uses\na move you've never seen before!
All of your team's types were randomly swapped!`,
selected_3: "Flustered fool, fall for my flawless deception!",
},
},
outro: "The clown and his cohorts\ndisappear in a puff of smoke."
};

View File

@ -127,9 +127,9 @@ class DefaultOverrides {
// -------------------------
// 1 to 256, set to null to ignore
readonly MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = null;
readonly MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = 256;
readonly MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier = null;
readonly MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = null;
readonly MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = MysteryEncounterType.CLOWNING_AROUND;
// -------------------------
// MODIFIER / ITEM OVERRIDES