Guard source gear namespaces and retain recoverable legacy records (#9)
This commit is contained in:
1 parent
ab37006932
commit
e567910c04
23 files changed
+1203
-66
No files matched your search
@@ -1,10 +1,12 @@
|
||||
import {
|
||||
contentCategoryForClass,
|
||||
classById,
|
||||
isRomClassId,
|
||||
type ClassId,
|
||||
} from "../app/characterCatalog";
|
||||
import {
|
||||
classCanEquipItem,
|
||||
classItemShapeFitsEquipmentRules,
|
||||
EQUIPMENT_SLOTS,
|
||||
equipmentSlotForItem,
|
||||
type EquipmentAssignments,
|
||||
@@ -94,6 +96,11 @@ const ARMOR_SLOTS = new Set<EquipmentSlot>([
|
||||
|
||||
const CATALOG_ITEMS = LOOT_CATALOG.bosses.flatMap((boss) => boss.items);
|
||||
const itemCache = new Map<string, InventoryItem>();
|
||||
// Training placeholders are generated internally and are never serialized as
|
||||
// earned inventory. Keep their legacy simulator projection private so it can
|
||||
// preserve the existing RoM training profile without making direct WoW stats
|
||||
// valid on a caller-supplied RoM item.
|
||||
const romTrainingItems = new WeakSet<InventoryItem>();
|
||||
|
||||
function effectiveLevel(context: HeirloomContext): number {
|
||||
const cap = context.ownerKind === "party" ? PARTY_HEIRLOOM_LEVEL_CAP : PLAYER_HEIRLOOM_LEVEL_CAP;
|
||||
@@ -181,6 +188,7 @@ function weaponStats(slot: EquipmentSlot, inventorySlot: string, weaponType: str
|
||||
|
||||
function syntheticCatalogItem(template: LootCatalogItem, itemLevel: number): InventoryItem {
|
||||
return {
|
||||
contentCategory: "wow",
|
||||
instanceId: `catalog:${template.itemId}`,
|
||||
itemId: template.itemId,
|
||||
itemKey: template.itemKey,
|
||||
@@ -203,7 +211,9 @@ function highestCatalogScore(classId: ClassId, slot: EquipmentSlot, level: numbe
|
||||
let highest = 0;
|
||||
for (const template of CATALOG_ITEMS) {
|
||||
const candidate = syntheticCatalogItem(template, level);
|
||||
if (equipmentSlotForItem(candidate) !== slot || !classCanEquipItem(classId, candidate)) continue;
|
||||
// Catalog comparison is an internal shape-only specialization baseline.
|
||||
// These WoW templates never enter inventory or an equipment assignment.
|
||||
if (equipmentSlotForItem(candidate) !== slot || !classItemShapeFitsEquipmentRules(classId, candidate)) continue;
|
||||
highest = Math.max(highest, specializationScore(candidate.stats, profile));
|
||||
}
|
||||
return highest;
|
||||
@@ -286,6 +296,7 @@ function heirloomItem(
|
||||
// internal quality so this label change cannot alter saved builds or budgets.
|
||||
const romTrainingGear = isRomClassId(context.classId);
|
||||
const result: InventoryItem = Object.freeze({
|
||||
contentCategory: contentCategoryForClass(context.classId),
|
||||
instanceId: `heirloom:${context.ownerId}:${profile.id}:${slot}`,
|
||||
itemId: 9_000_000 + stableNumber % 900_000,
|
||||
itemKey: `heirloom-${profile.id.replace(/:/g, "-")}-${slot}`,
|
||||
@@ -302,6 +313,7 @@ function heirloomItem(
|
||||
sourceBossName: romTrainingGear ? "Training Armory" : "Heirloom Armory",
|
||||
acquiredAt: 0,
|
||||
});
|
||||
if (romTrainingGear) romTrainingItems.add(result);
|
||||
itemCache.set(cacheKey, result);
|
||||
return result;
|
||||
}
|
||||
@@ -348,7 +360,12 @@ export function equipmentStatsForItems(items: readonly InventoryItem[]): ItemSta
|
||||
const nativePayloads = [] as NonNullable<ItemStats["romNative"]>[];
|
||||
for (const item of items) {
|
||||
for (const key of ITEM_STAT_KEYS) numeric[key] += item.stats[key];
|
||||
const nativePayload = item.stats.romNative ?? romNativeGearFromSharedDirectStats(item.stats);
|
||||
const nativePayload = item.stats.romNative
|
||||
?? (romTrainingItems.has(item)
|
||||
|| item.contentCategory === undefined
|
||||
|| item.contentCategory === "wow"
|
||||
? romNativeGearFromSharedDirectStats(item.stats)
|
||||
: undefined);
|
||||
if (nativePayload) nativePayloads.push(nativePayload);
|
||||
if (item.stats.meleeWeapon) meleeWeapon = item.stats.meleeWeapon;
|
||||
if (item.stats.rangedWeapon) rangedWeapon = item.stats.rangedWeapon;
|
||||
|
||||
Reference in new issue
Block a user