From 077d284987dd2e248ea3237aa32c8ad5f10579a4 Mon Sep 17 00:00:00 2001 From: cosmo Date: Sun, 26 Apr 2026 17:48:08 +0200 Subject: [PATCH] add DhCharacter patch to inject Ikonis augment features into character sheet UI lists --- scripts/ikonis-data.js | 66 ++++++++++++++++++++++++++++++++++++------ scripts/main.js | 7 +++-- 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/scripts/ikonis-data.js b/scripts/ikonis-data.js index 2029640..4d716e7 100644 --- a/scripts/ikonis-data.js +++ b/scripts/ikonis-data.js @@ -10,8 +10,9 @@ export const DEFAULT_AUGMENTS = [ { id: "weight", name: "Gravity Plate", effect: "Weapon is Heavy (more damage)", cost: "4 Lead", precompile: 2 } ]; -// Global cache for resolved features to keep generators fast +// Global caches for resolved features to keep getters fast const _featureCache = new Map(); +const _itemObjectCache = new Map(); export function getAugments() { return game.settings.get('dh-ikonis', 'augmentsList') || DEFAULT_AUGMENTS; @@ -63,10 +64,8 @@ export function patchIkonisLogic() { // 1. Patch allApplicableEffects to inject Active Effects from Augments const originalAllEffects = Actor.prototype.allApplicableEffects; Actor.prototype.allApplicableEffects = function* () { - // Yield standard effects yield* originalAllEffects.call(this); - // Inject effects from equipped Ikonis weapons for (const item of this.items) { if (item.type !== 'weapon' || !item.system.equipped) continue; @@ -77,18 +76,14 @@ export function patchIkonisLogic() { const aug = allAugs.find(a => String(a.id) === String(id)); if (!aug?.featureUuid) continue; - // We use sync lookup here because generators must be synchronous. - // The features should already be in the cache from the sheet rendering. const feature = fromUuidSync(aug.featureUuid); if (!feature || !feature.effects) continue; for (const effect of feature.effects) { - // Only yield transfer effects (those meant to apply to the actor) if (effect.transfer) yield effect; } } - // Also check Bonded feature const bondedUuid = item.getFlag('dh-ikonis', 'bondedFeatureUuid'); if (bondedUuid) { const feature = fromUuidSync(bondedUuid); @@ -100,11 +95,64 @@ export function patchIkonisLogic() { } } }; +} - console.log("DH-Ikonis | Actor patches complete."); +/** + * Patches the Character Data Model to show features in the UI lists. + */ +export function patchDhCharacter(DhCharacter) { + console.log("DH-Ikonis | Patching DhCharacter data model for UI lists..."); + + const descriptor = Object.getOwnPropertyDescriptor(DhCharacter.prototype, 'sheetLists'); + if (!descriptor) return; + + const originalSheetLists = descriptor.get; + Object.defineProperty(DhCharacter.prototype, 'sheetLists', { + get: function() { + const lists = originalSheetLists.call(this); + const ikonisFeatures = []; + + // Find equipped Ikonis weapons + for (const item of this.parent.items) { + if (item.type !== 'weapon' || !item.system.equipped) continue; + + const installedIds = item.getFlag('dh-ikonis', 'installedAugments') || []; + const allAugs = getAugments(); + const bondedUuid = item.getFlag('dh-ikonis', 'bondedFeatureUuid'); + + // Collect Bonded Feature + if (bondedUuid) { + const feature = fromUuidSync(bondedUuid); + if (feature) ikonisFeatures.push(feature); + } + + // Collect Augments + for (const id of installedIds) { + const aug = allAugs.find(a => String(a.id) === String(id)); + if (!aug?.featureUuid) continue; + + const feature = fromUuidSync(aug.featureUuid); + if (feature) ikonisFeatures.push(feature); + } + } + + if (ikonisFeatures.length > 0) { + // Ensure unique features + const uniqueFeatures = Array.from(new Set(ikonisFeatures)); + + lists.ikonis = { + title: "Ikonis Augments", + type: "ikonis", + values: uniqueFeatures + }; + } + + return lists; + }, + configurable: true + }); } export function patchDHWeapon() { - console.log("DH-Ikonis | Patching DH Weapon system..."); // Future: Add damage type override logic here } diff --git a/scripts/main.js b/scripts/main.js index c4fc899..989f63e 100644 --- a/scripts/main.js +++ b/scripts/main.js @@ -1,4 +1,4 @@ -import { patchDHWeapon, patchIkonisLogic, DEFAULT_AUGMENTS } from './ikonis-data.js'; +import { patchDHWeapon, patchIkonisLogic, patchDhCharacter, DEFAULT_AUGMENTS } from './ikonis-data.js'; import { patchIkonisSheet } from './ikonis-sheet.js'; import { IkonisAugmentConfig } from './ikonis-config.js'; @@ -87,8 +87,11 @@ Hooks.once('ready', async () => { } const actorsApi = game.system.api.models.actors || {}; - const DhCharacter = actorsApi.DhCharacter || actorsApi.DHCharacter || actorsApi.character; + const DhCharacter = actorsApi.DhCharacter || actorsApi.character; if (DhCharacter) { + // Apply visual injection patch + patchDhCharacter(DhCharacter); + Object.defineProperty(DhCharacter.prototype, 'primaryWeapon', { get: function() { return this.parent.items.find(x => x.type === 'weapon' && x.system.equipped && !x.system.secondary); }, configurable: true