diff --git a/module.json b/module.json index ea9925c..4977959 100644 --- a/module.json +++ b/module.json @@ -42,18 +42,5 @@ "name": "English", "path": "lang/en.json" } - ], - "packs": [ - { - "name": "ikonis-features", - "label": "Ikonis Features", - "path": "packs/ikonis-features", - "type": "Item", - "system": "daggerheart", - "ownership": { - "PLAYER": "OBSERVER", - "ASSISTANT": "OWNER" - } - } ] } \ No newline at end of file diff --git a/packs/000003.log b/packs/000003.log deleted file mode 100644 index eaab53f..0000000 Binary files a/packs/000003.log and /dev/null differ diff --git a/packs/CURRENT b/packs/CURRENT deleted file mode 100644 index 1a84852..0000000 --- a/packs/CURRENT +++ /dev/null @@ -1 +0,0 @@ -MANIFEST-000002 diff --git a/packs/LOCK b/packs/LOCK deleted file mode 100644 index e69de29..0000000 diff --git a/packs/LOG b/packs/LOG deleted file mode 100644 index c51a2fd..0000000 --- a/packs/LOG +++ /dev/null @@ -1 +0,0 @@ -2026/04/26-14:45:07.673032 146fb55fe6c0 Delete type=3 #1 diff --git a/packs/MANIFEST-000002 b/packs/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/MANIFEST-000002 and /dev/null differ diff --git a/packs/ikonis-features.json b/packs/ikonis-features.json deleted file mode 100644 index 9f8c377..0000000 --- a/packs/ikonis-features.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - { "name": "Kinetic Amplifier", "type": "feature", "img": "icons/magic/force/projectile-orb-blue.webp", "system": { "description": "
+1 Damage on Melee attacks.
", "attribution": { "source": "Ikonis Tech" } } }, - { "name": "Thermal Core", "type": "feature", "img": "icons/magic/fire/orb-magma.webp", "system": { "description": "Deals Fire damage instead of Physical.
", "attribution": { "source": "Ikonis Tech" } } }, - { "name": "Static Coil", "type": "feature", "img": "icons/magic/lightning/bolt-blue.webp", "system": { "description": "Targets hit are Dazed.
", "attribution": { "source": "Ikonis Tech" } } }, - { "name": "Reactive Plating", "type": "feature", "img": "icons/equipment/chest/breastplate-metal-scaled-silver.webp", "system": { "description": "+1 Armor while equipped.
", "attribution": { "source": "Ikonis Tech" } } }, - { "name": "Long-Range Optics", "type": "feature", "img": "icons/tools/navigation/spyglass-brass.webp", "system": { "description": "Increases Range by 1 step.
", "attribution": { "source": "Ikonis Tech" } } }, - { "name": "Precision Chip", "type": "feature", "img": "icons/commodities/tech/circuit-board.webp", "system": { "description": "+1 to Crit range.
", "attribution": { "source": "Ikonis Tech" } } }, - { "name": "Burst Module", "type": "feature", "img": "icons/magic/fire/explosion-fireball-medium-red-orange.webp", "system": { "description": "Can target 2 enemies (Half damage).
", "attribution": { "source": "Ikonis Tech" } } }, - { "name": "Siphon Link", "type": "feature", "img": "icons/magic/unholy/strike-body-life-drain-red.webp", "system": { "description": "Recover 1 Hope on kill.
", "attribution": { "source": "Ikonis Tech" } } }, - { "name": "Gravity Plate", "type": "feature", "img": "icons/magic/air/vortex-wind-blue.webp", "system": { "description": "Weapon is Heavy (more damage).
", "attribution": { "source": "Ikonis Tech" } } }, - { "name": "Ikonis Bond", "type": "feature", "img": "icons/magic/symbols/rune-sigil-blue-white.webp", "system": { "description": "This weapon is bonded to your biological signature.
", "attribution": { "source": "Ikonis Tech" } } } -] diff --git a/packs/ikonis-features/000003.log b/packs/ikonis-features/000003.log deleted file mode 100644 index 44878fc..0000000 Binary files a/packs/ikonis-features/000003.log and /dev/null differ diff --git a/packs/ikonis-features/CURRENT b/packs/ikonis-features/CURRENT deleted file mode 100644 index 1a84852..0000000 --- a/packs/ikonis-features/CURRENT +++ /dev/null @@ -1 +0,0 @@ -MANIFEST-000002 diff --git a/packs/ikonis-features/LOCK b/packs/ikonis-features/LOCK deleted file mode 100644 index e69de29..0000000 diff --git a/packs/ikonis-features/LOG b/packs/ikonis-features/LOG deleted file mode 100644 index 5ba48f5..0000000 --- a/packs/ikonis-features/LOG +++ /dev/null @@ -1 +0,0 @@ -2026/04/26-17:05:00.760293 146f67fff6c0 Delete type=3 #1 diff --git a/packs/ikonis-features/MANIFEST-000002 b/packs/ikonis-features/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/ikonis-features/MANIFEST-000002 and /dev/null differ diff --git a/scripts/ikonis-data.js b/scripts/ikonis-data.js index ee320c5..6d20a30 100644 --- a/scripts/ikonis-data.js +++ b/scripts/ikonis-data.js @@ -128,112 +128,65 @@ export function patchIkonisLogic() { } /** - * Internal helper to generate and cache virtual features for an actor. - * Safe to call multiple times; uses a cache to keep it fast. + * Synchronizes Ikonis Augments into the Daggerheart Homebrew settings. + * This makes them "Real" Weapon Features to the system. */ -function _injectIkonisFeatures(actor) { - if (!actor || actor._isIkonisInjecting) return []; - - // Initialize the cache if it doesn't exist - if (!actor._ikonisCache) actor._ikonisCache = new Map(); - - const ikonisFeatures = []; - actor._isIkonisInjecting = true; - - try { - const weapons = actor.items.filter(i => i.type === 'weapon'); - const allAugs = getAugments(); +export async function syncIkonisToHomebrew() { + if (!game.user.isGM) return; - for (const item of weapons) { - const isEquipped = item.system.equipped; - const installedIds = item.getFlag('dh-ikonis', 'installedAugments') || []; - const bondedUuid = item.getFlag('dh-ikonis', 'bondedFeatureUuid'); + 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 = {}; - const processFeature = (uuid, type) => { - if (!uuid) return; - - // Extract original feature ID from UUID to build our virtual ID - const featureId = uuid.split('.').pop(); - const virtualId = `ikonis-${item.id}-${featureId}`; + let updates = false; + const allAugments = getAugments(); - // Check cache first - if (actor._ikonisCache.has(virtualId)) { - if (isEquipped) ikonisFeatures.push(actor._ikonisCache.get(virtualId)); - return; + 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(); } - - // Resolve original and clone - const feature = _featureCache.get(uuid) || fromUuidSync(uuid); - if (feature) { - const featureClone = feature.clone({ parent: actor }, { keepId: true }); - featureClone.system.type = "ikonis"; - Object.defineProperty(featureClone, "id", { value: virtualId, enumerable: true }); - - actor._ikonisCache.set(virtualId, featureClone); - if (isEquipped) ikonisFeatures.push(featureClone); - } - }; - - if (bondedUuid) processFeature(bondedUuid, "bonded"); - for (const id of installedIds) { - const aug = allAugs.find(a => String(a.id) === String(id)); - if (aug?.featureUuid) processFeature(aug.featureUuid, "augment"); } + + 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; } - } catch (err) { - console.error("DH-Ikonis | Error during feature injection:", err); - } finally { - actor._isIkonisInjecting = false; } - - return ikonisFeatures; + + if (updates) { + await game.settings.set('daggerheart', homebrewKey, homebrew); + console.log("DH-Ikonis | Homebrew settings synchronized."); + } } /** - * Patches the Character Data Model to show features in the UI lists. + * 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) { - console.log("DH-Ikonis | Applying DhCharacter.sheetLists patch..."); - - const descriptor = Object.getOwnPropertyDescriptor(DhCharacter.prototype, 'sheetLists'); - if (!descriptor) { - console.error("DH-Ikonis | FAILED to find sheetLists descriptor on DhCharacter prototype!"); - return; - } - - const originalSheetLists = descriptor.get; - Object.defineProperty(DhCharacter.prototype, 'sheetLists', { - get: function() { - const lists = originalSheetLists.call(this); // This is an Array - if (!this.parent || !Array.isArray(lists)) return lists; - - const ikonisFeatures = _injectIkonisFeatures(this.parent); - - if (ikonisFeatures.length > 0) { - // Add our custom category to the end of the lists array - lists.push({ - title: "Ikonis Augments", - type: "ikonis", - values: ikonisFeatures - }); - } - - return lists; - }, - configurable: true - }); - - // Patch getEmbeddedDocument to resolve our virtual features - const originalGetEmbedded = Actor.prototype.getEmbeddedDocument; - Actor.prototype.getEmbeddedDocument = function(embeddedName, id, options) { - if (embeddedName === "Item" && typeof id === "string" && id.startsWith("ikonis-")) { - if (!this._ikonisCache?.has(id) && !this._isIkonisInjecting) { - _injectIkonisFeatures(this); - } - return this._ikonisCache?.get(id); - } - return originalGetEmbedded.call(this, embeddedName, id, options); - }; + // Injection is deprecated in favor of native weapon features } export function patchDHWeapon() { diff --git a/scripts/ikonis-sheet.js b/scripts/ikonis-sheet.js index ff2d2c0..03b59f3 100644 --- a/scripts/ikonis-sheet.js +++ b/scripts/ikonis-sheet.js @@ -44,18 +44,15 @@ export function patchIkonisSheet() { const doc = this.document; if (!doc) return context; - const installedIds = doc.getFlag('dh-ikonis', 'installedAugments') || []; + const weaponFeatures = doc.system.weaponFeatures || []; const allAugmentsList = getAugments() || []; const processedAugments = []; - for (const id of installedIds) { + for (const featureRef of weaponFeatures) { + const id = featureRef.value; const base = allAugmentsList.find(a => String(a.id) === String(id)); if (!base) continue; const aug = { ...base, installed: true }; - if (aug.featureUuid) { - const item = await getAttachedFeature(aug.featureUuid); - if (item) aug.feature = { name: item.name, img: item.img, uuid: item.uuid }; - } processedAugments.push(aug); } @@ -97,17 +94,18 @@ export function patchIkonisSheet() { // 5. Add custom methods Weapon.prototype._onAddAugment = async function(event, target) { - const installedIds = this.document.getFlag('dh-ikonis', 'installedAugments') || []; + const weaponFeatures = this.document.system.weaponFeatures || []; const allAugments = getAugments(); - const validInstalled = installedIds.filter(id => allAugments.some(a => String(a.id) === String(id))); + // Filter out native features that aren't Ikonis augments if needed, + // but for now we'll just count total weapon features against slots const maxSlots = getSlotCount(this.document); - if (validInstalled.length >= maxSlots) { + if (weaponFeatures.length >= maxSlots) { ui.notifications.warn(`No more augment slots available! (Max: ${maxSlots})`); return; } - const available = allAugments.filter(a => !validInstalled.includes(String(a.id))); + const available = allAugments.filter(a => !weaponFeatures.some(f => f.value === a.id)); const content = `