diff --git a/module.json b/module.json index 9caf802..8f8ee2e 100644 --- a/module.json +++ b/module.json @@ -1,7 +1,7 @@ { "id": "dh-importer", "title": "Daggerheart Statblock Importer", - "version": "1.2.2", + "version": "1.1.0", "compatibility": { "minimum": "13", "verified": "13" @@ -34,5 +34,5 @@ "description": "Imports Adversaries and Environments from text blocks into the Daggerheart system.", "url": "https://github.com/cptn-cosmo/dh-importer", "manifest": "https://git.geeks.gay/cosmo/dh-importer/raw/branch/main/module.json", - "download": "https://git.geeks.gay/cosmo/dh-importer/releases/download/1.2.2/dh-importer.zip" + "download": "https://git.geeks.gay/cosmo/dh-importer/releases/download/1.1.0/dh-importer.zip" } \ No newline at end of file diff --git a/scripts/app.js b/scripts/app.js index 466ac48..dd72686 100644 --- a/scripts/app.js +++ b/scripts/app.js @@ -8,7 +8,6 @@ export class DHImporterApp extends HandlebarsApplicationMixin(ApplicationV2) { this.step = "input"; this.parsedData = null; this.parsedDataType = null; - this.inputText = ""; } static DEFAULT_OPTIONS = { @@ -46,10 +45,7 @@ export class DHImporterApp extends HandlebarsApplicationMixin(ApplicationV2) { types: { adversary: "Adversary", environment: "Environment" - }, - inputText: this.inputText, - folders: game.folders.filter(f => f.type === "Actor").sort((a, b) => a.name.localeCompare(b.name)), - packs: game.packs.filter(p => p.documentName === "Actor" && !p.locked) + } }; } @@ -79,9 +75,6 @@ export class DHImporterApp extends HandlebarsApplicationMixin(ApplicationV2) { const text = form.querySelector("textarea[name='text']").value; const type = form.querySelector("select[name='type']").value; - // Store input text - this.inputText = text; - if (!text) { ui.notifications.warn("Please enter text to import."); return; @@ -154,10 +147,7 @@ export class DHImporterApp extends HandlebarsApplicationMixin(ApplicationV2) { } } - const importTarget = formData.importTarget || ""; - const sortTier = formData.sortTier || false; - - await DHImporter.createDocuments(this.parsedData, this.parsedDataType, { target: importTarget, sortTier }); + await DHImporter.createDocuments(this.parsedData, this.parsedDataType); ui.notifications.info(`Successfully imported ${this.parsedData.length} documents.`); this.close(); } catch (e) { diff --git a/scripts/importer.js b/scripts/importer.js index 58b97b6..cbc5cd4 100644 --- a/scripts/importer.js +++ b/scripts/importer.js @@ -241,10 +241,7 @@ export class DHImporter { // Ranges: Melee, Very Close, Close, Far, Very Far const rangeMatch = rest.match(/^(Melee|Very Close|Close|Far|Very Far)/i); if (rangeMatch) { - let rangeVal = rangeMatch[1].toLowerCase(); - if (rangeVal === "very close") rangeVal = "veryClose"; - if (rangeVal === "very far") rangeVal = "veryFar"; - data.system.attack.range = rangeVal; + data.system.attack.range = rangeMatch[1].toLowerCase(); rest = rest.substring(rangeMatch[0].length).trim(); } @@ -263,7 +260,7 @@ export class DHImporter { formula = dmgMatch[1]; type = dmgMatch[2].toLowerCase(); if (type === "phy") type = "physical"; - else if (type === "mag" || type === "magic") type = "magical"; + else if (type === "mag") type = "magic"; } data.system.attack.damage.parts.push({ @@ -279,31 +276,16 @@ export class DHImporter { } static _parseExperienceLine(line, data) { - // Handle "Experience: Manipulate +2, Infiltrate +2" or "Knowledge (Arcana, History) +2" - const parts = line.split(","); - let buffer = ""; - - for (let part of parts) { - buffer = buffer ? buffer + "," + part : part; - - // Check if buffer matches "Name +Value" - // We trim to handle spaces around commas - const trimmed = buffer.trim(); - // Regex to match "Name +Value" at the end of the string - const match = trimmed.match(/(.+?)\s+([+-]?\d+)$/); - - if (match) { - const currentCount = Object.keys(data.system.experiences).length; - const key = "exp" + currentCount; - data.system.experiences[key] = { - name: match[1].trim(), - value: parseInt(match[2]) - }; - // Reset buffer as we found a complete experience - buffer = ""; - } + // "Ambusher +3" + const match = line.match(/(.+?)\s+([+-]?\d+)$/); + if (match) { + const currentCount = Object.keys(data.system.experiences).length; + const key = "exp" + currentCount; + data.system.experiences[key] = { + name: match[1].trim(), + value: parseInt(match[2]) + }; } - // If buffer remains (e.g. "Some Trait" without number), it is ignored, consistent with previous behavior. } /** @@ -329,18 +311,10 @@ export class DHImporter { }; if (isAction) { - // Determine if this is an attack or a generic ability - const isAttack = buffer.description.match(/make.*?attack/i) || - buffer.description.match(/(?:deal|inflict|take)\s+(\d+(?:d\d+)?(?:[\s]*[\+\-][\s]*\d+)?)\s+(direct\s+)?(\w+)\s+damage/i); - - const actionType = isAttack ? "attack" : "ability"; - const rollType = isAttack ? "attack" : "ability"; - const actionId = foundry.utils.randomID(); - const action = { _id: actionId, - type: actionType, + type: "attack", name: buffer.name, actionType: "action", img: "icons/svg/item-bag.svg", @@ -350,7 +324,7 @@ export class DHImporter { damage: { parts: [], includeBase: false, direct: false }, range: "", roll: { - type: rollType, + type: "action", // Default to action, switch to attack if detected diceRolling: { multiplier: "flat", dice: "d6" } } }; @@ -387,11 +361,7 @@ export class DHImporter { // Parse Range const rangeMatch = buffer.description.match(/(Melee|Very Close|Close|Far|Very Far)/i); if (rangeMatch) { - let rangeVal = rangeMatch[1].toLowerCase(); - if (rangeVal === "very close") rangeVal = "veryClose"; - if (rangeVal === "very far") rangeVal = "veryFar"; - - action.range = rangeVal; + action.range = rangeMatch[1].toLowerCase(); } // Parse Damage: "deal 3d4+10 direct physical damage" @@ -406,7 +376,7 @@ export class DHImporter { // Map short codes if (type === "phy") type = "physical"; - else if (type === "mag" || type === "magic") type = "magical"; + else if (type === "mag") type = "magic"; action.damage.direct = isDirect; action.damage.parts.push({ @@ -559,86 +529,19 @@ export class DHImporter { return results; } - static async createDocuments(dataList, type, options = {}) { + static async createDocuments(dataList, type) { if (!dataList || dataList.length === 0) return; - const { target, sortTier } = options; const Actor = getDocumentClass("Actor"); - const Folder = getDocumentClass("Folder"); const actorsToCreate = []; - // Determine Target Context - let targetFolderId = null; - let targetPack = null; - - if (target) { - if (game.packs.has(target)) { - targetPack = game.packs.get(target); - } else { - targetFolderId = target; - } - } - - // Folder Cache for Tier Sorting - const folderCache = {}; - - const getTierFolder = async (tier) => { - const folderName = `Tier ${tier}`; - const cacheKey = `${targetPack ? targetPack.collection : "world"}-${targetFolderId || "root"}-${tier}`; - - if (folderCache[cacheKey]) return folderCache[cacheKey]; - - // Parent ID (for creating subfolder) - const parentId = targetFolderId; - - // Search for existing folder - let folder; - if (targetPack) { - // Search in compendium index (requires V11+ folders) - // We'll rely on pack.folders if available (V11) - if (targetPack.folders) { - folder = targetPack.folders.find(f => f.name === folderName && f.folder?.id === parentId); - } - } else { - // Search in World - folder = game.folders.find(f => f.type === "Actor" && f.name === folderName && f.folder?.id === parentId); - } - - if (folder) { - folderCache[cacheKey] = folder.id; - return folder.id; - } - - // Create Folder if not found - try { - const folderData = { - name: folderName, - type: "Actor", - folder: parentId, - sorting: "a" - }; - - if (targetPack) { - folderData.pack = targetPack.collection; - } - - const newFolder = await Folder.create(folderData, { pack: targetPack?.collection }); - if (newFolder) { - folderCache[cacheKey] = newFolder.id; - return newFolder.id; - } - } catch (e) { - console.warn("Could not create Tier folder:", e); - // Fallback to parent - return parentId; - } - }; - for (const data of dataList) { - // Process Items + // Process Items based on 'useCompendium' flags or similar set by the UI + // The UI should have modified data.items or we loop through and replace based on user choice const finalItems = []; for (const item of data.items) { if (data.useFeatures && data.useFeatures[item.name]) { + // User selected to use existing feature const uuid = data.useFeatures[item.name]; const original = await fromUuid(uuid); if (original) { @@ -652,43 +555,21 @@ export class DHImporter { } data.items = finalItems; - // Handle Sorting / Folder Assignment - if (sortTier) { - const tier = data.system.tier !== undefined ? data.system.tier : 0; - data.folder = await getTierFolder(tier); - } else if (targetFolderId) { - data.folder = targetFolderId; - } - // Clean up temporary flags const shouldOpen = data.openSheet; delete data.foundFeatures; delete data.useFeatures; delete data.openSheet; - // If finding an existing actor to update could be a future feature, but for now we create new. actorsToCreate.push({ data, shouldOpen }); } - let createdActors = []; - if (targetPack) { - // Import to Compendium - // Note: createDocuments with pack option works in V10+ - const docs = actorsToCreate.map(a => a.data); - createdActors = await Actor.createDocuments(docs, { pack: targetPack.collection }); - } else { - // Import to World - createdActors = await Actor.createDocuments(actorsToCreate.map(a => a.data)); - } + const createdActors = await Actor.createDocuments(actorsToCreate.map(a => a.data)); // Open sheets if (createdActors && createdActors.length > 0) { for (let i = 0; i < createdActors.length; i++) { - // If we imported to compendium, we generally don't open sheets immediately as they are in the pack - // But if the user really wants to, we'd have to retrieve the sheet from the pack. - // Standard behavior for compendium import: don't open. - - if (!targetPack && actorsToCreate[i].shouldOpen) { + if (actorsToCreate[i].shouldOpen) { createdActors[i].sheet.render(true); } } diff --git a/templates/importer.hbs b/templates/importer.hbs index 4ad3828..833799c 100644 --- a/templates/importer.hbs +++ b/templates/importer.hbs @@ -13,7 +13,7 @@
- +
-
-
- - -
-
- -
-
-