Updated various MEs. HeldItemManager can now generate a configuration from its items.

This commit is contained in:
Wlowscha 2025-06-19 00:23:07 +02:00
parent d161aad372
commit 2321de0983
No known key found for this signature in database
GPG Key ID: 3C8F1AD330565D04
6 changed files with 46 additions and 58 deletions

View File

@ -18,7 +18,7 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
import { Challenges } from "#enums/challenges";
import type { HeldItemPropertyMap } from "#app/field/pokemon-held-item-manager";
import type { HeldItemConfiguration } from "#app/items/held-item-data-types";
/** i18n namespace for encounter */
const namespace = "mysteryEncounters/darkDeal";
@ -148,7 +148,7 @@ export const DarkDealEncounter: MysteryEncounter = MysteryEncounterBuilder.withE
const removedPokemon = getRandomPlayerPokemon(true, false, true);
// Get all the pokemon's held items
const itemConfig = removedPokemon.heldItemManager.heldItems;
const itemConfig = removedPokemon.heldItemManager.generateHeldItemConfiguration();
globalScene.removePokemonFromPlayerParty(removedPokemon);
const encounter = globalScene.currentBattle.mysteryEncounter!;
@ -175,7 +175,7 @@ export const DarkDealEncounter: MysteryEncounter = MysteryEncounterBuilder.withE
bossTypes = singleTypeChallenges.map(c => (c.value - 1) as PokemonType);
}
const bossItemConfig: HeldItemPropertyMap = encounter.misc.itemConfig;
const bossItemConfig: HeldItemConfiguration = encounter.misc.itemConfig;
// Starter egg tier, 35/50/10/5 %odds for tiers 6/7/8/9+
const roll = randSeedInt(100);
const starterTier: number | [number, number] = roll >= 65 ? 6 : roll >= 15 ? 7 : roll >= 5 ? 8 : [9, 10];

View File

@ -46,7 +46,7 @@ import { HeldItemCategoryId, HeldItemId } from "#enums/held-item-id";
import { getNewHeldItemFromCategory } from "#app/items/held-item-pool";
import { allHeldItems } from "#app/items/all-held-items";
import { MoveUseMode } from "#enums/move-use-mode";
import { allAbilities, modifierTypes } from "#app/data/data-lists";
import { allAbilities } from "#app/data/data-lists";
/** the i18n namespace for the encounter */
const namespace = "mysteryEncounters/fieryFallout";

View File

@ -75,13 +75,13 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuil
status: [StatusEffect.SLEEP, 6], // Extra turns on timer for Snorlax's start of fight moves
nature: Nature.DOCILE,
moveSet: [MoveId.BODY_SLAM, MoveId.CRUNCH, MoveId.SLEEP_TALK, MoveId.REST],
heldItemConfig: {
[HeldItemId.SITRUS_BERRY]: { stack: 1 },
[HeldItemId.ENIGMA_BERRY]: { stack: 1 },
[HeldItemId.HP_UP]: { stack: 1 },
[HeldItemId.SOOTHE_BELL]: { stack: randSeedInt(2, 0) },
[HeldItemId.LUCKY_EGG]: { stack: randSeedInt(2, 0) },
},
heldItemConfig: [
{ entry: HeldItemId.SITRUS_BERRY, count: 1 },
{ entry: HeldItemId.ENIGMA_BERRY, count: 1 },
{ entry: HeldItemId.HP_UP, count: 1 },
{ entry: HeldItemId.SOOTHE_BELL, count: randSeedInt(2, 0) },
{ entry: HeldItemId.LUCKY_EGG, count: randSeedInt(2, 0) },
],
customPokemonData: new CustomPokemonData({ spriteScale: 1.25 }),
aiType: AiType.SMART, // Required to ensure Snorlax uses Sleep Talk while it is asleep
};

View File

@ -93,13 +93,13 @@ export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder
customPokemonData: new CustomPokemonData({ spriteScale: 1.25 }),
nature: Nature.HARDY,
moveSet: [MoveId.INFESTATION, MoveId.SALT_CURE, MoveId.GASTRO_ACID, MoveId.HEAL_ORDER],
heldItemConfig: {
[HeldItemId.SITRUS_BERRY]: { stack: 1 },
[HeldItemId.ENIGMA_BERRY]: { stack: 1 },
[HeldItemId.APICOT_BERRY]: { stack: 1 },
[HeldItemId.GANLON_BERRY]: { stack: 1 },
[HeldItemId.LUM_BERRY]: { stack: 2 },
},
heldItemConfig: [
{ entry: HeldItemId.SITRUS_BERRY, count: 1 },
{ entry: HeldItemId.ENIGMA_BERRY, count: 1 },
{ entry: HeldItemId.APICOT_BERRY, count: 1 },
{ entry: HeldItemId.GANLON_BERRY, count: 1 },
{ entry: HeldItemId.LUM_BERRY, count: 2 },
],
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
queueEncounterMessage(`${namespace}:option.2.stat_boost`);

View File

@ -24,7 +24,6 @@ import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/myst
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import type HeldModifierConfig from "#app/@types/held-modifier-config";
import i18next from "i18next";
import { getStatKey } from "#enums/stat";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
@ -101,8 +100,7 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde
// Spawn light training session with chosen pokemon
// Every 50 waves, add +1 boss segment, capping at 5
const segments = Math.min(2 + Math.floor(globalScene.currentBattle.waveIndex / 50), 5);
const modifiers = new ModifiersHolder();
const config = getEnemyConfig(playerPokemon, segments, modifiers);
const config = getEnemyConfig(playerPokemon, segments);
globalScene.removePokemonFromPlayerParty(playerPokemon, false);
const onBeforeRewardsPhase = () => {
@ -151,12 +149,7 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde
globalScene.gameData.setPokemonCaught(playerPokemon, false);
}
// Add pokemon and mods back
globalScene.getPlayerParty().push(playerPokemon);
for (const mod of modifiers.value) {
mod.pokemonId = playerPokemon.id;
globalScene.addModifier(mod, true, false, false, true);
}
// Make held items show up again
globalScene.updateModifiers(true);
queueEncounterMessage(`${namespace}:option.1.finished`);
};
@ -217,8 +210,7 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde
// Spawn medium training session with chosen pokemon
// Every 40 waves, add +1 boss segment, capping at 6
const segments = Math.min(2 + Math.floor(globalScene.currentBattle.waveIndex / 40), 6);
const modifiers = new ModifiersHolder();
const config = getEnemyConfig(playerPokemon, segments, modifiers);
const config = getEnemyConfig(playerPokemon, segments);
globalScene.removePokemonFromPlayerParty(playerPokemon, false);
const onBeforeRewardsPhase = () => {
@ -227,12 +219,7 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde
playerPokemon.setCustomNature(encounter.misc.chosenNature);
globalScene.gameData.unlockSpeciesNature(playerPokemon.species, encounter.misc.chosenNature);
// Add pokemon and modifiers back
globalScene.getPlayerParty().push(playerPokemon);
for (const mod of modifiers.value) {
mod.pokemonId = playerPokemon.id;
globalScene.addModifier(mod, true, false, false, true);
}
// Make held items show up again
globalScene.updateModifiers(true);
};
@ -308,8 +295,7 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde
// Every 30 waves, add +1 boss segment, capping at 6
// Also starts with +1 to all stats
const segments = Math.min(2 + Math.floor(globalScene.currentBattle.waveIndex / 30), 6);
const modifiers = new ModifiersHolder();
const config = getEnemyConfig(playerPokemon, segments, modifiers);
const config = getEnemyConfig(playerPokemon, segments);
config.pokemonConfigs![0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
globalScene.removePokemonFromPlayerParty(playerPokemon, false);
@ -340,12 +326,7 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde
playerPokemon.calculateStats();
globalScene.gameData.setPokemonCaught(playerPokemon, false);
// Add pokemon and mods back
globalScene.getPlayerParty().push(playerPokemon);
for (const mod of modifiers.value) {
mod.pokemonId = playerPokemon.id;
globalScene.addModifier(mod, true, false, false, true);
}
// Make held items show up again
globalScene.updateModifiers(true);
};
@ -373,18 +354,12 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde
)
.build();
function getEnemyConfig(playerPokemon: PlayerPokemon, segments: number, modifiers: ModifiersHolder): EnemyPartyConfig {
function getEnemyConfig(playerPokemon: PlayerPokemon, segments: number): EnemyPartyConfig {
playerPokemon.resetSummonData();
// Passes modifiers by reference
modifiers.value = playerPokemon.getHeldItems();
const modifierConfigs = modifiers.value.map(mod => {
return {
modifier: mod.clone(),
isTransferable: false,
stackCount: mod.stackCount,
};
}) as HeldModifierConfig[];
// TODO: fix various things, like make enemy items untransferable, make sure form change items can come back
const config = playerPokemon.heldItemManager.generateHeldItemConfiguration();
const data = new PokemonData(playerPokemon);
return {
@ -396,12 +371,8 @@ function getEnemyConfig(playerPokemon: PlayerPokemon, segments: number, modifier
formIndex: playerPokemon.formIndex,
level: playerPokemon.level,
dataSource: data,
modifierConfigs: modifierConfigs,
heldItemConfig: config,
},
],
};
}
class ModifiersHolder {
public value: PokemonHeldItemModifier[] = [];
}

View File

@ -1,7 +1,12 @@
import { allHeldItems } from "#app/items/all-held-items";
import { isItemInRequested, type HeldItemCategoryId, type HeldItemId } from "#app/enums/held-item-id";
import type { FormChangeItem } from "#enums/form-change-item";
import { isHeldItemSpecs, type HeldItemDataMap, type HeldItemSpecs } from "#app/items/held-item-data-types";
import {
type HeldItemConfiguration,
isHeldItemSpecs,
type HeldItemDataMap,
type HeldItemSpecs,
} from "#app/items/held-item-data-types";
interface FormChangeItemProperties {
active: boolean;
@ -32,6 +37,18 @@ export class PokemonItemManager {
return undefined;
}
generateHeldItemConfiguration(restrictedIds?: HeldItemId[]): HeldItemConfiguration {
const config: HeldItemConfiguration = [];
for (const [k, item] of Object.entries(this.heldItems)) {
const id = Number(k);
if (item && (!restrictedIds || id in restrictedIds)) {
const specs: HeldItemSpecs = { ...item, id };
config.push({ entry: specs, count: 1 });
}
}
return config;
}
getHeldItems(): number[] {
return Object.keys(this.heldItems).map(k => Number(k));
}