Compare commits
5 Commits
14.0.6
..
4cb8e26333
| Author | SHA1 | Date | |
|---|---|---|---|
| 4cb8e26333 | |||
| faf8c4ca92 | |||
| 20b41f2cd4 | |||
| 34b7e32d08 | |||
| 75f79c1c08 |
@@ -2179,6 +2179,25 @@ section.npc .cde-neon-tabs .item.active {
|
||||
.cde-magic-toggle:hover i {
|
||||
color: #e2e8f4;
|
||||
}
|
||||
.cde-magic-order-btn {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
color: #7d94b8;
|
||||
border-radius: 3px;
|
||||
flex-shrink: 0;
|
||||
transition: color 0.12s, background 0.12s;
|
||||
}
|
||||
.cde-magic-order-btn i {
|
||||
font-size: 9px;
|
||||
}
|
||||
.cde-magic-order-btn:hover {
|
||||
color: #e2e8f4;
|
||||
background: rgba(38, 56, 83, 0.25);
|
||||
}
|
||||
.cde-magic-specialities {
|
||||
border-top: 1px solid #1a2436;
|
||||
padding: 4px 0;
|
||||
@@ -3190,7 +3209,9 @@ ol.item-list li.item h4.item-name {
|
||||
flex: 1 1 0;
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #e2e8f4;
|
||||
font-family: "Signika", sans-serif;
|
||||
}
|
||||
ol.item-list li.item .cde-item-stat {
|
||||
font-family: monospace;
|
||||
@@ -3523,6 +3544,12 @@ ol.item-list li.item .item-controls a.item-control:hover {
|
||||
color: var(--rr-accent, #e2e8f4);
|
||||
text-shadow: 0 0 12px var(--rr-accent, transparent);
|
||||
}
|
||||
.cde-roll-result .cde-rr-hero .cde-rr-spell-power .cde-rr-spell-power-formula {
|
||||
font-size: 10px;
|
||||
color: #7d94b8;
|
||||
margin: 2px 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.cde-roll-result .cde-rr-hero .cde-rr-spell-power .cde-rr-spell-power-label {
|
||||
font-size: 9px;
|
||||
font-weight: 700;
|
||||
@@ -4418,6 +4445,105 @@ ol.item-list li.item .item-controls a.item-control:hover {
|
||||
color: #7d94b8;
|
||||
text-align: center;
|
||||
}
|
||||
/* Duplicate row highlight */
|
||||
.cde-migration-row-duplicate {
|
||||
background: rgba(212, 175, 55, 0.15);
|
||||
}
|
||||
.cde-migration-duplicate-icon {
|
||||
color: #d4af37;
|
||||
margin-right: 4px;
|
||||
font-size: 11px;
|
||||
}
|
||||
/* Confirmation bar */
|
||||
.cde-migration-confirm-bar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 12px;
|
||||
border: 1px solid rgba(212, 175, 55, 0.7);
|
||||
border-radius: 6px;
|
||||
background: rgba(212, 175, 55, 0.1);
|
||||
}
|
||||
.cde-migration-confirm-msg {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
color: #e2e8f4;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.cde-migration-confirm-msg i {
|
||||
color: #d4af37;
|
||||
}
|
||||
.cde-migration-confirm-duplicates {
|
||||
margin: 0;
|
||||
font-size: 11px;
|
||||
color: #e07070;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.cde-migration-confirm-duplicates i {
|
||||
color: #e07070;
|
||||
}
|
||||
.cde-migration-confirm-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.cde-migration-confirm-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 9px 24px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
background: #4a9eff;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: filter 0.15s;
|
||||
}
|
||||
.cde-migration-confirm-btn:hover {
|
||||
filter: brightness(1.15);
|
||||
}
|
||||
.cde-migration-cancel-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 9px 24px;
|
||||
border: 1px solid #1a2436;
|
||||
border-radius: 6px;
|
||||
background: none;
|
||||
color: #7d94b8;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
transition: color 0.15s, border-color 0.15s;
|
||||
}
|
||||
.cde-migration-cancel-btn:hover {
|
||||
color: #e04444;
|
||||
border-color: #e04444;
|
||||
}
|
||||
/* Progress section */
|
||||
.cde-migration-progress {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
padding: 16px;
|
||||
font-size: 13px;
|
||||
color: #e2e8f4;
|
||||
}
|
||||
.cde-migration-progress i {
|
||||
color: #4a9eff;
|
||||
}
|
||||
.cde-migration-progress-count {
|
||||
font-weight: 700;
|
||||
color: #4a9eff;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.cde-welcome-message {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
+131
-1
@@ -2253,6 +2253,23 @@ section.npc .cde-neon-tabs .item.active { color: @cde-supernatural; borde
|
||||
&:hover i { color: @cde-text; }
|
||||
}
|
||||
|
||||
.cde-magic-order-btn {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
color: @cde-muted;
|
||||
border-radius: 3px;
|
||||
flex-shrink: 0;
|
||||
transition: color 0.12s, background 0.12s;
|
||||
|
||||
i { font-size: 9px; }
|
||||
|
||||
&:hover { color: @cde-text; background: fade(@cde-border-hi, 25%); }
|
||||
}
|
||||
|
||||
// Specialities list
|
||||
.cde-magic-specialities {
|
||||
border-top: 1px solid @cde-border;
|
||||
@@ -3247,7 +3264,7 @@ ol.item-list {
|
||||
|
||||
img { border: none; border-radius: 3px; flex-shrink: 0; }
|
||||
|
||||
h4.item-name { flex: 1 1 0; margin: 0; font-size: 13px; color: @cde-text; }
|
||||
h4.item-name { flex: 1 1 0; margin: 0; font-size: 13px; font-weight: 600; color: @cde-text; font-family: "Signika", sans-serif; }
|
||||
|
||||
.cde-item-stat {
|
||||
font-family: monospace;
|
||||
@@ -3582,6 +3599,13 @@ ol.item-list {
|
||||
text-shadow: 0 0 12px var(--rr-accent, transparent);
|
||||
}
|
||||
|
||||
.cde-rr-spell-power-formula {
|
||||
font-size: 10px;
|
||||
color: @cde-muted;
|
||||
margin: 2px 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.cde-rr-spell-power-label {
|
||||
font-size: 9px;
|
||||
font-weight: 700;
|
||||
@@ -4607,6 +4631,112 @@ ol.item-list {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Duplicate row highlight */
|
||||
.cde-migration-row-duplicate {
|
||||
background: fadeout(#d4af37, 85%);
|
||||
}
|
||||
|
||||
.cde-migration-duplicate-icon {
|
||||
color: #d4af37;
|
||||
margin-right: 4px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/* Confirmation bar */
|
||||
.cde-migration-confirm-bar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 12px;
|
||||
border: 1px solid fadeout(#d4af37, 30%);
|
||||
border-radius: 6px;
|
||||
background: fadeout(#d4af37, 90%);
|
||||
}
|
||||
|
||||
.cde-migration-confirm-msg {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
color: @cde-text;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
|
||||
i { color: #d4af37; }
|
||||
}
|
||||
|
||||
.cde-migration-confirm-duplicates {
|
||||
margin: 0;
|
||||
font-size: 11px;
|
||||
color: #e07070;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
|
||||
i { color: #e07070; }
|
||||
}
|
||||
|
||||
.cde-migration-confirm-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.cde-migration-confirm-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 9px 24px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
background: @cde-spell;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: filter 0.15s;
|
||||
|
||||
&:hover { filter: brightness(1.15); }
|
||||
}
|
||||
|
||||
.cde-migration-cancel-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 9px 24px;
|
||||
border: 1px solid @cde-border;
|
||||
border-radius: 6px;
|
||||
background: none;
|
||||
color: @cde-muted;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
transition: color 0.15s, border-color 0.15s;
|
||||
|
||||
&:hover {
|
||||
color: #e04444;
|
||||
border-color: #e04444;
|
||||
}
|
||||
}
|
||||
|
||||
/* Progress section */
|
||||
.cde-migration-progress {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
padding: 16px;
|
||||
font-size: 13px;
|
||||
color: @cde-text;
|
||||
|
||||
i { color: @cde-spell; }
|
||||
}
|
||||
|
||||
.cde-migration-progress-count {
|
||||
font-weight: 700;
|
||||
color: @cde-spell;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Welcome message
|
||||
// ============================================================
|
||||
|
||||
Vendored
+263
-79
@@ -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
|
||||
@@ -661,6 +796,7 @@ function preLocalizeConfig() {
|
||||
magic.aspectlabel = game.i18n.localize(magic.aspectlabel);
|
||||
Object.values(magic.speciality).forEach((spec) => {
|
||||
spec.label = game.i18n.localize(spec.label);
|
||||
spec.labelelementkey = spec.labelelement;
|
||||
spec.labelelement = game.i18n.localize(spec.labelelement);
|
||||
});
|
||||
});
|
||||
@@ -774,9 +910,8 @@ var CharacterDataModel = class extends foundry.abstract.TypeDataModel {
|
||||
typeofthrow: numberField(0),
|
||||
aspectskill: numberField(0),
|
||||
bonusmalusskill: numberField(0),
|
||||
aspectspeciality: numberField(0),
|
||||
rolldifficulty: numberField(0),
|
||||
bonusmalusspeciality: numberField(0)
|
||||
freepowerlevels: numberField(0)
|
||||
})
|
||||
}),
|
||||
aspect: new fields.SchemaField({
|
||||
@@ -815,6 +950,10 @@ var CharacterDataModel = class extends foundry.abstract.TypeDataModel {
|
||||
nine: componentField(),
|
||||
zero: componentField()
|
||||
}),
|
||||
magicOrder: new fields.ArrayField(
|
||||
new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
{ required: true, initial: [] }
|
||||
),
|
||||
magics: new fields.SchemaField({
|
||||
internalcinnabar: magicField(),
|
||||
alchemy: magicField(),
|
||||
@@ -931,7 +1070,7 @@ var KungfuDataModel = class extends foundry.abstract.TypeDataModel {
|
||||
orientation: stringField("yin"),
|
||||
// yin | yang | yinyang
|
||||
aspect: stringField("metal"),
|
||||
// metal | eau | terre | feu | bois
|
||||
// metal | water | earth | fire | wood
|
||||
skill: stringField("kungfu"),
|
||||
// kungfu | rangedcombat
|
||||
speciality: stringField(""),
|
||||
@@ -957,7 +1096,7 @@ var SpellDataModel = class extends foundry.abstract.TypeDataModel {
|
||||
description: htmlField(""),
|
||||
specialityname: stringField(""),
|
||||
associatedelement: stringField("metal"),
|
||||
// metal | eau | terre | feu | bois
|
||||
// metal | water | earth | fire | wood
|
||||
hei: stringField(""),
|
||||
realizationtimeritual: stringField(""),
|
||||
realizationtimeaccelerated: stringField(""),
|
||||
@@ -1012,7 +1151,7 @@ var WeaponDataModel = class extends foundry.abstract.TypeDataModel {
|
||||
// contact | courte | mediane | longue | extreme
|
||||
obtainLevel: intField(0, { min: 0, max: 5 }),
|
||||
obtainDifficulty: intField(0, { min: 0, max: 3 }),
|
||||
quantity: intField(1),
|
||||
quantity: intField(1, { min: 0 }),
|
||||
notes: htmlField("")
|
||||
};
|
||||
}
|
||||
@@ -1032,7 +1171,7 @@ var ArmorDataModel = class extends foundry.abstract.TypeDataModel {
|
||||
domain: stringField(""),
|
||||
obtainLevel: intField(0, { min: 0, max: 5 }),
|
||||
obtainDifficulty: intField(0, { min: 0, max: 3 }),
|
||||
quantity: intField(1),
|
||||
quantity: intField(1, { min: 0 }),
|
||||
notes: htmlField("")
|
||||
};
|
||||
}
|
||||
@@ -1078,7 +1217,7 @@ var IngredientDataModel = class extends foundry.abstract.TypeDataModel {
|
||||
school: stringField("all"),
|
||||
obtainLevel: intField(0, { min: 0, max: 5 }),
|
||||
obtainDifficulty: intField(0, { min: 0, max: 3 }),
|
||||
quantity: intField(1),
|
||||
quantity: intField(1, { min: 0 }),
|
||||
notes: htmlField("")
|
||||
};
|
||||
}
|
||||
@@ -1568,20 +1707,16 @@ async function showMagicPrompt(params) {
|
||||
aspectskill: Number(params.aspectskill ?? 0),
|
||||
bonusmalusskill: params.bonusmalusskill ?? 0,
|
||||
bonusauspiciousdice: params.bonusauspiciousdice ?? 0,
|
||||
aspectspeciality: Number(params.aspectspeciality ?? 0),
|
||||
rolldifficulty: params.rolldifficulty ?? 1,
|
||||
bonusmalusspeciality: params.bonusmalusspeciality ?? 0,
|
||||
heispend: params.heispend ?? 0,
|
||||
freepowerlevels: params.freepowerlevels ?? 0,
|
||||
typeofthrow: Number(params.typeofthrow ?? 0)
|
||||
},
|
||||
fields: [
|
||||
"aspectskill",
|
||||
"bonusmalusskill",
|
||||
"bonusauspiciousdice",
|
||||
"aspectspeciality",
|
||||
"rolldifficulty",
|
||||
"bonusmalusspeciality",
|
||||
"heispend",
|
||||
"freepowerlevels",
|
||||
"typeofthrow"
|
||||
]
|
||||
});
|
||||
@@ -1711,7 +1846,9 @@ async function rollForActor(actor, rollKey) {
|
||||
const kfSkill = kfItem.system.skill ?? "kungfu";
|
||||
numberofdice = sys.skills?.[kfSkill]?.value ?? 0;
|
||||
title = `${kfItem.name} [${game.i18n.localize(sys.skills?.[kfSkill]?.label ?? "CDE.KungFu")}]`;
|
||||
kfDefaultAspect = ASPECT_NAMES.indexOf(kfItem.system.aspect ?? "metal");
|
||||
const kfAspect = kfItem.system.aspect?.toLowerCase() ?? "metal";
|
||||
const ASPECT_NORMALIZE = { eau: "water", terre: "earth", feu: "fire", bois: "wood" };
|
||||
kfDefaultAspect = ASPECT_NAMES.indexOf(ASPECT_NORMALIZE[kfAspect] ?? kfAspect);
|
||||
if (kfDefaultAspect < 0) kfDefaultAspect = 0;
|
||||
break;
|
||||
}
|
||||
@@ -1813,7 +1950,10 @@ async function rollForActor(actor, rollKey) {
|
||||
d0: wpFaces[0]
|
||||
}, wpRoll, ROLL_MODES[wpThrowMode] ?? "roll");
|
||||
if (game.modules.get("dice-so-nice")?.active && wpMsg?.id) {
|
||||
await game.dice3d.waitFor3DAnimationByMessageID(wpMsg.id);
|
||||
try {
|
||||
await game.dice3d.waitFor3DAnimationByMessageID(wpMsg.id);
|
||||
} catch (_e) {
|
||||
}
|
||||
}
|
||||
if ((wpResults.loksyudice ?? 0) > 0) await updateLoksyuFromRoll(wpAspectName, wpFaces);
|
||||
if ((wpResults.tinjidice ?? 0) > 0) await updateTinjiFromRoll(wpResults.tinjidice);
|
||||
@@ -1846,14 +1986,6 @@ async function rollForActor(actor, rollKey) {
|
||||
if (kfDefaultAspect >= 0) {
|
||||
defaultAspect = kfDefaultAspect;
|
||||
}
|
||||
let defaultSpecialAspect = 0;
|
||||
if (isMagicSpecial && specialLibel) {
|
||||
const specialCfg = MAGICS?.[skillLibel]?.speciality?.[specialLibel];
|
||||
const aspectName = LABELELEMENT_TO_ASPECT[specialCfg?.labelelement];
|
||||
if (aspectName) {
|
||||
defaultSpecialAspect = ASPECT_NAMES.indexOf(aspectName);
|
||||
}
|
||||
}
|
||||
let params;
|
||||
if (isMagic) {
|
||||
params = await showMagicPrompt({
|
||||
@@ -1862,10 +1994,8 @@ async function rollForActor(actor, rollKey) {
|
||||
aspectskill: defaultAspect,
|
||||
bonusmalusskill: 0,
|
||||
bonusauspiciousdice: 0,
|
||||
aspectspeciality: defaultSpecialAspect,
|
||||
rolldifficulty: 1,
|
||||
bonusmalusspeciality: 0,
|
||||
heispend: 0,
|
||||
freepowerlevels: 0,
|
||||
typeofthrow: typeOfThrow
|
||||
});
|
||||
} else {
|
||||
@@ -1882,20 +2012,16 @@ async function rollForActor(actor, rollKey) {
|
||||
}
|
||||
if (!params) return;
|
||||
let aspectIndex, bonusMalus, bonusAuspicious, throwMode;
|
||||
let spellAspectIndex = null;
|
||||
let rollDifficulty = 1;
|
||||
if (isMagic) {
|
||||
const skillAspectIndex = Number(params.aspectskill ?? 0);
|
||||
spellAspectIndex = Number(params.aspectspeciality ?? skillAspectIndex);
|
||||
aspectIndex = skillAspectIndex;
|
||||
bonusMalus = Number(params.bonusmalusskill ?? 0);
|
||||
bonusAuspicious = Number(params.bonusauspiciousdice ?? 0);
|
||||
rollDifficulty = Math.max(1, Number(params.rolldifficulty ?? 1));
|
||||
throwMode = Number(params.typeofthrow ?? 0);
|
||||
const aspectDice = sys.aspect?.[ASPECT_NAMES[aspectIndex]]?.value ?? 0;
|
||||
const bonusSpec = Number(params.bonusmalusspeciality ?? 0);
|
||||
const heiDice = Number(params.heispend ?? 0);
|
||||
numberofdice = numberofdice + aspectDice + bonusMalus + 1 + bonusSpec + heiDice;
|
||||
numberofdice = numberofdice + aspectDice + bonusMalus + 1;
|
||||
} else {
|
||||
aspectIndex = Number(params.aspect ?? 0);
|
||||
bonusMalus = Number(params.bonusmalus ?? 0);
|
||||
@@ -1913,22 +2039,33 @@ async function rollForActor(actor, rollKey) {
|
||||
const roll = new Roll(`${numberofdice}d10`);
|
||||
await roll.evaluate();
|
||||
const rollModeKey = ROLL_MODES[throwMode] ?? "roll";
|
||||
const wuXingAspectName = spellAspectIndex !== null ? ASPECT_NAMES[spellAspectIndex] : ASPECT_NAMES[aspectIndex];
|
||||
let spellPower = null;
|
||||
let spellPowerAspectName = null;
|
||||
let spellPowerAspectValue = null;
|
||||
if (isMagic) {
|
||||
if (isMagicSpecial && specialLibel) {
|
||||
const specialCfg = MAGICS?.[skillLibel]?.speciality?.[specialLibel];
|
||||
const elemName = LABELELEMENT_TO_ASPECT[specialCfg?.labelelementkey];
|
||||
if (elemName) spellPowerAspectName = elemName;
|
||||
}
|
||||
if (!spellPowerAspectName) spellPowerAspectName = ASPECT_NAMES[aspectIndex];
|
||||
spellPowerAspectValue = sys.aspect?.[spellPowerAspectName]?.value ?? 0;
|
||||
const freePowerLevels = Number(params.freepowerlevels ?? 0);
|
||||
spellPower = rollDifficulty * (spellPowerAspectValue + freePowerLevels);
|
||||
}
|
||||
const wuXingAspectName = ASPECT_NAMES[aspectIndex];
|
||||
const allResults = roll.dice[0]?.results ?? [];
|
||||
const faces = countFaces(allResults);
|
||||
const results = computeWuXingResults(faces, wuXingAspectName, bonusAuspicious);
|
||||
if (!results) return;
|
||||
const spellPower = isMagic ? results.successesdice * rollDifficulty : null;
|
||||
const modParts = [];
|
||||
if (isMagic) {
|
||||
const bm = Number(params.bonusmalusskill ?? 0);
|
||||
const bs = Number(params.bonusmalusspeciality ?? 0);
|
||||
const hs = Number(params.heispend ?? 0);
|
||||
const ba = Number(params.bonusauspiciousdice ?? 0);
|
||||
const fp = Number(params.freepowerlevels ?? 0);
|
||||
if (bm !== 0) modParts.push(`${bm > 0 ? "+" : ""}${bm} ${game.i18n.localize("CDE.BonusMalus")}`);
|
||||
if (bs !== 0) modParts.push(`${bs > 0 ? "+" : ""}${bs} ${game.i18n.localize("CDE.SpellBonus")}`);
|
||||
if (ba !== 0) modParts.push(`+${ba} ${game.i18n.localize("CDE.BonusAuspiciousDice")}`);
|
||||
if (hs !== 0) modParts.push(`${hs} ${game.i18n.localize("CDE.HeiSpend")}`);
|
||||
if (fp !== 0) modParts.push(`+${fp} ${game.i18n.localize("CDE.FreePowerLevels")}`);
|
||||
if (rollDifficulty !== 1) modParts.push(`\xD7${rollDifficulty} ${game.i18n.localize("CDE.RollDifficulty")}`);
|
||||
} else {
|
||||
const bm = Number(params.bonusmalus ?? 0);
|
||||
@@ -1948,6 +2085,9 @@ async function rollForActor(actor, rollKey) {
|
||||
modifiersText: modParts.length ? modParts.join(" \xB7 ") : "",
|
||||
// Spell power (magic only)
|
||||
spellPower,
|
||||
spellPowerAspectLabel: spellPowerAspectName ? game.i18n.localize(ASPECT_LABELS[spellPowerAspectName] ?? "") : "",
|
||||
spellPowerAspectValue,
|
||||
spellPowerFreeLevels: isMagic ? Number(params.freepowerlevels ?? 0) : 0,
|
||||
rollDifficulty: isMagic ? rollDifficulty : null,
|
||||
// Actor info
|
||||
actorName: actor.name ?? "",
|
||||
@@ -1968,7 +2108,10 @@ async function rollForActor(actor, rollKey) {
|
||||
d0: faces[0]
|
||||
}, roll, rollModeKey);
|
||||
if (game.modules.get("dice-so-nice")?.active && msg?.id) {
|
||||
await game.dice3d.waitFor3DAnimationByMessageID(msg.id);
|
||||
try {
|
||||
await game.dice3d.waitFor3DAnimationByMessageID(msg.id);
|
||||
} catch (_e) {
|
||||
}
|
||||
}
|
||||
if ((results.loksyudice ?? 0) > 0) await updateLoksyuFromRoll(wuXingAspectName, faces);
|
||||
if ((results.tinjidice ?? 0) > 0) await updateTinjiFromRoll(results.tinjidice);
|
||||
@@ -2064,9 +2207,13 @@ var CDEBaseActorSheet = class _CDEBaseActorSheet extends HandlebarsApplicationMi
|
||||
};
|
||||
|
||||
// src/ui/sheets/actors/character.js
|
||||
var CDECharacterSheet = class extends CDEBaseActorSheet {
|
||||
var CDECharacterSheet = class _CDECharacterSheet extends CDEBaseActorSheet {
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["character"]
|
||||
classes: ["character"],
|
||||
actions: {
|
||||
moveMagicUp: _CDECharacterSheet.#onMoveMagicUp,
|
||||
moveMagicDown: _CDECharacterSheet.#onMoveMagicDown
|
||||
}
|
||||
};
|
||||
static PARTS = {
|
||||
main: { template: "systems/fvtt-chroniques-de-l-etrange/templates/actor/cde-character-sheet.html" }
|
||||
@@ -2089,25 +2236,35 @@ var CDECharacterSheet = class extends CDEBaseActorSheet {
|
||||
spellsByDiscipline[disc].push(spell);
|
||||
}
|
||||
const systemMagics = context.systemData.magics ?? {};
|
||||
context.magicsDisplay = Object.fromEntries(
|
||||
Object.entries(MAGICS).map(([magicKey, magicDef]) => {
|
||||
const magicData = systemMagics[magicKey] ?? {};
|
||||
return [
|
||||
magicKey,
|
||||
{
|
||||
value: magicData.value ?? 0,
|
||||
visible: magicData.visible ?? false,
|
||||
speciality: Object.fromEntries(
|
||||
Object.keys(magicDef.speciality).map((specKey) => [
|
||||
specKey,
|
||||
{ check: magicData.speciality?.[specKey]?.check ?? false }
|
||||
])
|
||||
),
|
||||
grimoire: spellsByDiscipline[magicKey] ?? []
|
||||
}
|
||||
];
|
||||
})
|
||||
);
|
||||
const magicEntries = Object.entries(MAGICS).map(([magicKey, magicDef]) => {
|
||||
const magicData = systemMagics[magicKey] ?? {};
|
||||
return [
|
||||
magicKey,
|
||||
{
|
||||
value: magicData.value ?? 0,
|
||||
visible: magicData.visible ?? false,
|
||||
speciality: Object.fromEntries(
|
||||
Object.keys(magicDef.speciality).map((specKey) => [
|
||||
specKey,
|
||||
{ check: magicData.speciality?.[specKey]?.check ?? false }
|
||||
])
|
||||
),
|
||||
grimoire: spellsByDiscipline[magicKey] ?? []
|
||||
}
|
||||
];
|
||||
});
|
||||
const order = context.systemData.magicOrder ?? [];
|
||||
if (order.length > 0) {
|
||||
magicEntries.sort((a, b) => {
|
||||
const ia = order.indexOf(a[0]);
|
||||
const ib = order.indexOf(b[0]);
|
||||
if (ia === -1 && ib === -1) return 0;
|
||||
if (ia === -1) return 1;
|
||||
if (ib === -1) return -1;
|
||||
return ia - ib;
|
||||
});
|
||||
}
|
||||
context.magicsDisplay = Object.fromEntries(magicEntries);
|
||||
return context;
|
||||
}
|
||||
_onRender(context, options) {
|
||||
@@ -2191,7 +2348,7 @@ var CDECharacterSheet = class extends CDEBaseActorSheet {
|
||||
cell.addEventListener("click", (event) => {
|
||||
event.preventDefault();
|
||||
const rollKey = cell.dataset.libelId;
|
||||
if (rollKey) rollForActor(this.document, rollKey);
|
||||
if (rollKey) rollForActor(this.document, rollKey)?.catch((err) => console.error("Roll failed:", err));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -2205,6 +2362,26 @@ var CDECharacterSheet = class extends CDEBaseActorSheet {
|
||||
}).render(true);
|
||||
});
|
||||
}
|
||||
static async #onMoveMagicUp(event, target) {
|
||||
const key = target.dataset.magicKey;
|
||||
let order = this.document.system.magicOrder ?? [];
|
||||
if (!order.length) order = [...Object.keys(MAGICS)];
|
||||
else order = [...order];
|
||||
const idx = order.indexOf(key);
|
||||
if (idx <= 0) return;
|
||||
[order[idx - 1], order[idx]] = [order[idx], order[idx - 1]];
|
||||
await this.document.update({ "system.magicOrder": order });
|
||||
}
|
||||
static async #onMoveMagicDown(event, target) {
|
||||
const key = target.dataset.magicKey;
|
||||
let order = this.document.system.magicOrder ?? [];
|
||||
if (!order.length) order = [...Object.keys(MAGICS)];
|
||||
else order = [...order];
|
||||
const idx = order.indexOf(key);
|
||||
if (idx === -1 || idx >= order.length - 1) return;
|
||||
[order[idx], order[idx + 1]] = [order[idx + 1], order[idx]];
|
||||
await this.document.update({ "system.magicOrder": order });
|
||||
}
|
||||
#bindComponentRandomize() {
|
||||
const btn = this.element?.querySelector("[data-action='randomize-component']");
|
||||
if (!btn) return;
|
||||
@@ -2274,7 +2451,7 @@ var CDENpcSheet = class extends CDEBaseActorSheet {
|
||||
cell.addEventListener("click", (event) => {
|
||||
event.preventDefault();
|
||||
const rollKey = cell.dataset.libelId;
|
||||
if (rollKey) rollForActor(this.document, rollKey);
|
||||
if (rollKey) rollForActor(this.document, rollKey)?.catch((err) => console.error("Roll failed:", err));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -2461,11 +2638,11 @@ var CDESanheiSheet = class extends CDEBaseItemSheet {
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext();
|
||||
const enrich = (content) => foundry.applications.ux.TextEditor.implementation.enrichHTML(content ?? "", { async: true });
|
||||
const props = this.document.system.properties;
|
||||
context.prop1DescriptionHTML = await enrich(props.prop1.description);
|
||||
context.prop2DescriptionHTML = await enrich(props.prop2.description);
|
||||
context.prop3DescriptionHTML = await enrich(props.prop3.description);
|
||||
context.propFields = this.document.system.schema.fields.properties.fields;
|
||||
const props = this.document.system.properties ?? {};
|
||||
context.prop1DescriptionHTML = await enrich(props.prop1?.description);
|
||||
context.prop2DescriptionHTML = await enrich(props.prop2?.description);
|
||||
context.prop3DescriptionHTML = await enrich(props.prop3?.description);
|
||||
context.propFields = this.document.system.schema.fields.properties?.fields;
|
||||
return context;
|
||||
}
|
||||
};
|
||||
@@ -2673,7 +2850,7 @@ var CDETinjiApp = class _CDETinjiApp extends foundry.applications.api.Handlebars
|
||||
return;
|
||||
}
|
||||
await setTinjiValue(current - 1);
|
||||
ChatMessage.create({
|
||||
await ChatMessage.create({
|
||||
user: game.user.id,
|
||||
content: `<div class="cde-tinji-spend-msg">
|
||||
<i class="fas fa-star"></i>
|
||||
@@ -2692,7 +2869,7 @@ var CDECombat = class extends Combat {
|
||||
* for each selected combatant, then sync the result to the Combatant document.
|
||||
*/
|
||||
async rollInitiative(ids, options = {}) {
|
||||
const combatantIds = typeof ids === "string" ? [ids] : ids;
|
||||
const combatantIds = ids ? typeof ids === "string" ? [ids] : ids : this.combatants.map((c) => c.id);
|
||||
for (const id of combatantIds) {
|
||||
const combatant = this.combatants.get(id);
|
||||
if (!combatant) continue;
|
||||
@@ -2994,7 +3171,7 @@ async function _drawFromLoksyu(message, aspect, type, aspectLabel) {
|
||||
}
|
||||
const remain = entry.yin + entry.yang;
|
||||
const typeLabel = type === "success" ? game.i18n.localize("CDE.Successes") : game.i18n.localize("CDE.AuspiciousDie");
|
||||
ChatMessage.create({
|
||||
await ChatMessage.create({
|
||||
user: game.user.id,
|
||||
content: `<div class="cde-loksyu-draw-msg">
|
||||
<div class="cde-loksyu-draw-header">
|
||||
@@ -3020,7 +3197,7 @@ async function _spendTinjiPostRoll() {
|
||||
return;
|
||||
}
|
||||
await setTinjiValue(current - 1);
|
||||
ChatMessage.create({
|
||||
await ChatMessage.create({
|
||||
user: game.user.id,
|
||||
content: `<div class="cde-tinji-spend-msg">
|
||||
<span class="cde-tinji-icon">\u5929</span>
|
||||
@@ -3086,7 +3263,14 @@ function injectWelcomeActions(_message, html) {
|
||||
// src/system.js
|
||||
Hooks.once("i18nInit", preLocalizeConfig);
|
||||
Hooks.once("init", async () => {
|
||||
console.info(`CHRONIQUESDELETRANGE | Initializing ${SYSTEM_ID}`);
|
||||
console.log(
|
||||
"%c\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n%c\u2551 Chroniques de l'\xC9trange \u2014 FoundryVTT \u2551\n%c\u2551 Syst\xE8me de jeu par Antre-Monde \xC9ditions \u2551\n%c\u2551 Made by Uberwald - https://www.ubwerwald.me \u2551\n%c\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D",
|
||||
"color: #d4af37; font-weight: bold;",
|
||||
"color: #e2e8f4;",
|
||||
"color: #7d94b8;",
|
||||
"color: #5a7a9a;",
|
||||
"color: #d4af37; font-weight: bold;"
|
||||
);
|
||||
registerSettings();
|
||||
game.system.CONST = { MAGICS, SUBTYPES };
|
||||
game.cde = { CDELoksyuApp, CDETinjiApp, CDEWheelApp };
|
||||
|
||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
@@ -34,6 +34,7 @@
|
||||
"CDE.HeiSpend": "Dépense HEI",
|
||||
"CDE.SpellBonus": "Bonus Sort",
|
||||
"CDE.SpellPower": "Puissance du Sort",
|
||||
"CDE.BonusMalus": "Bonus/Malus",
|
||||
"CDE.Boss": "Boss",
|
||||
"CDE.Cancel": "Annuler",
|
||||
"CDE.CancelChanges": "Annuler les modifications",
|
||||
@@ -81,6 +82,7 @@
|
||||
"CDE.EarthlyPrayer": "Prière Terrestre",
|
||||
"CDE.Effects": "Effets",
|
||||
"CDE.Elixirs": "Élixirs",
|
||||
"CDE.EnablePrompt": "Toujours demander avant de lancer",
|
||||
"CDE.Error0": "Impossible de poursuivre : le nombre total de vos dés à lancer est inférieur à 1.",
|
||||
"CDE.Error1": "Impossible de poursuivre : vous ne possédez pas cette Compétence.",
|
||||
"CDE.Error10": "Impossible de poursuivre : vous avez 0 ou moins dans cet Aspect.",
|
||||
@@ -148,6 +150,11 @@
|
||||
"CDE.MigrationPartialError": "{count} personnage(s) n'ont pas pu être importés.",
|
||||
"CDE.MigrationErrorNotJson": "Le fichier « {file} » n'est pas un fichier JSON.",
|
||||
"CDE.MigrationErrorParse": "Erreur lors de la lecture de « {file} » : {error}",
|
||||
"CDE.MigrationConfirmAction": "Confirmer l'importation",
|
||||
"CDE.MigrationDuplicate": "Ce nom existe déjà dans le monde",
|
||||
"CDE.MigrationDuplicateCount": "{count} personnage(s) existent déjà dans le monde",
|
||||
"CDE.MigrationImportConfirm": "Vous allez importer {count} personnage(s). Confirmez-vous ?",
|
||||
"CDE.MigrationImporting": "Importation en cours...",
|
||||
"CDE.InitiativeWheel": "Roue d'Initiative",
|
||||
"CDE.InitiativeWheelOpen": "Ouvrir la Roue d'Initiative",
|
||||
"CDE.InitiativeWheelHint": "Roue d'initiative – Les Chroniques de l'Étrange",
|
||||
@@ -199,6 +206,7 @@
|
||||
"CDE.MartialArts": "Arts Martiaux",
|
||||
"CDE.Masterized": "Vous maîtrisez cette Technique",
|
||||
"CDE.MasteryOfTheWay": "Maîtrise de la Voie",
|
||||
"CDE.Material": "Matériau",
|
||||
"CDE.Max": "Max",
|
||||
"CDE.Max-Present-Malus-Present-Max": "Max ● Actuel ● Malus ● Actuel ● Max",
|
||||
"CDE.Max-Present-Present-Max": "Max ● Actuel ● Actuel ● Max",
|
||||
@@ -217,8 +225,11 @@
|
||||
"CDE.MsgMagic2": "s'élève à ",
|
||||
"CDE.MsgMagic3": ". La puissance à invoquer est de ",
|
||||
"CDE.MsgMagic4": ", si toutefois le sort est lancé avec succès.",
|
||||
"CDE.MoveUp": "Monter",
|
||||
"CDE.MoveDown": "Descendre",
|
||||
"CDE.NPCName": "Nom du PNJ",
|
||||
"CDE.FatSi": "Fat Si",
|
||||
"CDE.FreePowerLevels": "Niveaux de puissance gratuits",
|
||||
"CDE.PNJ": "PNJ",
|
||||
"CDE.Name": "Nom",
|
||||
"CDE.Necromancy": "Nécromancie",
|
||||
@@ -280,6 +291,7 @@
|
||||
"CDE.ResourceValue": "Valeur",
|
||||
"CDE.Resources": "Ressources",
|
||||
"CDE.Results": "Résultats :",
|
||||
"CDE.Roll": "Jet",
|
||||
"CDE.RollDifficulty": "Difficulté du Jet",
|
||||
"CDE.SAN-ZING": "SAN ● ZING",
|
||||
"CDE.Sanhei": "Sanhei",
|
||||
@@ -321,6 +333,7 @@
|
||||
"CDE.Technique": "Technique",
|
||||
"CDE.Technologies": "Technologies",
|
||||
"CDE.Threat": "Niveau de Menace",
|
||||
"CDE.ThrowType": "Type de jet",
|
||||
"CDE.TinJi": "Tin Ji :",
|
||||
"CDE.TinJi2": "Tin Ji",
|
||||
"CDE.TinJiName": "Nom de la Tin Ji",
|
||||
|
||||
@@ -1 +1 @@
|
||||
MANIFEST-000032
|
||||
MANIFEST-000048
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-23:03:15.040398 7ff7d67ee6c0 Recovering log #30
|
||||
2026/06/09-23:03:15.049230 7ff7d67ee6c0 Delete type=3 #28
|
||||
2026/06/09-23:03:15.049250 7ff7d67ee6c0 Delete type=0 #30
|
||||
2026/06/09-23:04:39.160365 7ff7d4feb6c0 Level-0 table #35: started
|
||||
2026/06/09-23:04:39.160378 7ff7d4feb6c0 Level-0 table #35: 0 bytes OK
|
||||
2026/06/09-23:04:39.167186 7ff7d4feb6c0 Delete type=0 #33
|
||||
2026/06/09-23:04:39.173014 7ff7d4feb6c0 Manual compaction at level-0 from '!items!3aig6MWvZCRoWXPW' @ 72057594037927935 : 1 .. '!items!cXaQG1TBE0jzrbNt' @ 0 : 0; will stop at (end)
|
||||
2026/06/14-22:22:39.661219 7f29d6fef6c0 Recovering log #46
|
||||
2026/06/14-22:22:39.671056 7f29d6fef6c0 Delete type=3 #44
|
||||
2026/06/14-22:22:39.671114 7f29d6fef6c0 Delete type=0 #46
|
||||
2026/06/14-22:32:37.952133 7f29d4feb6c0 Level-0 table #51: started
|
||||
2026/06/14-22:32:37.952163 7f29d4feb6c0 Level-0 table #51: 0 bytes OK
|
||||
2026/06/14-22:32:37.958637 7f29d4feb6c0 Delete type=0 #49
|
||||
2026/06/14-22:32:37.965966 7f29d4feb6c0 Manual compaction at level-0 from '!items!3aig6MWvZCRoWXPW' @ 72057594037927935 : 1 .. '!items!cXaQG1TBE0jzrbNt' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-14:17:25.397390 7ff7d5fed6c0 Recovering log #25
|
||||
2026/06/09-14:17:25.407486 7ff7d5fed6c0 Delete type=3 #23
|
||||
2026/06/09-14:17:25.407509 7ff7d5fed6c0 Delete type=0 #25
|
||||
2026/06/09-14:18:14.027632 7ff7d4feb6c0 Level-0 table #31: started
|
||||
2026/06/09-14:18:14.027648 7ff7d4feb6c0 Level-0 table #31: 0 bytes OK
|
||||
2026/06/09-14:18:14.034363 7ff7d4feb6c0 Delete type=0 #29
|
||||
2026/06/09-14:18:14.046545 7ff7d4feb6c0 Manual compaction at level-0 from '!items!3aig6MWvZCRoWXPW' @ 72057594037927935 : 1 .. '!items!cXaQG1TBE0jzrbNt' @ 0 : 0; will stop at (end)
|
||||
2026/06/10-22:16:59.072626 7f2fceffd6c0 Recovering log #42
|
||||
2026/06/10-22:16:59.081861 7f2fceffd6c0 Delete type=3 #40
|
||||
2026/06/10-22:16:59.081884 7f2fceffd6c0 Delete type=0 #42
|
||||
2026/06/10-22:17:30.144147 7f2fce7fc6c0 Level-0 table #47: started
|
||||
2026/06/10-22:17:30.144159 7f2fce7fc6c0 Level-0 table #47: 0 bytes OK
|
||||
2026/06/10-22:17:30.150289 7f2fce7fc6c0 Delete type=0 #45
|
||||
2026/06/10-22:17:30.156728 7f2fce7fc6c0 Manual compaction at level-0 from '!items!3aig6MWvZCRoWXPW' @ 72057594037927935 : 1 .. '!items!cXaQG1TBE0jzrbNt' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000032
|
||||
MANIFEST-000048
|
||||
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
2026/06/09-23:03:15.103926 7ff7d6fef6c0 Recovering log #30
|
||||
2026/06/09-23:03:15.112824 7ff7d6fef6c0 Delete type=3 #28
|
||||
2026/06/09-23:03:15.112841 7ff7d6fef6c0 Delete type=0 #30
|
||||
2026/06/09-23:04:39.173059 7ff7d4feb6c0 Level-0 table #35: started
|
||||
2026/06/09-23:04:39.173076 7ff7d4feb6c0 Level-0 table #35: 0 bytes OK
|
||||
2026/06/09-23:04:39.178896 7ff7d4feb6c0 Delete type=0 #33
|
||||
2026/06/09-23:04:39.197694 7ff7d4feb6c0 Manual compaction at level-0 from '!journal!CDEGuideMain0001' @ 72057594037927935 : 1 .. '!journal.pages!CDEGuideMain0001.wgqIHHVlO9miegn1' @ 0 : 0; will stop at (end)
|
||||
2026/06/14-22:22:39.748395 7f29d6fef6c0 Recovering log #46
|
||||
2026/06/14-22:22:39.759263 7f29d6fef6c0 Delete type=3 #44
|
||||
2026/06/14-22:22:39.759326 7f29d6fef6c0 Delete type=0 #46
|
||||
2026/06/14-22:32:38.022572 7f29d4feb6c0 Level-0 table #51: started
|
||||
2026/06/14-22:32:38.022623 7f29d4feb6c0 Level-0 table #51: 0 bytes OK
|
||||
2026/06/14-22:32:38.028952 7f29d4feb6c0 Delete type=0 #49
|
||||
2026/06/14-22:32:38.054477 7f29d4feb6c0 Manual compaction at level-0 from '!journal!CDEGuideMain0001' @ 72057594037927935 : 1 .. '!journal.pages!CDEGuideMain0001.wgqIHHVlO9miegn1' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-14:17:25.462325 7ff7d5fed6c0 Recovering log #25
|
||||
2026/06/09-14:17:25.472781 7ff7d5fed6c0 Delete type=3 #23
|
||||
2026/06/09-14:17:25.472805 7ff7d5fed6c0 Delete type=0 #25
|
||||
2026/06/09-14:18:14.058523 7ff7d4feb6c0 Level-0 table #31: started
|
||||
2026/06/09-14:18:14.058534 7ff7d4feb6c0 Level-0 table #31: 0 bytes OK
|
||||
2026/06/09-14:18:14.065661 7ff7d4feb6c0 Delete type=0 #29
|
||||
2026/06/09-14:18:14.071686 7ff7d4feb6c0 Manual compaction at level-0 from '!journal!CDEGuideMain0001' @ 72057594037927935 : 1 .. '!journal.pages!CDEGuideMain0001.wgqIHHVlO9miegn1' @ 0 : 0; will stop at (end)
|
||||
2026/06/10-22:16:59.141528 7f2fceffd6c0 Recovering log #42
|
||||
2026/06/10-22:16:59.150670 7f2fceffd6c0 Delete type=3 #40
|
||||
2026/06/10-22:16:59.150697 7f2fceffd6c0 Delete type=0 #42
|
||||
2026/06/10-22:17:30.188270 7f2fce7fc6c0 Level-0 table #47: started
|
||||
2026/06/10-22:17:30.188284 7f2fce7fc6c0 Level-0 table #47: 0 bytes OK
|
||||
2026/06/10-22:17:30.194047 7f2fce7fc6c0 Delete type=0 #45
|
||||
2026/06/10-22:17:30.206835 7f2fce7fc6c0 Manual compaction at level-0 from '!journal!CDEGuideMain0001' @ 72057594037927935 : 1 .. '!journal.pages!CDEGuideMain0001.wgqIHHVlO9miegn1' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000032
|
||||
MANIFEST-000048
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-23:03:15.061218 7ff7d67ee6c0 Recovering log #30
|
||||
2026/06/09-23:03:15.070526 7ff7d67ee6c0 Delete type=3 #28
|
||||
2026/06/09-23:03:15.070546 7ff7d67ee6c0 Delete type=0 #30
|
||||
2026/06/09-23:04:39.154224 7ff7d4feb6c0 Level-0 table #35: started
|
||||
2026/06/09-23:04:39.154234 7ff7d4feb6c0 Level-0 table #35: 0 bytes OK
|
||||
2026/06/09-23:04:39.160305 7ff7d4feb6c0 Delete type=0 #33
|
||||
2026/06/09-23:04:39.173009 7ff7d4feb6c0 Manual compaction at level-0 from '!items!0NDBw1YB54q3hLH0' @ 72057594037927935 : 1 .. '!items!ykekdZlirabRobEF' @ 0 : 0; will stop at (end)
|
||||
2026/06/14-22:22:39.688631 7f29d6fef6c0 Recovering log #46
|
||||
2026/06/14-22:22:39.699291 7f29d6fef6c0 Delete type=3 #44
|
||||
2026/06/14-22:22:39.699355 7f29d6fef6c0 Delete type=0 #46
|
||||
2026/06/14-22:32:37.979476 7f29d4feb6c0 Level-0 table #51: started
|
||||
2026/06/14-22:32:37.979507 7f29d4feb6c0 Level-0 table #51: 0 bytes OK
|
||||
2026/06/14-22:32:37.985981 7f29d4feb6c0 Delete type=0 #49
|
||||
2026/06/14-22:32:37.994186 7f29d4feb6c0 Manual compaction at level-0 from '!items!0NDBw1YB54q3hLH0' @ 72057594037927935 : 1 .. '!items!ykekdZlirabRobEF' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-14:17:25.419369 7ff7d6fef6c0 Recovering log #25
|
||||
2026/06/09-14:17:25.428427 7ff7d6fef6c0 Delete type=3 #23
|
||||
2026/06/09-14:17:25.428447 7ff7d6fef6c0 Delete type=0 #25
|
||||
2026/06/09-14:18:14.040287 7ff7d4feb6c0 Level-0 table #31: started
|
||||
2026/06/09-14:18:14.040298 7ff7d4feb6c0 Level-0 table #31: 0 bytes OK
|
||||
2026/06/09-14:18:14.046472 7ff7d4feb6c0 Delete type=0 #29
|
||||
2026/06/09-14:18:14.046553 7ff7d4feb6c0 Manual compaction at level-0 from '!items!0NDBw1YB54q3hLH0' @ 72057594037927935 : 1 .. '!items!ykekdZlirabRobEF' @ 0 : 0; will stop at (end)
|
||||
2026/06/10-22:16:59.094638 7f301cbff6c0 Recovering log #42
|
||||
2026/06/10-22:16:59.105309 7f301cbff6c0 Delete type=3 #40
|
||||
2026/06/10-22:16:59.105334 7f301cbff6c0 Delete type=0 #42
|
||||
2026/06/10-22:17:30.162703 7f2fce7fc6c0 Level-0 table #47: started
|
||||
2026/06/10-22:17:30.162714 7f2fce7fc6c0 Level-0 table #47: 0 bytes OK
|
||||
2026/06/10-22:17:30.168944 7f2fce7fc6c0 Delete type=0 #45
|
||||
2026/06/10-22:17:30.181202 7f2fce7fc6c0 Manual compaction at level-0 from '!items!0NDBw1YB54q3hLH0' @ 72057594037927935 : 1 .. '!items!ykekdZlirabRobEF' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000032
|
||||
MANIFEST-000048
|
||||
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
2026/06/09-23:03:15.071667 7ff7d57ec6c0 Recovering log #30
|
||||
2026/06/09-23:03:15.080691 7ff7d57ec6c0 Delete type=3 #28
|
||||
2026/06/09-23:03:15.080714 7ff7d57ec6c0 Delete type=0 #30
|
||||
2026/06/09-23:04:39.167245 7ff7d4feb6c0 Level-0 table #35: started
|
||||
2026/06/09-23:04:39.167259 7ff7d4feb6c0 Level-0 table #35: 0 bytes OK
|
||||
2026/06/09-23:04:39.172955 7ff7d4feb6c0 Delete type=0 #33
|
||||
2026/06/09-23:04:39.173017 7ff7d4feb6c0 Manual compaction at level-0 from '!items!HKq5ANSGiBIdcnki' @ 72057594037927935 : 1 .. '!items!HKq5ANSGiBIdcnki' @ 0 : 0; will stop at (end)
|
||||
2026/06/14-22:22:39.702477 7f29d5fed6c0 Recovering log #46
|
||||
2026/06/14-22:22:39.712938 7f29d5fed6c0 Delete type=3 #44
|
||||
2026/06/14-22:22:39.712993 7f29d5fed6c0 Delete type=0 #46
|
||||
2026/06/14-22:32:37.986092 7f29d4feb6c0 Level-0 table #51: started
|
||||
2026/06/14-22:32:37.986120 7f29d4feb6c0 Level-0 table #51: 0 bytes OK
|
||||
2026/06/14-22:32:37.994045 7f29d4feb6c0 Delete type=0 #49
|
||||
2026/06/14-22:32:37.994361 7f29d4feb6c0 Manual compaction at level-0 from '!items!HKq5ANSGiBIdcnki' @ 72057594037927935 : 1 .. '!items!HKq5ANSGiBIdcnki' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-14:17:25.429438 7ff7d67ee6c0 Recovering log #25
|
||||
2026/06/09-14:17:25.439353 7ff7d67ee6c0 Delete type=3 #23
|
||||
2026/06/09-14:17:25.439378 7ff7d67ee6c0 Delete type=0 #25
|
||||
2026/06/09-14:18:14.021756 7ff7d4feb6c0 Level-0 table #31: started
|
||||
2026/06/09-14:18:14.021767 7ff7d4feb6c0 Level-0 table #31: 0 bytes OK
|
||||
2026/06/09-14:18:14.027556 7ff7d4feb6c0 Delete type=0 #29
|
||||
2026/06/09-14:18:14.046539 7ff7d4feb6c0 Manual compaction at level-0 from '!items!HKq5ANSGiBIdcnki' @ 72057594037927935 : 1 .. '!items!HKq5ANSGiBIdcnki' @ 0 : 0; will stop at (end)
|
||||
2026/06/10-22:16:59.106484 7f2fcf7fe6c0 Recovering log #42
|
||||
2026/06/10-22:16:59.115923 7f2fcf7fe6c0 Delete type=3 #40
|
||||
2026/06/10-22:16:59.115950 7f2fcf7fe6c0 Delete type=0 #42
|
||||
2026/06/10-22:17:30.174912 7f2fce7fc6c0 Level-0 table #47: started
|
||||
2026/06/10-22:17:30.174926 7f2fce7fc6c0 Level-0 table #47: 0 bytes OK
|
||||
2026/06/10-22:17:30.181136 7f2fce7fc6c0 Delete type=0 #45
|
||||
2026/06/10-22:17:30.181212 7f2fce7fc6c0 Manual compaction at level-0 from '!items!HKq5ANSGiBIdcnki' @ 72057594037927935 : 1 .. '!items!HKq5ANSGiBIdcnki' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000032
|
||||
MANIFEST-000048
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-23:03:14.997184 7ff7d5fed6c0 Recovering log #30
|
||||
2026/06/09-23:03:15.006667 7ff7d5fed6c0 Delete type=3 #28
|
||||
2026/06/09-23:03:15.006688 7ff7d5fed6c0 Delete type=0 #30
|
||||
2026/06/09-23:04:39.135859 7ff7d4feb6c0 Level-0 table #35: started
|
||||
2026/06/09-23:04:39.135872 7ff7d4feb6c0 Level-0 table #35: 0 bytes OK
|
||||
2026/06/09-23:04:39.142395 7ff7d4feb6c0 Delete type=0 #33
|
||||
2026/06/09-23:04:39.148225 7ff7d4feb6c0 Manual compaction at level-0 from '!items!2nKXEHLG0fXtSOdy' @ 72057594037927935 : 1 .. '!items!tlIc1bmIAbQeUwj7' @ 0 : 0; will stop at (end)
|
||||
2026/06/14-22:22:39.603745 7f29d67ee6c0 Recovering log #46
|
||||
2026/06/14-22:22:39.614957 7f29d67ee6c0 Delete type=3 #44
|
||||
2026/06/14-22:22:39.615010 7f29d67ee6c0 Delete type=0 #46
|
||||
2026/06/14-22:32:37.939036 7f29d4feb6c0 Level-0 table #51: started
|
||||
2026/06/14-22:32:37.939102 7f29d4feb6c0 Level-0 table #51: 0 bytes OK
|
||||
2026/06/14-22:32:37.945655 7f29d4feb6c0 Delete type=0 #49
|
||||
2026/06/14-22:32:37.965934 7f29d4feb6c0 Manual compaction at level-0 from '!items!2nKXEHLG0fXtSOdy' @ 72057594037927935 : 1 .. '!items!tlIc1bmIAbQeUwj7' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-14:17:25.355145 7ff7d5fed6c0 Recovering log #25
|
||||
2026/06/09-14:17:25.364080 7ff7d5fed6c0 Delete type=3 #23
|
||||
2026/06/09-14:17:25.364100 7ff7d5fed6c0 Delete type=0 #25
|
||||
2026/06/09-14:18:14.002973 7ff7d4feb6c0 Level-0 table #31: started
|
||||
2026/06/09-14:18:14.002982 7ff7d4feb6c0 Level-0 table #31: 0 bytes OK
|
||||
2026/06/09-14:18:14.008712 7ff7d4feb6c0 Delete type=0 #29
|
||||
2026/06/09-14:18:14.021671 7ff7d4feb6c0 Manual compaction at level-0 from '!items!2nKXEHLG0fXtSOdy' @ 72057594037927935 : 1 .. '!items!tlIc1bmIAbQeUwj7' @ 0 : 0; will stop at (end)
|
||||
2026/06/10-22:16:59.023554 7f2fcffff6c0 Recovering log #42
|
||||
2026/06/10-22:16:59.033543 7f2fcffff6c0 Delete type=3 #40
|
||||
2026/06/10-22:16:59.033571 7f2fcffff6c0 Delete type=0 #42
|
||||
2026/06/10-22:17:30.131435 7f2fce7fc6c0 Level-0 table #47: started
|
||||
2026/06/10-22:17:30.131469 7f2fce7fc6c0 Level-0 table #47: 0 bytes OK
|
||||
2026/06/10-22:17:30.138026 7f2fce7fc6c0 Delete type=0 #45
|
||||
2026/06/10-22:17:30.156715 7f2fce7fc6c0 Manual compaction at level-0 from '!items!2nKXEHLG0fXtSOdy' @ 72057594037927935 : 1 .. '!items!tlIc1bmIAbQeUwj7' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000032
|
||||
MANIFEST-000048
|
||||
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
2026/06/09-23:03:15.081631 7ff7d67ee6c0 Recovering log #30
|
||||
2026/06/09-23:03:15.091455 7ff7d67ee6c0 Delete type=3 #28
|
||||
2026/06/09-23:03:15.091476 7ff7d67ee6c0 Delete type=0 #30
|
||||
2026/06/09-23:04:39.178964 7ff7d4feb6c0 Level-0 table #35: started
|
||||
2026/06/09-23:04:39.178977 7ff7d4feb6c0 Level-0 table #35: 0 bytes OK
|
||||
2026/06/09-23:04:39.185830 7ff7d4feb6c0 Delete type=0 #33
|
||||
2026/06/09-23:04:39.197701 7ff7d4feb6c0 Manual compaction at level-0 from '!actors!4ZjFZ1HoJV9mJStt' @ 72057594037927935 : 1 .. '!actors!zVpmacwoWEG8YTCQ' @ 0 : 0; will stop at (end)
|
||||
2026/06/14-22:22:39.716564 7f29d6fef6c0 Recovering log #46
|
||||
2026/06/14-22:22:39.726981 7f29d6fef6c0 Delete type=3 #44
|
||||
2026/06/14-22:22:39.727264 7f29d6fef6c0 Delete type=0 #46
|
||||
2026/06/14-22:32:37.994382 7f29d4feb6c0 Level-0 table #51: started
|
||||
2026/06/14-22:32:37.994411 7f29d4feb6c0 Level-0 table #51: 0 bytes OK
|
||||
2026/06/14-22:32:38.000939 7f29d4feb6c0 Delete type=0 #49
|
||||
2026/06/14-22:32:38.022274 7f29d4feb6c0 Manual compaction at level-0 from '!actors!4ZjFZ1HoJV9mJStt' @ 72057594037927935 : 1 .. '!actors!zVpmacwoWEG8YTCQ' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-14:17:25.440402 7ff7d5fed6c0 Recovering log #25
|
||||
2026/06/09-14:17:25.450255 7ff7d5fed6c0 Delete type=3 #23
|
||||
2026/06/09-14:17:25.450286 7ff7d5fed6c0 Delete type=0 #25
|
||||
2026/06/09-14:18:14.046641 7ff7d4feb6c0 Level-0 table #31: started
|
||||
2026/06/09-14:18:14.046651 7ff7d4feb6c0 Level-0 table #31: 0 bytes OK
|
||||
2026/06/09-14:18:14.052649 7ff7d4feb6c0 Delete type=0 #29
|
||||
2026/06/09-14:18:14.071674 7ff7d4feb6c0 Manual compaction at level-0 from '!actors!4ZjFZ1HoJV9mJStt' @ 72057594037927935 : 1 .. '!actors!zVpmacwoWEG8YTCQ' @ 0 : 0; will stop at (end)
|
||||
2026/06/10-22:16:59.117278 7f2fceffd6c0 Recovering log #42
|
||||
2026/06/10-22:16:59.126816 7f2fceffd6c0 Delete type=3 #40
|
||||
2026/06/10-22:16:59.126846 7f2fceffd6c0 Delete type=0 #42
|
||||
2026/06/10-22:17:30.168999 7f2fce7fc6c0 Level-0 table #47: started
|
||||
2026/06/10-22:17:30.169011 7f2fce7fc6c0 Level-0 table #47: 0 bytes OK
|
||||
2026/06/10-22:17:30.174853 7f2fce7fc6c0 Delete type=0 #45
|
||||
2026/06/10-22:17:30.181208 7f2fce7fc6c0 Manual compaction at level-0 from '!actors!4ZjFZ1HoJV9mJStt' @ 72057594037927935 : 1 .. '!actors!zVpmacwoWEG8YTCQ' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000010
|
||||
MANIFEST-000026
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2026/06/09-23:03:15.092892 7ff7d6fef6c0 Recovering log #8
|
||||
2026/06/09-23:03:15.102087 7ff7d6fef6c0 Delete type=3 #6
|
||||
2026/06/09-23:03:15.102101 7ff7d6fef6c0 Delete type=0 #8
|
||||
2026/06/09-23:04:39.185891 7ff7d4feb6c0 Level-0 table #13: started
|
||||
2026/06/09-23:04:39.185906 7ff7d4feb6c0 Level-0 table #13: 0 bytes OK
|
||||
2026/06/09-23:04:39.191585 7ff7d4feb6c0 Delete type=0 #11
|
||||
2026/06/09-23:04:39.197705 7ff7d4feb6c0 Manual compaction at level-0 from '!actors!5OGW1fRUn12aNMMV' @ 72057594037927935 : 1 .. '!actors.items!zSWwOmFiFjN4YxC9.w8LXSYQ1eIygtlKV' @ 0 : 0; will stop at (end)
|
||||
2026/06/09-23:04:39.197713 7ff7d4feb6c0 Manual compaction at level-1 from '!actors!5OGW1fRUn12aNMMV' @ 72057594037927935 : 1 .. '!actors.items!zSWwOmFiFjN4YxC9.w8LXSYQ1eIygtlKV' @ 0 : 0; will stop at (end)
|
||||
2026/06/14-22:22:39.731841 7f29d6fef6c0 Recovering log #24
|
||||
2026/06/14-22:22:39.741957 7f29d6fef6c0 Delete type=3 #22
|
||||
2026/06/14-22:22:39.742028 7f29d6fef6c0 Delete type=0 #24
|
||||
2026/06/14-22:32:38.007843 7f29d4feb6c0 Level-0 table #29: started
|
||||
2026/06/14-22:32:38.007886 7f29d4feb6c0 Level-0 table #29: 0 bytes OK
|
||||
2026/06/14-22:32:38.014714 7f29d4feb6c0 Delete type=0 #27
|
||||
2026/06/14-22:32:38.022308 7f29d4feb6c0 Manual compaction at level-0 from '!actors!5OGW1fRUn12aNMMV' @ 72057594037927935 : 1 .. '!actors.items!zSWwOmFiFjN4YxC9.w8LXSYQ1eIygtlKV' @ 0 : 0; will stop at (end)
|
||||
2026/06/14-22:32:38.022452 7f29d4feb6c0 Manual compaction at level-1 from '!actors!5OGW1fRUn12aNMMV' @ 72057594037927935 : 1 .. '!actors.items!zSWwOmFiFjN4YxC9.w8LXSYQ1eIygtlKV' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
2026/06/09-14:17:25.451270 7ff7d5fed6c0 Recovering log #4
|
||||
2026/06/09-14:17:25.460590 7ff7d5fed6c0 Delete type=3 #2
|
||||
2026/06/09-14:17:25.460605 7ff7d5fed6c0 Delete type=0 #4
|
||||
2026/06/09-14:18:14.052676 7ff7d4feb6c0 Level-0 table #9: started
|
||||
2026/06/09-14:18:14.052683 7ff7d4feb6c0 Level-0 table #9: 0 bytes OK
|
||||
2026/06/09-14:18:14.058481 7ff7d4feb6c0 Delete type=0 #7
|
||||
2026/06/09-14:18:14.071681 7ff7d4feb6c0 Manual compaction at level-0 from '!actors!5OGW1fRUn12aNMMV' @ 72057594037927935 : 1 .. '!actors.items!zSWwOmFiFjN4YxC9.w8LXSYQ1eIygtlKV' @ 0 : 0; will stop at (end)
|
||||
2026/06/09-14:18:14.071693 7ff7d4feb6c0 Manual compaction at level-1 from '!actors!5OGW1fRUn12aNMMV' @ 72057594037927935 : 1 .. '!actors.items!zSWwOmFiFjN4YxC9.w8LXSYQ1eIygtlKV' @ 0 : 0; will stop at (end)
|
||||
2026/06/10-22:16:59.128431 7f2fceffd6c0 Recovering log #20
|
||||
2026/06/10-22:16:59.138004 7f2fceffd6c0 Delete type=3 #18
|
||||
2026/06/10-22:16:59.138034 7f2fceffd6c0 Delete type=0 #20
|
||||
2026/06/10-22:17:30.194124 7f2fce7fc6c0 Level-0 table #25: started
|
||||
2026/06/10-22:17:30.194157 7f2fce7fc6c0 Level-0 table #25: 0 bytes OK
|
||||
2026/06/10-22:17:30.200786 7f2fce7fc6c0 Delete type=0 #23
|
||||
2026/06/10-22:17:30.206841 7f2fce7fc6c0 Manual compaction at level-0 from '!actors!5OGW1fRUn12aNMMV' @ 72057594037927935 : 1 .. '!actors.items!zSWwOmFiFjN4YxC9.w8LXSYQ1eIygtlKV' @ 0 : 0; will stop at (end)
|
||||
2026/06/10-22:17:30.206854 7f2fce7fc6c0 Manual compaction at level-1 from '!actors!5OGW1fRUn12aNMMV' @ 72057594037927935 : 1 .. '!actors.items!zSWwOmFiFjN4YxC9.w8LXSYQ1eIygtlKV' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000032
|
||||
MANIFEST-000048
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-23:03:15.050263 7ff7d57ec6c0 Recovering log #30
|
||||
2026/06/09-23:03:15.060149 7ff7d57ec6c0 Delete type=3 #28
|
||||
2026/06/09-23:03:15.060171 7ff7d57ec6c0 Delete type=0 #30
|
||||
2026/06/09-23:04:39.148277 7ff7d4feb6c0 Level-0 table #35: started
|
||||
2026/06/09-23:04:39.148301 7ff7d4feb6c0 Level-0 table #35: 0 bytes OK
|
||||
2026/06/09-23:04:39.154194 7ff7d4feb6c0 Delete type=0 #33
|
||||
2026/06/09-23:04:39.173001 7ff7d4feb6c0 Manual compaction at level-0 from '!items!DC2kimCi9sWxqhXG' @ 72057594037927935 : 1 .. '!items!qzfAEhmvVxEMzm0k' @ 0 : 0; will stop at (end)
|
||||
2026/06/14-22:22:39.674682 7f29d5fed6c0 Recovering log #46
|
||||
2026/06/14-22:22:39.685769 7f29d5fed6c0 Delete type=3 #44
|
||||
2026/06/14-22:22:39.685821 7f29d5fed6c0 Delete type=0 #46
|
||||
2026/06/14-22:32:37.972754 7f29d4feb6c0 Level-0 table #51: started
|
||||
2026/06/14-22:32:37.972783 7f29d4feb6c0 Level-0 table #51: 0 bytes OK
|
||||
2026/06/14-22:32:37.979353 7f29d4feb6c0 Delete type=0 #49
|
||||
2026/06/14-22:32:37.994176 7f29d4feb6c0 Manual compaction at level-0 from '!items!DC2kimCi9sWxqhXG' @ 72057594037927935 : 1 .. '!items!qzfAEhmvVxEMzm0k' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-14:17:25.408481 7ff7d57ec6c0 Recovering log #25
|
||||
2026/06/09-14:17:25.418586 7ff7d57ec6c0 Delete type=3 #23
|
||||
2026/06/09-14:17:25.418602 7ff7d57ec6c0 Delete type=0 #25
|
||||
2026/06/09-14:18:14.034422 7ff7d4feb6c0 Level-0 table #31: started
|
||||
2026/06/09-14:18:14.034431 7ff7d4feb6c0 Level-0 table #31: 0 bytes OK
|
||||
2026/06/09-14:18:14.040246 7ff7d4feb6c0 Delete type=0 #29
|
||||
2026/06/09-14:18:14.046549 7ff7d4feb6c0 Manual compaction at level-0 from '!items!DC2kimCi9sWxqhXG' @ 72057594037927935 : 1 .. '!items!qzfAEhmvVxEMzm0k' @ 0 : 0; will stop at (end)
|
||||
2026/06/10-22:16:59.083173 7f2fcffff6c0 Recovering log #42
|
||||
2026/06/10-22:16:59.093107 7f2fcffff6c0 Delete type=3 #40
|
||||
2026/06/10-22:16:59.093136 7f2fcffff6c0 Delete type=0 #42
|
||||
2026/06/10-22:17:30.206915 7f2fce7fc6c0 Level-0 table #47: started
|
||||
2026/06/10-22:17:30.206925 7f2fce7fc6c0 Level-0 table #47: 0 bytes OK
|
||||
2026/06/10-22:17:30.212983 7f2fce7fc6c0 Delete type=0 #45
|
||||
2026/06/10-22:17:30.225529 7f2fce7fc6c0 Manual compaction at level-0 from '!items!DC2kimCi9sWxqhXG' @ 72057594037927935 : 1 .. '!items!qzfAEhmvVxEMzm0k' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000051
|
||||
MANIFEST-000067
|
||||
|
||||
+14
-7
@@ -1,7 +1,14 @@
|
||||
2026/06/09-23:03:15.114055 7ff7d57ec6c0 Recovering log #49
|
||||
2026/06/09-23:03:15.124263 7ff7d57ec6c0 Delete type=3 #47
|
||||
2026/06/09-23:03:15.124286 7ff7d57ec6c0 Delete type=0 #49
|
||||
2026/06/09-23:04:39.191632 7ff7d4feb6c0 Level-0 table #54: started
|
||||
2026/06/09-23:04:39.191645 7ff7d4feb6c0 Level-0 table #54: 0 bytes OK
|
||||
2026/06/09-23:04:39.197661 7ff7d4feb6c0 Delete type=0 #52
|
||||
2026/06/09-23:04:39.219495 7ff7d4feb6c0 Manual compaction at level-0 from '!scenes!2C6gyZpvPxWlsVZi' @ 72057594037927935 : 1 .. '!scenes.levels!olYe9bhuXwRWQ8j7.defaultLevel0000' @ 0 : 0; will stop at (end)
|
||||
2026/06/14-22:22:39.763440 7f29d67ee6c0 Recovering log #65
|
||||
2026/06/14-22:22:39.773982 7f29d67ee6c0 Delete type=3 #63
|
||||
2026/06/14-22:22:39.774029 7f29d67ee6c0 Delete type=0 #65
|
||||
2026/06/14-22:32:38.029088 7f29d4feb6c0 Level-0 table #70: started
|
||||
2026/06/14-22:32:38.032823 7f29d4feb6c0 Level-0 table #70: 3169 bytes OK
|
||||
2026/06/14-22:32:38.039619 7f29d4feb6c0 Delete type=0 #68
|
||||
2026/06/14-22:32:38.054502 7f29d4feb6c0 Manual compaction at level-0 from '!scenes!2C6gyZpvPxWlsVZi' @ 72057594037927935 : 1 .. '!scenes.levels!olYe9bhuXwRWQ8j7.defaultLevel0000' @ 0 : 0; will stop at '!scenes.levels!olYe9bhuXwRWQ8j7.defaultLevel0000' @ 29 : 1
|
||||
2026/06/14-22:32:38.054509 7f29d4feb6c0 Compacting 1@0 + 1@1 files
|
||||
2026/06/14-22:32:38.058254 7f29d4feb6c0 Generated table #71@0: 8 keys, 3169 bytes
|
||||
2026/06/14-22:32:38.058277 7f29d4feb6c0 Compacted 1@0 + 1@1 files => 3169 bytes
|
||||
2026/06/14-22:32:38.064919 7f29d4feb6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
|
||||
2026/06/14-22:32:38.065170 7f29d4feb6c0 Delete type=2 #46
|
||||
2026/06/14-22:32:38.065328 7f29d4feb6c0 Delete type=2 #70
|
||||
2026/06/14-22:32:38.072993 7f29d4feb6c0 Manual compaction at level-0 from '!scenes.levels!olYe9bhuXwRWQ8j7.defaultLevel0000' @ 29 : 1 .. '!scenes.levels!olYe9bhuXwRWQ8j7.defaultLevel0000' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-14:17:25.474281 7ff7d57ec6c0 Recovering log #44
|
||||
2026/06/09-14:17:25.483017 7ff7d57ec6c0 Delete type=3 #42
|
||||
2026/06/09-14:17:25.483037 7ff7d57ec6c0 Delete type=0 #44
|
||||
2026/06/09-14:18:14.065718 7ff7d4feb6c0 Level-0 table #50: started
|
||||
2026/06/09-14:18:14.065734 7ff7d4feb6c0 Level-0 table #50: 0 bytes OK
|
||||
2026/06/09-14:18:14.071596 7ff7d4feb6c0 Delete type=0 #48
|
||||
2026/06/09-14:18:14.071689 7ff7d4feb6c0 Manual compaction at level-0 from '!scenes!2C6gyZpvPxWlsVZi' @ 72057594037927935 : 1 .. '!scenes.levels!olYe9bhuXwRWQ8j7.defaultLevel0000' @ 0 : 0; will stop at (end)
|
||||
2026/06/10-22:16:59.152572 7f2fcffff6c0 Recovering log #61
|
||||
2026/06/10-22:16:59.162721 7f2fcffff6c0 Delete type=3 #59
|
||||
2026/06/10-22:16:59.162748 7f2fcffff6c0 Delete type=0 #61
|
||||
2026/06/10-22:17:30.213038 7f2fce7fc6c0 Level-0 table #66: started
|
||||
2026/06/10-22:17:30.213049 7f2fce7fc6c0 Level-0 table #66: 0 bytes OK
|
||||
2026/06/10-22:17:30.219379 7f2fce7fc6c0 Delete type=0 #64
|
||||
2026/06/10-22:17:30.234624 7f2fce7fc6c0 Manual compaction at level-0 from '!scenes!2C6gyZpvPxWlsVZi' @ 72057594037927935 : 1 .. '!scenes.levels!olYe9bhuXwRWQ8j7.defaultLevel0000' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000032
|
||||
MANIFEST-000048
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-23:03:15.007971 7ff7d5fed6c0 Recovering log #30
|
||||
2026/06/09-23:03:15.017257 7ff7d5fed6c0 Delete type=3 #28
|
||||
2026/06/09-23:03:15.017277 7ff7d5fed6c0 Delete type=0 #30
|
||||
2026/06/09-23:04:39.130034 7ff7d4feb6c0 Level-0 table #35: started
|
||||
2026/06/09-23:04:39.130046 7ff7d4feb6c0 Level-0 table #35: 0 bytes OK
|
||||
2026/06/09-23:04:39.135814 7ff7d4feb6c0 Delete type=0 #33
|
||||
2026/06/09-23:04:39.148218 7ff7d4feb6c0 Manual compaction at level-0 from '!items!2f51pcvFkcZjaxDk' @ 72057594037927935 : 1 .. '!items!yVN7PZw35iIaBl0H' @ 0 : 0; will stop at (end)
|
||||
2026/06/14-22:22:39.618536 7f29d57ec6c0 Recovering log #46
|
||||
2026/06/14-22:22:39.628785 7f29d57ec6c0 Delete type=3 #44
|
||||
2026/06/14-22:22:39.628834 7f29d57ec6c0 Delete type=0 #46
|
||||
2026/06/14-22:32:37.966108 7f29d4feb6c0 Level-0 table #51: started
|
||||
2026/06/14-22:32:37.966141 7f29d4feb6c0 Level-0 table #51: 0 bytes OK
|
||||
2026/06/14-22:32:37.972646 7f29d4feb6c0 Delete type=0 #49
|
||||
2026/06/14-22:32:37.994161 7f29d4feb6c0 Manual compaction at level-0 from '!items!2f51pcvFkcZjaxDk' @ 72057594037927935 : 1 .. '!items!yVN7PZw35iIaBl0H' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-14:17:25.365128 7ff7d67ee6c0 Recovering log #25
|
||||
2026/06/09-14:17:25.375651 7ff7d67ee6c0 Delete type=3 #23
|
||||
2026/06/09-14:17:25.375676 7ff7d67ee6c0 Delete type=0 #25
|
||||
2026/06/09-14:18:14.008762 7ff7d4feb6c0 Level-0 table #31: started
|
||||
2026/06/09-14:18:14.008772 7ff7d4feb6c0 Level-0 table #31: 0 bytes OK
|
||||
2026/06/09-14:18:14.014913 7ff7d4feb6c0 Delete type=0 #29
|
||||
2026/06/09-14:18:14.021676 7ff7d4feb6c0 Manual compaction at level-0 from '!items!2f51pcvFkcZjaxDk' @ 72057594037927935 : 1 .. '!items!yVN7PZw35iIaBl0H' @ 0 : 0; will stop at (end)
|
||||
2026/06/10-22:16:59.036129 7f301cbff6c0 Recovering log #42
|
||||
2026/06/10-22:16:59.045169 7f301cbff6c0 Delete type=3 #40
|
||||
2026/06/10-22:16:59.045189 7f301cbff6c0 Delete type=0 #42
|
||||
2026/06/10-22:17:30.138111 7f2fce7fc6c0 Level-0 table #47: started
|
||||
2026/06/10-22:17:30.138127 7f2fce7fc6c0 Level-0 table #47: 0 bytes OK
|
||||
2026/06/10-22:17:30.144090 7f2fce7fc6c0 Delete type=0 #45
|
||||
2026/06/10-22:17:30.156722 7f2fce7fc6c0 Manual compaction at level-0 from '!items!2f51pcvFkcZjaxDk' @ 72057594037927935 : 1 .. '!items!yVN7PZw35iIaBl0H' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000032
|
||||
MANIFEST-000048
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-23:03:15.018889 7ff7d57ec6c0 Recovering log #30
|
||||
2026/06/09-23:03:15.027808 7ff7d57ec6c0 Delete type=3 #28
|
||||
2026/06/09-23:03:15.027827 7ff7d57ec6c0 Delete type=0 #30
|
||||
2026/06/09-23:04:39.142437 7ff7d4feb6c0 Level-0 table #35: started
|
||||
2026/06/09-23:04:39.142454 7ff7d4feb6c0 Level-0 table #35: 0 bytes OK
|
||||
2026/06/09-23:04:39.148170 7ff7d4feb6c0 Delete type=0 #33
|
||||
2026/06/09-23:04:39.148230 7ff7d4feb6c0 Manual compaction at level-0 from '!items!APN91pQL0NBfZsG7' @ 72057594037927935 : 1 .. '!items!xxZKGqDVxAfr140W' @ 0 : 0; will stop at (end)
|
||||
2026/06/14-22:22:39.633149 7f29d6fef6c0 Recovering log #46
|
||||
2026/06/14-22:22:39.644445 7f29d6fef6c0 Delete type=3 #44
|
||||
2026/06/14-22:22:39.644504 7f29d6fef6c0 Delete type=0 #46
|
||||
2026/06/14-22:32:37.945805 7f29d4feb6c0 Level-0 table #51: started
|
||||
2026/06/14-22:32:37.945837 7f29d4feb6c0 Level-0 table #51: 0 bytes OK
|
||||
2026/06/14-22:32:37.952016 7f29d4feb6c0 Delete type=0 #49
|
||||
2026/06/14-22:32:37.965952 7f29d4feb6c0 Manual compaction at level-0 from '!items!APN91pQL0NBfZsG7' @ 72057594037927935 : 1 .. '!items!xxZKGqDVxAfr140W' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-14:17:25.377225 7ff7d6fef6c0 Recovering log #25
|
||||
2026/06/09-14:17:25.386451 7ff7d6fef6c0 Delete type=3 #23
|
||||
2026/06/09-14:17:25.386469 7ff7d6fef6c0 Delete type=0 #25
|
||||
2026/06/09-14:18:14.014965 7ff7d4feb6c0 Level-0 table #31: started
|
||||
2026/06/09-14:18:14.014978 7ff7d4feb6c0 Level-0 table #31: 0 bytes OK
|
||||
2026/06/09-14:18:14.021573 7ff7d4feb6c0 Delete type=0 #29
|
||||
2026/06/09-14:18:14.021680 7ff7d4feb6c0 Manual compaction at level-0 from '!items!APN91pQL0NBfZsG7' @ 72057594037927935 : 1 .. '!items!xxZKGqDVxAfr140W' @ 0 : 0; will stop at (end)
|
||||
2026/06/10-22:16:59.047090 7f2fceffd6c0 Recovering log #42
|
||||
2026/06/10-22:16:59.057530 7f2fceffd6c0 Delete type=3 #40
|
||||
2026/06/10-22:16:59.057556 7f2fceffd6c0 Delete type=0 #42
|
||||
2026/06/10-22:17:30.150367 7f2fce7fc6c0 Level-0 table #47: started
|
||||
2026/06/10-22:17:30.150382 7f2fce7fc6c0 Level-0 table #47: 0 bytes OK
|
||||
2026/06/10-22:17:30.156663 7f2fce7fc6c0 Delete type=0 #45
|
||||
2026/06/10-22:17:30.156732 7f2fce7fc6c0 Manual compaction at level-0 from '!items!APN91pQL0NBfZsG7' @ 72057594037927935 : 1 .. '!items!xxZKGqDVxAfr140W' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000032
|
||||
MANIFEST-000048
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-23:03:15.028836 7ff7d5fed6c0 Recovering log #30
|
||||
2026/06/09-23:03:15.038963 7ff7d5fed6c0 Delete type=3 #28
|
||||
2026/06/09-23:03:15.038982 7ff7d5fed6c0 Delete type=0 #30
|
||||
2026/06/09-23:04:39.124198 7ff7d4feb6c0 Level-0 table #35: started
|
||||
2026/06/09-23:04:39.124234 7ff7d4feb6c0 Level-0 table #35: 0 bytes OK
|
||||
2026/06/09-23:04:39.129992 7ff7d4feb6c0 Delete type=0 #33
|
||||
2026/06/09-23:04:39.148210 7ff7d4feb6c0 Manual compaction at level-0 from '!items!2IYbyCPF9LJojzsj' @ 72057594037927935 : 1 .. '!items!uOpWyMGK3oiUJ1Sl' @ 0 : 0; will stop at (end)
|
||||
2026/06/14-22:22:39.647097 7f29d67ee6c0 Recovering log #46
|
||||
2026/06/14-22:22:39.657645 7f29d67ee6c0 Delete type=3 #44
|
||||
2026/06/14-22:22:39.657692 7f29d67ee6c0 Delete type=0 #46
|
||||
2026/06/14-22:32:37.958747 7f29d4feb6c0 Level-0 table #51: started
|
||||
2026/06/14-22:32:37.958775 7f29d4feb6c0 Level-0 table #51: 0 bytes OK
|
||||
2026/06/14-22:32:37.965805 7f29d4feb6c0 Delete type=0 #49
|
||||
2026/06/14-22:32:37.966067 7f29d4feb6c0 Manual compaction at level-0 from '!items!2IYbyCPF9LJojzsj' @ 72057594037927935 : 1 .. '!items!uOpWyMGK3oiUJ1Sl' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2026/06/09-14:17:25.387408 7ff7d57ec6c0 Recovering log #25
|
||||
2026/06/09-14:17:25.396611 7ff7d57ec6c0 Delete type=3 #23
|
||||
2026/06/09-14:17:25.396630 7ff7d57ec6c0 Delete type=0 #25
|
||||
2026/06/09-14:18:13.995792 7ff7d4feb6c0 Level-0 table #31: started
|
||||
2026/06/09-14:18:13.995843 7ff7d4feb6c0 Level-0 table #31: 0 bytes OK
|
||||
2026/06/09-14:18:14.002901 7ff7d4feb6c0 Delete type=0 #29
|
||||
2026/06/09-14:18:14.021665 7ff7d4feb6c0 Manual compaction at level-0 from '!items!2IYbyCPF9LJojzsj' @ 72057594037927935 : 1 .. '!items!uOpWyMGK3oiUJ1Sl' @ 0 : 0; will stop at (end)
|
||||
2026/06/10-22:16:59.059510 7f2fcffff6c0 Recovering log #42
|
||||
2026/06/10-22:16:59.070966 7f2fcffff6c0 Delete type=3 #40
|
||||
2026/06/10-22:16:59.071001 7f2fcffff6c0 Delete type=0 #42
|
||||
2026/06/10-22:17:30.156791 7f2fce7fc6c0 Level-0 table #47: started
|
||||
2026/06/10-22:17:30.156799 7f2fce7fc6c0 Level-0 table #47: 0 bytes OK
|
||||
2026/06/10-22:17:30.162648 7f2fce7fc6c0 Delete type=0 #45
|
||||
2026/06/10-22:17:30.181195 7f2fce7fc6c0 Manual compaction at level-0 from '!items!2IYbyCPF9LJojzsj' @ 72057594037927935 : 1 .. '!items!uOpWyMGK3oiUJ1Sl' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -28,6 +28,7 @@ export function preLocalizeConfig() {
|
||||
magic.aspectlabel = game.i18n.localize(magic.aspectlabel)
|
||||
Object.values(magic.speciality).forEach((spec) => {
|
||||
spec.label = game.i18n.localize(spec.label)
|
||||
spec.labelelementkey = spec.labelelement
|
||||
spec.labelelement = game.i18n.localize(spec.labelelement)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -122,9 +122,8 @@ export default class CharacterDataModel extends foundry.abstract.TypeDataModel {
|
||||
typeofthrow: numberField(0),
|
||||
aspectskill: numberField(0),
|
||||
bonusmalusskill: numberField(0),
|
||||
aspectspeciality: numberField(0),
|
||||
rolldifficulty: numberField(0),
|
||||
bonusmalusspeciality: numberField(0),
|
||||
freepowerlevels: numberField(0),
|
||||
}),
|
||||
}),
|
||||
aspect: new fields.SchemaField({
|
||||
@@ -163,6 +162,10 @@ export default class CharacterDataModel extends foundry.abstract.TypeDataModel {
|
||||
nine: componentField(),
|
||||
zero: componentField(),
|
||||
}),
|
||||
magicOrder: new fields.ArrayField(
|
||||
new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
{ required: true, initial: [] }
|
||||
),
|
||||
magics: new fields.SchemaField({
|
||||
internalcinnabar: magicField(),
|
||||
alchemy: magicField(),
|
||||
|
||||
@@ -25,7 +25,7 @@ export default class ArmorDataModel extends foundry.abstract.TypeDataModel {
|
||||
domain: stringField(""),
|
||||
obtainLevel: intField(0, { min: 0, max: 5 }),
|
||||
obtainDifficulty: intField(0, { min: 0, max: 3 }),
|
||||
quantity: intField(1),
|
||||
quantity: intField(1, { min: 0 }),
|
||||
notes: htmlField(""),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export default class IngredientDataModel extends foundry.abstract.TypeDataModel
|
||||
school: stringField("all"),
|
||||
obtainLevel: intField(0, { min: 0, max: 5 }),
|
||||
obtainDifficulty: intField(0, { min: 0, max: 3 }),
|
||||
quantity: intField(1),
|
||||
quantity: intField(1, { min: 0 }),
|
||||
notes: htmlField(""),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ export default class KungfuDataModel extends foundry.abstract.TypeDataModel {
|
||||
reference: stringField(""),
|
||||
description: htmlField(""),
|
||||
orientation: stringField("yin"), // yin | yang | yinyang
|
||||
aspect: stringField("metal"), // metal | eau | terre | feu | bois
|
||||
aspect: stringField("metal"), // metal | water | earth | fire | wood
|
||||
skill: stringField("kungfu"), // kungfu | rangedcombat
|
||||
speciality: stringField(""),
|
||||
style: stringField(""),
|
||||
|
||||
@@ -21,7 +21,7 @@ export default class SpellDataModel extends foundry.abstract.TypeDataModel {
|
||||
reference: stringField(""),
|
||||
description: htmlField(""),
|
||||
specialityname: stringField(""),
|
||||
associatedelement: stringField("metal"), // metal | eau | terre | feu | bois
|
||||
associatedelement: stringField("metal"), // metal | water | earth | fire | wood
|
||||
hei: stringField(""),
|
||||
realizationtimeritual: stringField(""),
|
||||
realizationtimeaccelerated: stringField(""),
|
||||
|
||||
@@ -30,7 +30,7 @@ export default class WeaponDataModel extends foundry.abstract.TypeDataModel {
|
||||
range: stringField("contact"), // contact | courte | mediane | longue | extreme
|
||||
obtainLevel: intField(0, { min: 0, max: 5 }),
|
||||
obtainDifficulty: intField(0, { min: 0, max: 3 }),
|
||||
quantity: intField(1),
|
||||
quantity: intField(1, { min: 0 }),
|
||||
notes: htmlField(""),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,9 @@ export class CDECombat extends Combat {
|
||||
* for each selected combatant, then sync the result to the Combatant document.
|
||||
*/
|
||||
async rollInitiative(ids, options = {}) {
|
||||
const combatantIds = typeof ids === "string" ? [ids] : ids
|
||||
const combatantIds = ids
|
||||
? (typeof ids === "string" ? [ids] : ids)
|
||||
: this.combatants.map(c => c.id)
|
||||
for (const id of combatantIds) {
|
||||
const combatant = this.combatants.get(id)
|
||||
if (!combatant) continue
|
||||
|
||||
@@ -231,12 +231,103 @@ 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": return migrateEquipmentItem(oldItem)
|
||||
case "kungfu": return migrateKungfuItem(oldItem)
|
||||
case "spell": 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:
|
||||
// Unknown item type: keep as generic equipment
|
||||
return migrateEquipmentItem({ ...oldItem, type: "item" })
|
||||
@@ -329,6 +420,7 @@ function migrateCharacter(old) {
|
||||
resources,
|
||||
component,
|
||||
magics,
|
||||
magicOrder: [],
|
||||
threetreasures,
|
||||
experience: {
|
||||
value: Number(s.experience?.value ?? 0),
|
||||
|
||||
+12
-1
@@ -35,7 +35,18 @@ import { showWelcomeMessage, injectWelcomeActions } from "./ui/apps/welcome.js"
|
||||
Hooks.once("i18nInit", preLocalizeConfig)
|
||||
|
||||
Hooks.once("init", async () => {
|
||||
console.info(`CHRONIQUESDELETRANGE | Initializing ${SYSTEM_ID}`)
|
||||
console.log(
|
||||
"%c╔══════════════════════════════════════════════════════════╗\n" +
|
||||
"%c║ Chroniques de l'Étrange — FoundryVTT ║\n" +
|
||||
"%c║ Système de jeu par Antre-Monde Éditions ║\n" +
|
||||
"%c║ Made by Uberwald - https://www.ubwerwald.me ║\n" +
|
||||
"%c╚══════════════════════════════════════════════════════════╝",
|
||||
"color: #d4af37; font-weight: bold;",
|
||||
"color: #e2e8f4;",
|
||||
"color: #7d94b8;",
|
||||
"color: #5a7a9a;",
|
||||
"color: #d4af37; font-weight: bold;",
|
||||
)
|
||||
|
||||
registerSettings()
|
||||
|
||||
|
||||
@@ -1,16 +1,3 @@
|
||||
/**
|
||||
* Chroniques de l'Étrange — Système FoundryVTT
|
||||
*
|
||||
* Chroniques de l'Étrange est un jeu de rôle édité par Antre-Monde Éditions.
|
||||
* Ce système FoundryVTT est une implémentation indépendante et n'est pas
|
||||
* affilié à Antre-Monde Éditions,
|
||||
* mais a été réalisé avec l'autorisation d'Antre-Monde Éditions.
|
||||
*
|
||||
* @author LeRatierBretonnien
|
||||
* @copyright 2024–2026 LeRatierBretonnien
|
||||
* @license CC BY-NC-SA 4.0 – https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
*/
|
||||
|
||||
import { parseLegacyJson } from "../../migration/migrator.js"
|
||||
|
||||
const MIGRATION_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/apps/cde-migration-app.html"
|
||||
@@ -33,10 +20,12 @@ export class CDEMigrationApp extends foundry.applications.api.HandlebarsApplicat
|
||||
icon: "fas fa-file-import",
|
||||
resizable: false,
|
||||
},
|
||||
position: { width: 560, height: "auto" },
|
||||
position: { width: 600, height: "auto" },
|
||||
actions: {
|
||||
clearFiles: CDEMigrationApp.#clearFiles,
|
||||
doImport: CDEMigrationApp.#doImport,
|
||||
clearFiles: CDEMigrationApp.#clearFiles,
|
||||
doImport: CDEMigrationApp.#doImport,
|
||||
confirmImport: CDEMigrationApp.#confirmImport,
|
||||
cancelImport: CDEMigrationApp.#cancelImport,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -50,13 +39,31 @@ export class CDEMigrationApp extends foundry.applications.api.HandlebarsApplicat
|
||||
/** @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) {
|
||||
// Compute _duplicate live from the world each render, to avoid stale flags
|
||||
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,
|
||||
hasDuplicates: duplicateCount > 0,
|
||||
duplicateCount,
|
||||
count: this.#pending.length,
|
||||
importState: this.#importState,
|
||||
progress: this.#progress,
|
||||
total: this.#pending.length,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,43 +102,68 @@ export class CDEMigrationApp extends foundry.applications.api.HandlebarsApplicat
|
||||
const actors = parseLegacyJson(text)
|
||||
for (const actor of actors) {
|
||||
actor._srcFile = file.name
|
||||
// Avoid duplicates by name
|
||||
if (!this.#pending.some(p => p.name === actor.name)) {
|
||||
this.#pending.push(actor)
|
||||
// Avoid duplicates-by-name in our pending list
|
||||
if (this.#pending.some(p => p.name === actor.name)) {
|
||||
this.#errors.push(`« ${actor.name} » ignoré (nom déjà dans la liste d'attente, fichier « ${file.name} »)`)
|
||||
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
|
||||
// Live-update the progress element in the DOM without full re-render
|
||||
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) {
|
||||
@@ -145,4 +177,9 @@ export class CDEMigrationApp extends foundry.applications.api.HandlebarsApplicat
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
static async #cancelImport() {
|
||||
this.#importState = "idle"
|
||||
this.render()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ export class CDETinjiApp extends foundry.applications.api.HandlebarsApplicationM
|
||||
return
|
||||
}
|
||||
await setTinjiValue(current - 1)
|
||||
ChatMessage.create({
|
||||
await ChatMessage.create({
|
||||
user: game.user.id,
|
||||
content: `<div class="cde-tinji-spend-msg">
|
||||
<i class="fas fa-star"></i>
|
||||
|
||||
@@ -177,7 +177,7 @@ async function _drawFromLoksyu(message, aspect, type, aspectLabel) {
|
||||
? game.i18n.localize("CDE.Successes")
|
||||
: game.i18n.localize("CDE.AuspiciousDie")
|
||||
|
||||
ChatMessage.create({
|
||||
await ChatMessage.create({
|
||||
user: game.user.id,
|
||||
content: `<div class="cde-loksyu-draw-msg">
|
||||
<div class="cde-loksyu-draw-header">
|
||||
@@ -207,7 +207,7 @@ async function _spendTinjiPostRoll() {
|
||||
return
|
||||
}
|
||||
await setTinjiValue(current - 1)
|
||||
ChatMessage.create({
|
||||
await ChatMessage.create({
|
||||
user: game.user.id,
|
||||
content: `<div class="cde-tinji-spend-msg">
|
||||
<span class="cde-tinji-icon">天</span>
|
||||
|
||||
+44
-47
@@ -164,19 +164,16 @@ async function showMagicPrompt(params) {
|
||||
title: params.title,
|
||||
template: MAGIC_PROMPT_TEMPLATE,
|
||||
data: {
|
||||
numberofdice: params.numberofdice ?? 0,
|
||||
aspectskill: Number(params.aspectskill ?? 0),
|
||||
bonusmalusskill: params.bonusmalusskill ?? 0,
|
||||
numberofdice: params.numberofdice ?? 0,
|
||||
aspectskill: Number(params.aspectskill ?? 0),
|
||||
bonusmalusskill: params.bonusmalusskill ?? 0,
|
||||
bonusauspiciousdice: params.bonusauspiciousdice ?? 0,
|
||||
aspectspeciality: Number(params.aspectspeciality ?? 0),
|
||||
rolldifficulty: params.rolldifficulty ?? 1,
|
||||
bonusmalusspeciality: params.bonusmalusspeciality ?? 0,
|
||||
heispend: params.heispend ?? 0,
|
||||
typeofthrow: Number(params.typeofthrow ?? 0),
|
||||
rolldifficulty: params.rolldifficulty ?? 1,
|
||||
freepowerlevels: params.freepowerlevels ?? 0,
|
||||
typeofthrow: Number(params.typeofthrow ?? 0),
|
||||
},
|
||||
fields: ["aspectskill", "bonusmalusskill", "bonusauspiciousdice",
|
||||
"aspectspeciality", "rolldifficulty", "bonusmalusspeciality",
|
||||
"heispend", "typeofthrow"],
|
||||
"rolldifficulty", "freepowerlevels", "typeofthrow"],
|
||||
})
|
||||
}
|
||||
|
||||
@@ -318,7 +315,9 @@ export async function rollForActor(actor, rollKey) {
|
||||
const kfSkill = kfItem.system.skill ?? "kungfu"
|
||||
numberofdice = sys.skills?.[kfSkill]?.value ?? 0
|
||||
title = `${kfItem.name} [${game.i18n.localize(sys.skills?.[kfSkill]?.label ?? "CDE.KungFu")}]`
|
||||
kfDefaultAspect = ASPECT_NAMES.indexOf(kfItem.system.aspect ?? "metal")
|
||||
const kfAspect = kfItem.system.aspect?.toLowerCase() ?? "metal"
|
||||
const ASPECT_NORMALIZE = { eau: "water", terre: "earth", feu: "fire", bois: "wood" }
|
||||
kfDefaultAspect = ASPECT_NAMES.indexOf(ASPECT_NORMALIZE[kfAspect] ?? kfAspect)
|
||||
if (kfDefaultAspect < 0) kfDefaultAspect = 0
|
||||
break
|
||||
}
|
||||
@@ -427,7 +426,7 @@ export async function rollForActor(actor, rollKey) {
|
||||
}, wpRoll, ROLL_MODES[wpThrowMode] ?? "roll")
|
||||
|
||||
if (game.modules.get("dice-so-nice")?.active && wpMsg?.id) {
|
||||
await game.dice3d.waitFor3DAnimationByMessageID(wpMsg.id)
|
||||
try { await game.dice3d.waitFor3DAnimationByMessageID(wpMsg.id) } catch (_e) { /* DSN not available */ }
|
||||
}
|
||||
// Auto-update Loksyu/TinJi singletons from weapon roll faces
|
||||
if ((wpResults.loksyudice ?? 0) > 0) await updateLoksyuFromRoll(wpAspectName, wpFaces)
|
||||
@@ -439,8 +438,7 @@ export async function rollForActor(actor, rollKey) {
|
||||
return
|
||||
}
|
||||
|
||||
// For magic rolls the prompt allows adding HEI dice, so don't block early.
|
||||
// For itemkungfu, allow 0 base dice (user can add bonus dice in the prompt).
|
||||
// For magic rolls / itemkungfu, allow 0 base dice (user can add bonus dice in the prompt).
|
||||
if (numberofdice <= 0 && typeLibel !== "aspect" && typeLibel !== "itemkungfu" && !isMagic) {
|
||||
ui.notifications.warn(game.i18n.localize("CDE.Error0"))
|
||||
return
|
||||
@@ -465,16 +463,6 @@ export async function rollForActor(actor, rollKey) {
|
||||
defaultAspect = kfDefaultAspect
|
||||
}
|
||||
|
||||
let defaultSpecialAspect = 0
|
||||
if (isMagicSpecial && specialLibel) {
|
||||
// Look up the speciality's element from the MAGICS config constant
|
||||
const specialCfg = MAGICS?.[skillLibel]?.speciality?.[specialLibel]
|
||||
const aspectName = LABELELEMENT_TO_ASPECT[specialCfg?.labelelement]
|
||||
if (aspectName) {
|
||||
defaultSpecialAspect = ASPECT_NAMES.indexOf(aspectName)
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Show roll prompt ----
|
||||
let params
|
||||
|
||||
@@ -485,10 +473,8 @@ export async function rollForActor(actor, rollKey) {
|
||||
aspectskill: defaultAspect,
|
||||
bonusmalusskill: 0,
|
||||
bonusauspiciousdice: 0,
|
||||
aspectspeciality: defaultSpecialAspect,
|
||||
rolldifficulty: 1,
|
||||
bonusmalusspeciality: 0,
|
||||
heispend: 0,
|
||||
freepowerlevels: 0,
|
||||
typeofthrow: typeOfThrow,
|
||||
})
|
||||
} else {
|
||||
@@ -508,22 +494,18 @@ export async function rollForActor(actor, rollKey) {
|
||||
|
||||
// ---- Compute total dice and roll ----
|
||||
let aspectIndex, bonusMalus, bonusAuspicious, throwMode
|
||||
let spellAspectIndex = null // magic only: aspect of the speciality for Wu Xing
|
||||
let rollDifficulty = 1 // magic only: multiplier applied to successes
|
||||
let rollDifficulty = 1 // magic only: multiplier applied to successes
|
||||
|
||||
if (isMagic) {
|
||||
const skillAspectIndex = Number(params.aspectskill ?? 0)
|
||||
spellAspectIndex = Number(params.aspectspeciality ?? skillAspectIndex)
|
||||
aspectIndex = skillAspectIndex // used only for skill dice pool
|
||||
aspectIndex = skillAspectIndex // used for both dice pool and Wu Xing cycle
|
||||
bonusMalus = Number(params.bonusmalusskill ?? 0)
|
||||
bonusAuspicious = Number(params.bonusauspiciousdice ?? 0)
|
||||
rollDifficulty = Math.max(1, Number(params.rolldifficulty ?? 1))
|
||||
throwMode = Number(params.typeofthrow ?? 0)
|
||||
// magic: magic skill + aspect + bonuses + 1 (speciality base) + HEI spent
|
||||
const aspectDice = sys.aspect?.[ASPECT_NAMES[aspectIndex]]?.value ?? 0
|
||||
const bonusSpec = Number(params.bonusmalusspeciality ?? 0)
|
||||
const heiDice = Number(params.heispend ?? 0)
|
||||
numberofdice = numberofdice + aspectDice + bonusMalus + 1 + bonusSpec + heiDice
|
||||
numberofdice = numberofdice + aspectDice + bonusMalus + 1
|
||||
} else {
|
||||
aspectIndex = Number(params.aspect ?? 0)
|
||||
bonusMalus = Number(params.bonusmalus ?? 0)
|
||||
@@ -550,31 +532,43 @@ export async function rollForActor(actor, rollKey) {
|
||||
|
||||
const rollModeKey = ROLL_MODES[throwMode] ?? "roll"
|
||||
|
||||
// ---- Compute spell power (magic only) ----
|
||||
// Power = rollDifficulty × character aspect value for the speciality's
|
||||
// associated element (or the school's aspect for base magic rolls).
|
||||
let spellPower = null
|
||||
let spellPowerAspectName = null
|
||||
let spellPowerAspectValue = null
|
||||
if (isMagic) {
|
||||
if (isMagicSpecial && specialLibel) {
|
||||
const specialCfg = MAGICS?.[skillLibel]?.speciality?.[specialLibel]
|
||||
const elemName = LABELELEMENT_TO_ASPECT[specialCfg?.labelelementkey]
|
||||
if (elemName) spellPowerAspectName = elemName
|
||||
}
|
||||
if (!spellPowerAspectName) spellPowerAspectName = ASPECT_NAMES[aspectIndex]
|
||||
spellPowerAspectValue = sys.aspect?.[spellPowerAspectName]?.value ?? 0
|
||||
const freePowerLevels = Number(params.freepowerlevels ?? 0)
|
||||
spellPower = rollDifficulty * (spellPowerAspectValue + freePowerLevels)
|
||||
}
|
||||
|
||||
// ---- Compute Wu Xing results ----
|
||||
// For magic rolls, the spell's aspect (aspectspeciality) governs the Wu Xing
|
||||
// cycle (which faces count as successes/auspicious/etc.), not the skill aspect.
|
||||
const wuXingAspectName = spellAspectIndex !== null
|
||||
? ASPECT_NAMES[spellAspectIndex]
|
||||
: ASPECT_NAMES[aspectIndex]
|
||||
// The Wu Xing cycle always uses the roll's aspect (skill aspect for magic,
|
||||
// skill/resource aspect otherwise) to determine which faces count as
|
||||
// successes/auspicious/etc.
|
||||
const wuXingAspectName = ASPECT_NAMES[aspectIndex]
|
||||
const allResults = roll.dice[0]?.results ?? []
|
||||
const faces = countFaces(allResults)
|
||||
const results = computeWuXingResults(faces, wuXingAspectName, bonusAuspicious)
|
||||
if (!results) return
|
||||
|
||||
// For magic, successesdice × rollDifficulty = spell power
|
||||
const spellPower = isMagic ? results.successesdice * rollDifficulty : null
|
||||
|
||||
// ---- Build modifier summary text ----
|
||||
const modParts = []
|
||||
if (isMagic) {
|
||||
const bm = Number(params.bonusmalusskill ?? 0)
|
||||
const bs = Number(params.bonusmalusspeciality ?? 0)
|
||||
const hs = Number(params.heispend ?? 0)
|
||||
const ba = Number(params.bonusauspiciousdice ?? 0)
|
||||
const fp = Number(params.freepowerlevels ?? 0)
|
||||
if (bm !== 0) modParts.push(`${bm > 0 ? "+" : ""}${bm} ${game.i18n.localize("CDE.BonusMalus")}`)
|
||||
if (bs !== 0) modParts.push(`${bs > 0 ? "+" : ""}${bs} ${game.i18n.localize("CDE.SpellBonus")}`)
|
||||
if (ba !== 0) modParts.push(`+${ba} ${game.i18n.localize("CDE.BonusAuspiciousDice")}`)
|
||||
if (hs !== 0) modParts.push(`${hs} ${game.i18n.localize("CDE.HeiSpend")}`)
|
||||
if (fp !== 0) modParts.push(`+${fp} ${game.i18n.localize("CDE.FreePowerLevels")}`)
|
||||
if (rollDifficulty !== 1) modParts.push(`×${rollDifficulty} ${game.i18n.localize("CDE.RollDifficulty")}`)
|
||||
} else {
|
||||
const bm = Number(params.bonusmalus ?? 0)
|
||||
@@ -596,6 +590,9 @@ export async function rollForActor(actor, rollKey) {
|
||||
modifiersText: modParts.length ? modParts.join(" · ") : "",
|
||||
// Spell power (magic only)
|
||||
spellPower,
|
||||
spellPowerAspectLabel: spellPowerAspectName ? game.i18n.localize(ASPECT_LABELS[spellPowerAspectName] ?? "") : "",
|
||||
spellPowerAspectValue,
|
||||
spellPowerFreeLevels: isMagic ? Number(params.freepowerlevels ?? 0) : 0,
|
||||
rollDifficulty: isMagic ? rollDifficulty : null,
|
||||
// Actor info
|
||||
actorName: actor.name ?? "",
|
||||
@@ -610,7 +607,7 @@ export async function rollForActor(actor, rollKey) {
|
||||
|
||||
// ---- Wait for Dice So Nice animation ----
|
||||
if (game.modules.get("dice-so-nice")?.active && msg?.id) {
|
||||
await game.dice3d.waitFor3DAnimationByMessageID(msg.id)
|
||||
try { await game.dice3d.waitFor3DAnimationByMessageID(msg.id) } catch (_e) { /* DSN not available */ }
|
||||
}
|
||||
|
||||
// ---- Auto-update Loksyu / TinJi singletons ----
|
||||
|
||||
@@ -19,6 +19,10 @@ import { CDEBaseActorSheet } from "./base.js"
|
||||
export class CDECharacterSheet extends CDEBaseActorSheet {
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["character"],
|
||||
actions: {
|
||||
moveMagicUp: CDECharacterSheet.#onMoveMagicUp,
|
||||
moveMagicDown: CDECharacterSheet.#onMoveMagicDown,
|
||||
},
|
||||
}
|
||||
|
||||
static PARTS = {
|
||||
@@ -48,25 +52,35 @@ export class CDECharacterSheet extends CDEBaseActorSheet {
|
||||
|
||||
// Build magicsDisplay: only include the 5 relevant specialities per magic type + grimoire
|
||||
const systemMagics = context.systemData.magics ?? {}
|
||||
context.magicsDisplay = Object.fromEntries(
|
||||
Object.entries(MAGICS).map(([magicKey, magicDef]) => {
|
||||
const magicData = systemMagics[magicKey] ?? {}
|
||||
return [
|
||||
magicKey,
|
||||
{
|
||||
value: magicData.value ?? 0,
|
||||
visible: magicData.visible ?? false,
|
||||
speciality: Object.fromEntries(
|
||||
Object.keys(magicDef.speciality).map((specKey) => [
|
||||
specKey,
|
||||
{ check: magicData.speciality?.[specKey]?.check ?? false },
|
||||
])
|
||||
),
|
||||
grimoire: spellsByDiscipline[magicKey] ?? [],
|
||||
},
|
||||
]
|
||||
const magicEntries = Object.entries(MAGICS).map(([magicKey, magicDef]) => {
|
||||
const magicData = systemMagics[magicKey] ?? {}
|
||||
return [
|
||||
magicKey,
|
||||
{
|
||||
value: magicData.value ?? 0,
|
||||
visible: magicData.visible ?? false,
|
||||
speciality: Object.fromEntries(
|
||||
Object.keys(magicDef.speciality).map((specKey) => [
|
||||
specKey,
|
||||
{ check: magicData.speciality?.[specKey]?.check ?? false },
|
||||
])
|
||||
),
|
||||
grimoire: spellsByDiscipline[magicKey] ?? [],
|
||||
},
|
||||
]
|
||||
})
|
||||
const order = context.systemData.magicOrder ?? []
|
||||
if (order.length > 0) {
|
||||
magicEntries.sort((a, b) => {
|
||||
const ia = order.indexOf(a[0])
|
||||
const ib = order.indexOf(b[0])
|
||||
if (ia === -1 && ib === -1) return 0
|
||||
if (ia === -1) return 1
|
||||
if (ib === -1) return -1
|
||||
return ia - ib
|
||||
})
|
||||
)
|
||||
}
|
||||
context.magicsDisplay = Object.fromEntries(magicEntries)
|
||||
|
||||
return context
|
||||
}
|
||||
@@ -155,7 +169,7 @@ export class CDECharacterSheet extends CDEBaseActorSheet {
|
||||
cell.addEventListener("click", (event) => {
|
||||
event.preventDefault()
|
||||
const rollKey = cell.dataset.libelId
|
||||
if (rollKey) rollForActor(this.document, rollKey)
|
||||
if (rollKey) rollForActor(this.document, rollKey)?.catch(err => console.error("Roll failed:", err))
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -171,6 +185,28 @@ export class CDECharacterSheet extends CDEBaseActorSheet {
|
||||
})
|
||||
}
|
||||
|
||||
static async #onMoveMagicUp(event, target) {
|
||||
const key = target.dataset.magicKey
|
||||
let order = this.document.system.magicOrder ?? []
|
||||
if (!order.length) order = [...Object.keys(MAGICS)]
|
||||
else order = [...order]
|
||||
const idx = order.indexOf(key)
|
||||
if (idx <= 0) return
|
||||
[order[idx - 1], order[idx]] = [order[idx], order[idx - 1]]
|
||||
await this.document.update({ "system.magicOrder": order })
|
||||
}
|
||||
|
||||
static async #onMoveMagicDown(event, target) {
|
||||
const key = target.dataset.magicKey
|
||||
let order = this.document.system.magicOrder ?? []
|
||||
if (!order.length) order = [...Object.keys(MAGICS)]
|
||||
else order = [...order]
|
||||
const idx = order.indexOf(key)
|
||||
if (idx === -1 || idx >= order.length - 1) return
|
||||
[order[idx], order[idx + 1]] = [order[idx + 1], order[idx]]
|
||||
await this.document.update({ "system.magicOrder": order })
|
||||
}
|
||||
|
||||
#bindComponentRandomize() {
|
||||
const btn = this.element?.querySelector("[data-action='randomize-component']")
|
||||
if (!btn) return
|
||||
|
||||
@@ -50,7 +50,7 @@ export class CDENpcSheet extends CDEBaseActorSheet {
|
||||
cell.addEventListener("click", (event) => {
|
||||
event.preventDefault()
|
||||
const rollKey = cell.dataset.libelId
|
||||
if (rollKey) rollForActor(this.document, rollKey)
|
||||
if (rollKey) rollForActor(this.document, rollKey)?.catch(err => console.error("Roll failed:", err))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -26,11 +26,11 @@ export class CDESanheiSheet extends CDEBaseItemSheet {
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
const enrich = (content) => foundry.applications.ux.TextEditor.implementation.enrichHTML(content ?? "", { async: true })
|
||||
const props = this.document.system.properties
|
||||
context.prop1DescriptionHTML = await enrich(props.prop1.description)
|
||||
context.prop2DescriptionHTML = await enrich(props.prop2.description)
|
||||
context.prop3DescriptionHTML = await enrich(props.prop3.description)
|
||||
context.propFields = this.document.system.schema.fields.properties.fields
|
||||
const props = this.document.system.properties ?? {}
|
||||
context.prop1DescriptionHTML = await enrich(props.prop1?.description)
|
||||
context.prop2DescriptionHTML = await enrich(props.prop2?.description)
|
||||
context.prop3DescriptionHTML = await enrich(props.prop3?.description)
|
||||
context.propFields = this.document.system.schema.fields.properties?.fields
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,14 @@
|
||||
title="{{ localize 'CDE.Roll' }} {{getMagicLabel key}}">
|
||||
<i class="fas fa-dice-d10"></i>
|
||||
</a>
|
||||
<a class="cde-magic-order-btn" data-action="moveMagicUp" data-magic-key="{{key}}"
|
||||
title="{{ localize 'CDE.MoveUp' }}">
|
||||
<i class="fas fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="cde-magic-order-btn" data-action="moveMagicDown" data-magic-key="{{key}}"
|
||||
title="{{ localize 'CDE.MoveDown' }}">
|
||||
<i class="fas fa-chevron-down"></i>
|
||||
</a>
|
||||
<label class="cde-magic-toggle" title="{{ localize 'CDE.PracticeSpecialty' }}">
|
||||
<input type="checkbox" name="system.magics.{{key}}.visible" {{checked magic.visible}} />
|
||||
<i class="fas {{#if magic.visible}}fa-chevron-up{{else}}fa-chevron-down{{/if}}"></i>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
|
||||
{{! Preview table }}
|
||||
{{#if hasPending}}
|
||||
{{#if (and hasPending (ne importState "importing"))}}
|
||||
<div class="cde-migration-preview">
|
||||
<div class="cde-migration-preview-header">
|
||||
<span>{{ localize "CDE.MigrationPreviewTitle" }}</span>
|
||||
@@ -34,9 +34,12 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each pending}}
|
||||
<tr>
|
||||
<tr class="{{#if _duplicate}}cde-migration-row-duplicate{{/if}}">
|
||||
<td><img src="{{img}}" class="cde-migration-thumb" alt=""></td>
|
||||
<td class="cde-migration-name">{{name}}</td>
|
||||
<td class="cde-migration-name">
|
||||
{{#if _duplicate}}<i class="fa-solid fa-triangle-exclamation cde-migration-duplicate-icon" title="{{ localize 'CDE.MigrationDuplicate' }}"></i>{{/if}}
|
||||
{{name}}
|
||||
</td>
|
||||
<td>
|
||||
<span class="cde-migration-type-badge cde-migration-type-{{type}}">
|
||||
{{#if (eq type "character")}}
|
||||
@@ -55,6 +58,41 @@
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{! Duplicate warning banner (confirmation step) }}
|
||||
{{#if (eq importState "confirm")}}
|
||||
<div class="cde-migration-confirm-bar">
|
||||
<p class="cde-migration-confirm-msg">
|
||||
<i class="fa-solid fa-triangle-exclamation"></i>
|
||||
{{ localize "CDE.MigrationImportConfirm" count=count }}
|
||||
</p>
|
||||
{{#if hasDuplicates}}
|
||||
<p class="cde-migration-confirm-duplicates">
|
||||
<i class="fa-solid fa-triangle-exclamation"></i>
|
||||
{{ localize "CDE.MigrationDuplicateCount" count=duplicateCount }}
|
||||
</p>
|
||||
{{/if}}
|
||||
<div class="cde-migration-confirm-actions">
|
||||
<button type="button" class="cde-migration-confirm-btn" data-action="confirmImport">
|
||||
<i class="fa-solid fa-download"></i>
|
||||
{{ localize "CDE.MigrationConfirmAction" }} ({{count}})
|
||||
</button>
|
||||
<button type="button" class="cde-migration-cancel-btn" data-action="cancelImport">
|
||||
<i class="fa-solid fa-xmark"></i>
|
||||
{{ localize "CDE.Cancel" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{! Progress (importing state) }}
|
||||
{{#if (eq importState "importing")}}
|
||||
<div class="cde-migration-progress">
|
||||
<i class="fa-solid fa-spinner fa-spin"></i>
|
||||
<span>{{ localize "CDE.MigrationImporting" }}</span>
|
||||
<span class="cde-migration-progress-count">{{progress}}/{{total}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{! Errors }}
|
||||
{{#if hasErrors}}
|
||||
<ul class="cde-migration-errors">
|
||||
@@ -66,12 +104,12 @@
|
||||
|
||||
{{! Action bar }}
|
||||
<div class="cde-migration-actions">
|
||||
{{#if hasPending}}
|
||||
{{#if (and hasPending (eq importState "idle"))}}
|
||||
<button type="button" class="cde-migration-import-btn" data-action="doImport">
|
||||
<i class="fa-solid fa-download"></i>
|
||||
{{ localize "CDE.MigrationImport" }} ({{count}})
|
||||
</button>
|
||||
{{else}}
|
||||
{{else if (and (not hasPending) (eq importState "idle"))}}
|
||||
<p class="cde-migration-hint">{{ localize "CDE.MigrationHint" }}</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
{{#if spellPower}}
|
||||
<div class="cde-rr-spell-power">
|
||||
<span class="cde-rr-spell-power-count">{{spellPower}}</span>
|
||||
<span class="cde-rr-spell-power-formula">{{spellPowerAspectLabel}} ({{spellPowerAspectValue}}{{#if spellPowerFreeLevels}} + {{spellPowerFreeLevels}}{{/if}}) × {{rollDifficulty}}</span>
|
||||
<span class="cde-rr-spell-power-label">{{ localize "CDE.SpellPower" }}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
@@ -54,16 +54,6 @@
|
||||
<div class="cde-roll-section cde-roll-section--separator">
|
||||
<p class="cde-roll-section-title">② {{ localize "CDE.TwoPowerOfSpell" }}</p>
|
||||
<div class="cde-roll-fields">
|
||||
<div class="cde-roll-field">
|
||||
<label>{{ localize "CDE.AspectSpeciality" }}</label>
|
||||
<select name="aspectspeciality">
|
||||
<option value="0" {{#if (eq aspectspeciality 0)}}selected{{/if}}>{{ localize "CDE.Metal" }}</option>
|
||||
<option value="1" {{#if (eq aspectspeciality 1)}}selected{{/if}}>{{ localize "CDE.Water" }}</option>
|
||||
<option value="2" {{#if (eq aspectspeciality 2)}}selected{{/if}}>{{ localize "CDE.Earth" }}</option>
|
||||
<option value="3" {{#if (eq aspectspeciality 3)}}selected{{/if}}>{{ localize "CDE.Fire" }}</option>
|
||||
<option value="4" {{#if (eq aspectspeciality 4)}}selected{{/if}}>{{ localize "CDE.Wood" }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="cde-roll-field">
|
||||
<label>{{ localize "CDE.RollDifficulty" }} (×)</label>
|
||||
<select name="rolldifficulty">
|
||||
@@ -75,32 +65,17 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="cde-roll-field">
|
||||
<label>{{ localize "CDE.BonusMalus" }}</label>
|
||||
<select name="bonusmalusspeciality">
|
||||
<option value="-5" {{#if (eq bonusmalusspeciality -5)}}selected{{/if}}>−5 dés</option>
|
||||
<option value="-4" {{#if (eq bonusmalusspeciality -4)}}selected{{/if}}>−4 dés</option>
|
||||
<option value="-3" {{#if (eq bonusmalusspeciality -3)}}selected{{/if}}>−3 dés</option>
|
||||
<option value="-2" {{#if (eq bonusmalusspeciality -2)}}selected{{/if}}>−2 dés</option>
|
||||
<option value="-1" {{#if (eq bonusmalusspeciality -1)}}selected{{/if}}>−1 dé</option>
|
||||
<option value="0" {{#if (eq bonusmalusspeciality 0)}}selected{{/if}}>0 (aucun)</option>
|
||||
<option value="1" {{#if (eq bonusmalusspeciality 1)}}selected{{/if}}>+1 dé</option>
|
||||
<option value="2" {{#if (eq bonusmalusspeciality 2)}}selected{{/if}}>+2 dés</option>
|
||||
<option value="3" {{#if (eq bonusmalusspeciality 3)}}selected{{/if}}>+3 dés</option>
|
||||
<option value="4" {{#if (eq bonusmalusspeciality 4)}}selected{{/if}}>+4 dés</option>
|
||||
<option value="5" {{#if (eq bonusmalusspeciality 5)}}selected{{/if}}>+5 dés</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="cde-roll-field">
|
||||
<label>{{ localize "CDE.HeiSpend" }}</label>
|
||||
<select name="heispend">
|
||||
<option value="0" {{#if (eq heispend 0)}}selected{{/if}}>0 Hei</option>
|
||||
<option value="1" {{#if (eq heispend 1)}}selected{{/if}}>1 Hei</option>
|
||||
<option value="2" {{#if (eq heispend 2)}}selected{{/if}}>2 Hei</option>
|
||||
<option value="3" {{#if (eq heispend 3)}}selected{{/if}}>3 Hei</option>
|
||||
<option value="4" {{#if (eq heispend 4)}}selected{{/if}}>4 Hei</option>
|
||||
<option value="5" {{#if (eq heispend 5)}}selected{{/if}}>5 Hei</option>
|
||||
<label>{{ localize "CDE.FreePowerLevels" }}</label>
|
||||
<select name="freepowerlevels">
|
||||
<option value="0" {{#if (eq freepowerlevels 0)}}selected{{/if}}>0</option>
|
||||
<option value="1" {{#if (eq freepowerlevels 1)}}selected{{/if}}>+1</option>
|
||||
<option value="2" {{#if (eq freepowerlevels 2)}}selected{{/if}}>+2</option>
|
||||
<option value="3" {{#if (eq freepowerlevels 3)}}selected{{/if}}>+3</option>
|
||||
<option value="4" {{#if (eq freepowerlevels 4)}}selected{{/if}}>+4</option>
|
||||
<option value="5" {{#if (eq freepowerlevels 5)}}selected{{/if}}>+5</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<p class="cde-roll-hint"><i>{{ localize "CDE.DoNotModify" }}</i></p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user