Held item generation for enemies follows the new scheme

This commit is contained in:
Wlowscha 2025-06-17 23:08:14 +02:00
parent 39be97ef8e
commit f2a339fbe5
No known key found for this signature in database
GPG Key ID: 3C8F1AD330565D04
4 changed files with 114 additions and 14 deletions

View File

@ -51,13 +51,12 @@ import { allMoves } from "./data/data-lists";
import { MusicPreference } from "#app/system/settings/settings"; import { MusicPreference } from "#app/system/settings/settings";
import { import {
getDefaultModifierTypeForTier, getDefaultModifierTypeForTier,
getEnemyHeldItemsForWave,
getLuckString, getLuckString,
getLuckTextTint, getLuckTextTint,
getPartyLuckValue, getPartyLuckValue,
} from "#app/modifier/modifier-type"; } from "#app/modifier/modifier-type";
import { getModifierPoolForType } from "./utils/modifier-utils"; import { getModifierPoolForType } from "./utils/modifier-utils";
import { ModifierPoolType } from "#enums/modifier-pool-type"; import { HeldItemPoolType, ModifierPoolType } from "#enums/modifier-pool-type";
import AbilityBar from "#app/ui/ability-bar"; import AbilityBar from "#app/ui/ability-bar";
import { applyAbAttrs, applyPostBattleInitAbAttrs, applyPostItemLostAbAttrs } from "./data/abilities/apply-ab-attrs"; import { applyAbAttrs, applyPostBattleInitAbAttrs, applyPostItemLostAbAttrs } from "./data/abilities/apply-ab-attrs";
import { allAbilities } from "./data/data-lists"; import { allAbilities } from "./data/data-lists";
@ -157,7 +156,8 @@ import { allHeldItems, applyHeldItems } from "./items/all-held-items";
import { ITEM_EFFECT } from "./items/held-item"; import { ITEM_EFFECT } from "./items/held-item";
import { PhaseManager } from "./phase-manager"; import { PhaseManager } from "./phase-manager";
import { HeldItemId } from "#enums/held-item-id"; import { HeldItemId } from "#enums/held-item-id";
import type { HeldItemPropertyMap } from "./field/pokemon-held-item-manager"; import { assignEnemyHeldItemsForWave, assignItemsFromConfiguration } from "./items/held-item-pool";
import type { HeldItemConfiguration } from "./items/held-item-data-types";
const DEBUG_RNG = false; const DEBUG_RNG = false;
@ -2758,9 +2758,12 @@ export default class BattleScene extends SceneBase {
} }
const countTaken = Math.min(transferQuantity, itemStack, maxStackCount - matchingItemStack); const countTaken = Math.min(transferQuantity, itemStack, maxStackCount - matchingItemStack);
const data = source.heldItemManager[heldItemId].data; const itemSpecs = source.heldItemManager.getItemSpecs(heldItemId);
if (!itemSpecs) {
return false;
}
source.heldItemManager.remove(heldItemId, countTaken); source.heldItemManager.remove(heldItemId, countTaken);
target.heldItemManager.add(heldItemId, countTaken, data); target.heldItemManager.add(itemSpecs);
if (source.heldItemManager.getStack(heldItemId) === 0 && itemLost) { if (source.heldItemManager.getStack(heldItemId) === 0 && itemLost) {
applyPostItemLostAbAttrs("PostItemLostAbAttr", source, false); applyPostItemLostAbAttrs("PostItemLostAbAttr", source, false);
@ -2801,7 +2804,7 @@ export default class BattleScene extends SceneBase {
return countTaken > 0; return countTaken > 0;
} }
generateEnemyModifiers(heldItemConfigs?: HeldItemPropertyMap[]): Promise<void> { generateEnemyModifiers(heldItemConfigs?: HeldItemConfiguration[]): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
if (this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) { if (this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) {
return resolve(); return resolve();
@ -2824,7 +2827,7 @@ export default class BattleScene extends SceneBase {
party.forEach((enemyPokemon: EnemyPokemon, i: number) => { party.forEach((enemyPokemon: EnemyPokemon, i: number) => {
if (heldItemConfigs && i < heldItemConfigs.length && heldItemConfigs[i]) { if (heldItemConfigs && i < heldItemConfigs.length && heldItemConfigs[i]) {
enemyPokemon.heldItemManager.overrideItems(heldItemConfigs[i]); assignItemsFromConfiguration(heldItemConfigs[i], enemyPokemon);
} else { } else {
const isBoss = const isBoss =
enemyPokemon.isBoss() || enemyPokemon.isBoss() ||
@ -2845,13 +2848,13 @@ export default class BattleScene extends SceneBase {
if (isBoss) { if (isBoss) {
count = Math.max(count, Math.floor(chances / 2)); count = Math.max(count, Math.floor(chances / 2));
} }
getEnemyHeldItemsForWave( assignEnemyHeldItemsForWave(
difficultyWaveIndex, difficultyWaveIndex,
count, count,
[enemyPokemon], enemyPokemon,
this.currentBattle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD, this.currentBattle.battleType === BattleType.TRAINER ? HeldItemPoolType.TRAINER : HeldItemPoolType.WILD,
upgradeChance, upgradeChance,
).map(itemId => enemyPokemon.heldItemManager.add(itemId)); );
} }
return true; return true;
}); });

View File

@ -1,10 +1,10 @@
export enum ModifierPoolType { export enum ModifierPoolType {
PLAYER, PLAYER,
ENEMY_BUFF, ENEMY_BUFF,
DAILY_STARTER
} }
export enum HeldItemPoolType { export enum HeldItemPoolType {
WILD, WILD,
TRAINER, TRAINER,
DAILY_STARTER,
} }

View File

@ -20,6 +20,18 @@ export class PokemonItemManager {
this.formChangeItems = {}; this.formChangeItems = {};
} }
getItemSpecs(id: HeldItemId): HeldItemSpecs | undefined {
const item = this.heldItems[id];
if (item) {
const itemSpecs: HeldItemSpecs = {
...item,
id,
};
return itemSpecs;
}
return undefined;
}
getHeldItems(): number[] { getHeldItems(): number[] {
return Object.keys(this.heldItems).map(k => Number(k)); return Object.keys(this.heldItems).map(k => Number(k));
} }

View File

@ -1,8 +1,9 @@
import type { PlayerPokemon } from "#app/field/pokemon"; import type { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import { coerceArray, getEnumValues, randSeedFloat, randSeedInt } from "#app/utils/common"; import { coerceArray, getEnumValues, randSeedFloat, randSeedInt } from "#app/utils/common";
import { BerryType } from "#enums/berry-type"; import { BerryType } from "#enums/berry-type";
import { HeldItemCategoryId, HeldItemId } from "#enums/held-item-id"; import { HeldItemCategoryId, HeldItemId } from "#enums/held-item-id";
import { HeldItemPoolType } from "#enums/modifier-pool-type";
import type { PokemonType } from "#enums/pokemon-type"; import type { PokemonType } from "#enums/pokemon-type";
import { RewardTier } from "#enums/reward-tier"; import { RewardTier } from "#enums/reward-tier";
import { PERMANENT_STATS } from "#enums/stat"; import { PERMANENT_STATS } from "#enums/stat";
@ -33,7 +34,7 @@ export function assignDailyRunStarterHeldItems(party: PlayerPokemon[]) {
const tier = getDailyRewardTier(tierValue); const tier = getDailyRewardTier(tierValue);
const item = getNewHeldItemFromPool(dailyStarterHeldItemPool[tier] as HeldItemPool, party); const item = getNewHeldItemFromPool(getHeldItemPool(HeldItemPoolType.DAILY_STARTER)[tier] as HeldItemPool, party);
p.heldItemManager.add(item); p.heldItemManager.add(item);
} }
} }
@ -55,6 +56,90 @@ function getDailyRewardTier(tierValue: number): RewardTier {
return RewardTier.MASTER; return RewardTier.MASTER;
} }
function getHeldItemPool(poolType: HeldItemPoolType): HeldItemTieredPool {
let pool: HeldItemTieredPool;
switch (poolType) {
case HeldItemPoolType.WILD:
pool = wildHeldItemPool;
break;
case HeldItemPoolType.TRAINER:
pool = trainerHeldItemPool;
break;
case HeldItemPoolType.DAILY_STARTER:
pool = dailyStarterHeldItemPool;
break;
}
return pool;
}
// TODO: Add proper documentation to this function (once it fully works...)
export function assignEnemyHeldItemsForWave(
waveIndex: number,
count: number,
enemy: EnemyPokemon,
poolType: HeldItemPoolType.WILD | HeldItemPoolType.TRAINER,
upgradeChance = 0,
): void {
for (let i = 1; i <= count; i++) {
const item = getNewHeldItemFromTieredPool(
getHeldItemPool(poolType),
[enemy],
upgradeChance && !randSeedInt(upgradeChance) ? 1 : 0,
);
enemy.heldItemManager.add(item);
}
if (!(waveIndex % 1000)) {
enemy.heldItemManager.add(HeldItemId.MINI_BLACK_HOLE);
}
}
function getRandomTier(): RewardTier {
const tierValue = randSeedInt(1024);
if (tierValue > 255) {
return RewardTier.COMMON;
}
if (tierValue > 60) {
return RewardTier.GREAT;
}
if (tierValue > 12) {
return RewardTier.ULTRA;
}
if (tierValue) {
return RewardTier.ROGUE;
}
return RewardTier.MASTER;
}
function determineEnemyPoolTier(pool: HeldItemTieredPool, upgradeCount?: number): RewardTier {
let tier = getRandomTier();
if (!upgradeCount) {
upgradeCount = 0;
}
tier += upgradeCount;
while (tier && !pool[tier]?.length) {
tier--;
if (upgradeCount) {
upgradeCount--;
}
}
return tier;
}
function getNewHeldItemFromTieredPool(
pool: HeldItemTieredPool,
pokemon: Pokemon | Pokemon[],
upgradeCount: number,
): HeldItemId | HeldItemSpecs {
const tier = determineEnemyPoolTier(pool, upgradeCount);
const tierPool = pool[tier];
return getNewHeldItemFromPool(tierPool!, pokemon);
}
function pickWeightedIndex(weights: number[]): number { function pickWeightedIndex(weights: number[]): number {
const totalWeight = weights.reduce((sum, w) => sum + w, 0); const totalWeight = weights.reduce((sum, w) => sum + w, 0);