export const DEFAULT_AUGMENTS = [ { id: "force", name: "Kinetic Amplifier", effect: "+1 Damage on Melee attacks", cost: "2 Iron", precompile: 1 }, { id: "fire", name: "Thermal Core", effect: "Deals Fire damage instead of Physical", cost: "1 Blaze Glass", precompile: 1 }, { id: "shock", name: "Static Coil", effect: "Targets hit are Dazed", cost: "3 Copper", precompile: 2 }, { id: "shield", name: "Reactive Plating", effect: "+1 Armor while equipped", cost: "2 Steel", precompile: 1 }, { id: "range", name: "Long-Range Optics", effect: "Increases Range by 1 step", cost: "1 Lens", precompile: 2 }, { id: "crit", name: "Precision Chip", effect: "+1 to Crit range", cost: "1 Gold", precompile: 3 }, { id: "multi", name: "Burst Module", effect: "Can target 2 enemies (Half damage)", cost: "2 Gears", precompile: 4 }, { id: "drain", name: "Siphon Link", effect: "Recover 1 Hope on kill", cost: "1 Soul Gem", precompile: 4 }, { id: "weight", name: "Gravity Plate", effect: "Weapon is Heavy (more damage)", cost: "4 Lead", precompile: 2 } ]; // Global caches for resolved features to keep getters fast const _featureCache = new Map(); export function getAugments() { return game.settings.get('dh-ikonis', 'augmentsList') || DEFAULT_AUGMENTS; } /** * Pre-loads all features from the compendium into memory. * This is necessary because sheetLists getter is synchronous. */ export async function loadIkonisFeatures() { console.log("DH-Ikonis | Pre-loading features into cache..."); const allAugs = getAugments(); const bondedUuid = game.settings.get('dh-ikonis', 'defaultBondedUuid'); const uuids = new Set(allAugs.map(a => a.featureUuid).filter(Boolean)); if (bondedUuid) uuids.add(bondedUuid); for (const uuid of uuids) { try { const item = await fromUuid(uuid); if (item) { _featureCache.set(uuid, item); console.log(`DH-Ikonis | Cached feature: ${item.name} [${uuid}]`); } } catch (e) { console.error(`DH-Ikonis | Failed to load feature ${uuid}`, e); } } console.log(`DH-Ikonis | Cache size: ${_featureCache.size}`); } /** * Robust feature fetching. Tries cache first, then async fromUuid. */ export async function getAttachedFeature(uuid) { if (!uuid) return null; if (_featureCache.has(uuid)) return _featureCache.get(uuid); return await fromUuid(uuid); } export function getSlotCount(item) { const flags = item.getFlag('dh-ikonis') || {}; if (typeof flags.slotOverride === "number") return flags.slotOverride; let tier = item.system?.tier?.value; if (tier === undefined) tier = item.system?.tier; const tierNum = parseInt(tier) || 1; const settingKey = `slotsTier${tierNum}`; try { return game.settings.get('dh-ikonis', settingKey); } catch (e) { return tierNum >= 2 ? 3 : 2; } } /** * Synchronizes Ikonis Augments into the Daggerheart Homebrew settings. * This makes them "Real" Weapon Features to the system. */ export async function syncIkonisToHomebrew() { if (!game.user.isGM) return; const MODULE_ID = 'dh-ikonis'; const homebrewKey = game.settings.settings.has('daggerheart.Homebrew') ? 'Homebrew' : 'homebrew'; const homebrew = game.settings.get('daggerheart', homebrewKey); if (!homebrew.itemFeatures) homebrew.itemFeatures = { weaponFeatures: {}, armorFeatures: {} }; if (!homebrew.itemFeatures.weaponFeatures) homebrew.itemFeatures.weaponFeatures = {}; let updates = false; const allAugments = getAugments(); for (const aug of allAugments) { const feature = _featureCache.get(aug.featureUuid) || await fromUuid(aug.featureUuid); if (feature && !homebrew.itemFeatures.weaponFeatures[aug.id]) { console.log(`DH-Ikonis | Registering ${aug.name} as native weapon feature...`); // Format actions for the system's Homebrew model const actions = {}; if (feature.system.actions) { for (const [id, action] of Object.entries(feature.system.actions)) { actions[id] = action.toObject(); } } homebrew.itemFeatures.weaponFeatures[aug.id] = { name: aug.name, img: aug.img || feature.img, description: feature.system.description, actions: actions, effects: Array.from(feature.effects || []).map(e => e.toObject()) }; updates = true; } } if (updates) { await game.settings.set('daggerheart', homebrewKey, homebrew); console.log("DH-Ikonis | Homebrew settings synchronized."); } } /** * Patches the system's weapon data preparation to handle slot counts. */ export function patchIkonisLogic() { // We no longer need to patch Actor.allApplicableEffects // because the system handles native weapon features automatically. } /** * Placeholder for character patching - no longer needed for virtual items */ export function patchDhCharacter(DhCharacter) { // Injection is deprecated in favor of native weapon features } export function patchDHWeapon() { // Future: Add damage type override logic here }