Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 35078e9e26 | |||
| 24521f593f | |||
| a2f472f947 | |||
| f3d9c18028 | |||
| e536e24d6b | |||
| fcc8ad5c55 |
10
module.json
10
module.json
@@ -2,12 +2,12 @@
|
|||||||
"name": "shadowdarklings-importer",
|
"name": "shadowdarklings-importer",
|
||||||
"title": "Shadowdarklings.net Importer",
|
"title": "Shadowdarklings.net Importer",
|
||||||
"description": "Import JSON characters and items from shadowdarklings.net into Foundry VTT.",
|
"description": "Import JSON characters and items from shadowdarklings.net into Foundry VTT.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.5",
|
||||||
"author": "Booga",
|
"author": "Booga",
|
||||||
"minimumCoreVersion": "10",
|
"minimumCoreVersion": "11",
|
||||||
"compatibleCoreVersion": "11",
|
"compatibleCoreVersion": "12",
|
||||||
"esmodules": ["shadowdarklings-importer.js"],
|
"esmodules": ["shadowdarklings-importer.js"],
|
||||||
"systems": ["shadowdark"],
|
"systems": ["shadowdark"],
|
||||||
"manifest": "https://yourdomain.com/path/to/module.json",
|
"manifest": "https://g.kht.dev/kyle/shadowdark-importer/raw/branch/main/module.json",
|
||||||
"download": "https://yourdomain.com/path/to/module.zip"
|
"download": "https://g.kht.dev/kyle/shadowdark-importer/archive/v1.0.5.zip"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// shadowdarklings-importer.js
|
// shadowdarklings-importer.js
|
||||||
Hooks.on("ready", function () {
|
Hooks.once("ready", function () {
|
||||||
// Add button to Actors Directory
|
// Add button to Actors Directory
|
||||||
Hooks.on("renderActorDirectory", (app, html, data) => {
|
Hooks.on("renderActorDirectory", (app, html, data) => {
|
||||||
appendImportButton(html, app, "actor");
|
appendImportButton(html, app, "actor");
|
||||||
@@ -15,16 +15,15 @@ function appendImportButton(html, app, type) {
|
|||||||
`<button class="shadowdarklings-importer"><i class="fas fa-file-import"></i> Shadowdarklings Import</button>`
|
`<button class="shadowdarklings-importer"><i class="fas fa-file-import"></i> Shadowdarklings Import</button>`
|
||||||
);
|
);
|
||||||
importBtn.on("click", async () => {
|
importBtn.on("click", async () => {
|
||||||
const dialog = new ShadowdarklingsImportDialog(type);
|
const dialog = new ShadowdarklingsImportDialog(type, app);
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
html.find(".directory-footer").append(importBtn);
|
html.find(".directory-footer").append(importBtn);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A dialog window to upload JSON and start the import process
|
// Upload dialog
|
||||||
class ShadowdarklingsImportDialog extends Dialog {
|
class ShadowdarklingsImportDialog extends Dialog {
|
||||||
constructor(type) {
|
constructor(type, app) {
|
||||||
super({
|
super({
|
||||||
title: `Import Shadowdarklings ${type === "actor" ? "Character/Monster" : "Item"}`,
|
title: `Import Shadowdarklings ${type === "actor" ? "Character/Monster" : "Item"}`,
|
||||||
content: `
|
content: `
|
||||||
@@ -49,6 +48,7 @@ class ShadowdarklingsImportDialog extends Dialog {
|
|||||||
default: "import"
|
default: "import"
|
||||||
});
|
});
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
this.app = app;
|
||||||
}
|
}
|
||||||
|
|
||||||
async importJSON(html) {
|
async importJSON(html) {
|
||||||
@@ -65,27 +65,30 @@ class ShadowdarklingsImportDialog extends Dialog {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispatch to appropriate handler
|
|
||||||
if (this.type === "actor") {
|
if (this.type === "actor") {
|
||||||
return importShadowdarklingsActor(json);
|
return importShadowdarklingsActor(json, this.app);
|
||||||
} else {
|
} else {
|
||||||
return importShadowdarklingsItem(json);
|
return importShadowdarklingsItem(json, this.app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example mapping function for actor
|
// Main actor importer
|
||||||
async function importShadowdarklingsActor(data) {
|
async function importShadowdarklingsActor(data, app) {
|
||||||
// Try to discern if this is a character or monster format
|
// Use system-defined actor types: 'pc' (player), 'npc' (monsters/opponents)
|
||||||
if (!data.name) {
|
// Try to discern if this is a PC or NPC/Monster.
|
||||||
ui.notifications.error("This JSON does not look like a Shadowdark character.");
|
let actorType = "npc";
|
||||||
return;
|
// If class or level is present, it's likely a PC
|
||||||
}
|
if (data.class || data.level || data.background || data.player) actorType = "pc";
|
||||||
|
|
||||||
// Very basic mapping, adjust as needed
|
// Allowed actor types
|
||||||
|
const allowedTypes = game.system.model.Actor ? Object.keys(game.system.model.Actor) : ["pc","npc"];
|
||||||
|
if (!allowedTypes.includes(actorType)) actorType = allowedTypes[0]; // Fallback
|
||||||
|
|
||||||
|
// Setup the document data
|
||||||
const actorData = {
|
const actorData = {
|
||||||
name: data.name || "Imported Character",
|
name: data.name || "Imported Character",
|
||||||
type: data.class ? "character" : "npc", // Guess by "class" being present
|
type: actorType,
|
||||||
system: {
|
system: {
|
||||||
abilities: {
|
abilities: {
|
||||||
str: { value: data.str },
|
str: { value: data.str },
|
||||||
@@ -96,60 +99,68 @@ async function importShadowdarklingsActor(data) {
|
|||||||
cha: { value: data.cha }
|
cha: { value: data.cha }
|
||||||
},
|
},
|
||||||
ac: { value: data.ac },
|
ac: { value: data.ac },
|
||||||
hp: { value: data.hp, max: data.hp },
|
hp: { value: data.hp, max: data.hp || data.maxHp, min: 0 },
|
||||||
level: { value: data.level },
|
level: { value: data.level },
|
||||||
class: { value: data.class },
|
class: { value: data.class },
|
||||||
race: { value: data.race },
|
ancestry: { value: data.race },
|
||||||
alignment: { value: data.alignment },
|
alignment: { value: data.alignment }
|
||||||
// Add more mappings as fits your needs and data
|
// Extend as needed for your Shadowdark system version
|
||||||
},
|
},
|
||||||
// Optionally add avatar/portrait: img: data.img
|
// Optionally add image
|
||||||
// Optionally import inventory as embedded items, etc.
|
// img: data.img || "icons/svg/mystery-man.svg"
|
||||||
};
|
};
|
||||||
|
|
||||||
// Try to import inventory if present
|
// Try inventory import (if system supports embedded items in actors)
|
||||||
if (Array.isArray(data.inventory)) {
|
if (Array.isArray(data.inventory)) {
|
||||||
actorData.items = data.inventory.map(itm => ({
|
actorData.items = data.inventory.filter(i=>i.name).map(itm => ({
|
||||||
name: itm.name,
|
name: itm.name,
|
||||||
type: "equipment", // Guess, or use your actual item types
|
type: "equipment", // Or "gear" or your actual item type in Shadowdark
|
||||||
system: {
|
system: {
|
||||||
description: { value: itm.description || "" },
|
description: { value: itm.description || "" },
|
||||||
quantity: itm.quantity || 1,
|
quantity: itm.quantity || 1,
|
||||||
value: itm.value || "",
|
value: itm.value || "",
|
||||||
weight: itm.weight || "",
|
weight: itm.weight || ""
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the actor in the current folder
|
// Create the actor using v12 Documents API
|
||||||
try {
|
try {
|
||||||
await Actor.create(actorData);
|
const created = await Actor.createDocuments([actorData], {parent: game.actors});
|
||||||
ui.notifications.info(`${actorData.name} imported successfully!`);
|
ui.notifications.info(`${actorData.name} imported successfully!`);
|
||||||
|
// Optionally, highlight/select the imported actor
|
||||||
|
if (created.length && app) {
|
||||||
|
app._lastSelected = [created[0].id];
|
||||||
|
app.render();
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
ui.notifications.error("Actor import failed.");
|
ui.notifications.error("Actor import failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function importShadowdarklingsItem(data) {
|
// Items (single or list)
|
||||||
|
async function importShadowdarklingsItem(data, app) {
|
||||||
// Accept single or array of items
|
// Accept single or array of items
|
||||||
const items = Array.isArray(data) ? data : [data];
|
const items = Array.isArray(data) ? data : [data];
|
||||||
|
let created = [];
|
||||||
for (let itm of items) {
|
for (let itm of items) {
|
||||||
if (!itm.name) continue;
|
if (!itm.name) continue;
|
||||||
const itemData = {
|
const itemData = {
|
||||||
name: itm.name,
|
name: itm.name,
|
||||||
type: itm.type || "equipment",
|
type: itm.type || "equipment", // Check your Shadowdark item types!
|
||||||
system: {
|
system: {
|
||||||
description: { value: itm.description || "" },
|
description: { value: itm.description || "" },
|
||||||
// Add other fields as needed
|
quantity: itm.quantity || 1
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
await Item.create(itemData);
|
const docs = await Item.createDocuments([itemData], {parent: game.items});
|
||||||
|
created.push(...docs);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
ui.notifications.warn(`Failed to import item: ${itm.name}`);
|
ui.notifications.warn(`Failed to import item: ${itm.name}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui.notifications.info("Items imported.");
|
if (created.length > 0) ui.notifications.info("Items imported.");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user