From 2321de09830a21da093927a33f237d89499ea9be Mon Sep 17 00:00:00 2001 From: Wlowscha <54003515+Wlowscha@users.noreply.github.com> Date: Thu, 19 Jun 2025 00:23:07 +0200 Subject: [PATCH] Updated various MEs. HeldItemManager can now generate a configuration from its items. --- .../encounters/dark-deal-encounter.ts | 6 +-- .../encounters/fiery-fallout-encounter.ts | 2 +- .../slumbering-snorlax-encounter.ts | 14 +++--- .../encounters/the-strong-stuff-encounter.ts | 14 +++--- .../encounters/training-session-encounter.ts | 49 ++++--------------- src/field/pokemon-held-item-manager.ts | 19 ++++++- 6 files changed, 46 insertions(+), 58 deletions(-) diff --git a/src/data/mystery-encounters/encounters/dark-deal-encounter.ts b/src/data/mystery-encounters/encounters/dark-deal-encounter.ts index 3480a318b08..236b4fad9d7 100644 --- a/src/data/mystery-encounters/encounters/dark-deal-encounter.ts +++ b/src/data/mystery-encounters/encounters/dark-deal-encounter.ts @@ -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]; diff --git a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts index fea8e06ca9d..4a68066748d 100644 --- a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts +++ b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts @@ -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"; diff --git a/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts b/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts index 3050ee82c92..b2bc2321524 100644 --- a/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts +++ b/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts @@ -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 }; diff --git a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts index 6399bc41382..e5aafbfdeb9 100644 --- a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts @@ -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`); diff --git a/src/data/mystery-encounters/encounters/training-session-encounter.ts b/src/data/mystery-encounters/encounters/training-session-encounter.ts index 356b5784bef..688e62d8f9c 100644 --- a/src/data/mystery-encounters/encounters/training-session-encounter.ts +++ b/src/data/mystery-encounters/encounters/training-session-encounter.ts @@ -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[] = []; -} diff --git a/src/field/pokemon-held-item-manager.ts b/src/field/pokemon-held-item-manager.ts index 71ffed6750c..b9662041b52 100644 --- a/src/field/pokemon-held-item-manager.ts +++ b/src/field/pokemon-held-item-manager.ts @@ -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)); }