Import de masse des PNJ ancien système
Release Creation / build (release) Successful in 1m13s

This commit is contained in:
2026-06-10 22:16:25 +02:00
parent 20b41f2cd4
commit faf8c4ca92
8 changed files with 549 additions and 37 deletions
+143 -8
View File
@@ -311,6 +311,89 @@ function migrateSupernaturalItem(oldItem) {
}
};
}
function migrateWeaponItem(oldItem) {
const s = oldItem.system ?? {};
return {
name: oldItem.name,
type: "weapon",
img: oldItem.img || DEFAULT_ITEM_IMG,
system: {
reference: s.reference ?? "",
description: s.description ?? "",
hasSpeciality: Boolean(s.hasSpeciality),
weaponType: s.weaponType || "melee",
material: s.material ?? "",
damageAspect: elementKey(s.damageAspect ?? ""),
damageBase: Number(s.damageBase ?? 0),
range: s.range || "contact",
obtainLevel: Number(s.obtainLevel ?? 0),
obtainDifficulty: Number(s.obtainDifficulty ?? 0),
quantity: Number(s.quantity ?? 1),
notes: s.notes ?? ""
}
};
}
function migrateArmorItem(oldItem) {
const s = oldItem.system ?? {};
return {
name: oldItem.name,
type: "armor",
img: oldItem.img || DEFAULT_ITEM_IMG,
system: {
reference: s.reference ?? "",
description: s.description ?? "",
protectionValue: Number(s.protectionValue ?? 0),
domain: s.domain ?? "",
obtainLevel: Number(s.obtainLevel ?? 0),
obtainDifficulty: Number(s.obtainDifficulty ?? 0),
quantity: Number(s.quantity ?? 1),
notes: s.notes ?? ""
}
};
}
function migrateSanheiItem(oldItem) {
const s = oldItem.system ?? {};
const props = s.properties ?? {};
const propSchema = (p) => ({
name: p?.name ?? "",
heiCost: Number(p?.heiCost ?? 0),
heiType: heiKey(p?.heiType ?? ""),
description: p?.description ?? ""
});
return {
name: oldItem.name,
type: "sanhei",
img: oldItem.img || DEFAULT_ITEM_IMG,
system: {
reference: s.reference ?? "",
description: s.description ?? "",
heiType: heiKey(s.heiType ?? ""),
properties: {
prop1: propSchema(props.prop1),
prop2: propSchema(props.prop2),
prop3: propSchema(props.prop3)
},
notes: s.notes ?? ""
}
};
}
function migrateIngredientItem(oldItem) {
const s = oldItem.system ?? {};
return {
name: oldItem.name,
type: "ingredient",
img: oldItem.img || DEFAULT_ITEM_IMG,
system: {
reference: s.reference ?? "",
description: s.description ?? "",
school: s.school ?? "all",
obtainLevel: Number(s.obtainLevel ?? 0),
obtainDifficulty: Number(s.obtainDifficulty ?? 0),
quantity: Number(s.quantity ?? 1),
notes: s.notes ?? ""
}
};
}
function migrateItem(oldItem) {
switch (oldItem.type) {
case "item":
@@ -321,6 +404,14 @@ function migrateItem(oldItem) {
return migrateSpellItem(oldItem);
case "supernatural":
return migrateSupernaturalItem(oldItem);
case "weapon":
return migrateWeaponItem(oldItem);
case "armor":
return migrateArmorItem(oldItem);
case "sanhei":
return migrateSanheiItem(oldItem);
case "ingredient":
return migrateIngredientItem(oldItem);
default:
return migrateEquipmentItem({ ...oldItem, type: "item" });
}
@@ -394,6 +485,7 @@ function migrateCharacter(old) {
resources,
component,
magics,
magicOrder: [],
threetreasures,
experience: {
value: Number(s.experience?.value ?? 0),
@@ -471,10 +563,12 @@ var CDEMigrationApp = class _CDEMigrationApp extends foundry.applications.api.Ha
icon: "fas fa-file-import",
resizable: false
},
position: { width: 560, height: "auto" },
position: { width: 600, height: "auto" },
actions: {
clearFiles: _CDEMigrationApp.#clearFiles,
doImport: _CDEMigrationApp.#doImport
doImport: _CDEMigrationApp.#doImport,
confirmImport: _CDEMigrationApp.#confirmImport,
cancelImport: _CDEMigrationApp.#cancelImport
}
};
static PARTS = {
@@ -484,13 +578,28 @@ var CDEMigrationApp = class _CDEMigrationApp extends foundry.applications.api.Ha
#pending = [];
/** @type {string[]} - error messages per file */
#errors = [];
/** @type {"idle"|"confirm"|"importing"} */
#importState = "idle";
/** @type {number} - actors created so far (during importing) */
#progress = 0;
async _prepareContext(options) {
const enrichDuplicate = (a) => ({
...a,
_duplicate: game.actors?.getName(a.name) !== null
});
const pending = this.#pending.map(enrichDuplicate);
const duplicateCount = pending.filter((a) => a._duplicate).length;
return {
pending: this.#pending,
pending,
errors: this.#errors,
hasPending: this.#pending.length > 0,
hasErrors: this.#errors.length > 0,
count: this.#pending.length
hasDuplicates: duplicateCount > 0,
duplicateCount,
count: this.#pending.length,
importState: this.#importState,
progress: this.#progress,
total: this.#pending.length
};
}
/** After render, wire up the file input. */
@@ -528,37 +637,59 @@ var CDEMigrationApp = class _CDEMigrationApp extends foundry.applications.api.Ha
const actors = parseLegacyJson(text);
for (const actor of actors) {
actor._srcFile = file.name;
if (!this.#pending.some((p) => p.name === actor.name)) {
this.#pending.push(actor);
if (this.#pending.some((p) => p.name === actor.name)) {
this.#errors.push(`\xAB ${actor.name} \xBB ignor\xE9 (nom d\xE9j\xE0 dans la liste d'attente, fichier \xAB ${file.name} \xBB)`);
continue;
}
this.#pending.push(actor);
}
} catch (err) {
this.#errors.push(game.i18n.format("CDE.MigrationErrorParse", { file: file.name, error: err.message }));
}
}
this.#importState = "idle";
this.render();
}
static async #clearFiles() {
this.#pending = [];
this.#errors = [];
this.#importState = "idle";
this.#progress = 0;
this.render();
}
/** First click: switch to confirmation state instead of importing immediately. */
static async #doImport() {
if (!this.#pending.length) return;
this.#importState = "confirm";
this.render();
}
/** Second click: actually perform the import. */
static async #confirmImport() {
if (!this.#pending.length) return;
this.#importState = "importing";
this.#progress = 0;
this.render();
const total = this.#pending.length;
const created = [];
const failed = [];
for (const data of this.#pending) {
for (let i = 0; i < total; i++) {
const data = this.#pending[i];
try {
const { _srcFile, ...actorData } = data;
const actor = await Actor.create(actorData);
created.push(actor.name);
} catch (err) {
failed.push(`${data.name}: ${err.message}`);
console.error(`CHRONIQUESDELETRANGE | Migration failed for "${data.name}":`, err);
console.error(`CHRONIQUESDELETRANGE | Import failed for "${data.name}":`, err);
}
this.#progress = i + 1;
const progEl = this.element?.querySelector(".cde-migration-progress-count");
if (progEl) progEl.textContent = `${this.#progress}/${total}`;
}
this.#pending = [];
this.#errors = failed;
this.#importState = "idle";
this.#progress = 0;
this.render();
if (created.length) {
ui.notifications.info(
@@ -571,6 +702,10 @@ var CDEMigrationApp = class _CDEMigrationApp extends foundry.applications.api.Ha
);
}
}
static async #cancelImport() {
this.#importState = "idle";
this.render();
}
};
// src/config/settings.js