ALl features OK, excetp creatures sub-type, WIP3
This commit is contained in:
@@ -11,6 +11,10 @@ export default class MournbladeCYD2PersonnageSheet extends MournbladeCYD2ActorSh
|
||||
...super.DEFAULT_OPTIONS.window,
|
||||
title: "SHEETS.Actor.personnage",
|
||||
},
|
||||
actions: {
|
||||
...super.DEFAULT_OPTIONS.actions,
|
||||
removeLinkedActor: MournbladeCYD2PersonnageSheet.#onRemoveLinkedActor,
|
||||
},
|
||||
};
|
||||
|
||||
/** @override */
|
||||
@@ -53,6 +57,131 @@ export default class MournbladeCYD2PersonnageSheet extends MournbladeCYD2ActorSh
|
||||
context.adversiteTotal = (actor.system.adversite?.bleue || 0) + (actor.system.adversite?.rouge || 0) + (actor.system.adversite?.noire || 0);
|
||||
context.richesse = actor.computeRichesse?.() ?? { po: 0, pa: 0, sc: 0, valueSC: 0 };
|
||||
context.valeurEquipement = actor.computeValeurEquipement?.() ?? { po: 0, pa: 0, sc: 0, valueSC: 0 };
|
||||
|
||||
// Prepare sorcellerie linked actors for display
|
||||
context.creaturesInvoqueesActors = await this._getLinkedActors(actor.system.sorcellerie.creaturesinvoquees);
|
||||
context.demonsLiesActors = await this._getLinkedActors(actor.system.sorcellerie.demonslies);
|
||||
context.enchantementsActors = await this._getLinkedActors(actor.system.sorcellerie.enchantements);
|
||||
|
||||
// Prepare enriched HTML for sorcellerie fields
|
||||
context.enrichedInvocationsEnCours = await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||
actor.system.sorcellerie?.invocationsencours || "", { async: true }
|
||||
);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get actor objects from UUID references
|
||||
* @param {string[]} uuids - Array of actor UUIDs
|
||||
* @returns {Promise<Actor[]>} Array of actor documents
|
||||
*/
|
||||
async _getLinkedActors(uuids) {
|
||||
if (!uuids || !Array.isArray(uuids) || uuids.length === 0) return [];
|
||||
|
||||
const actors = [];
|
||||
for (const uuid of uuids) {
|
||||
const actor = await fromUuid(uuid);
|
||||
if (actor) {
|
||||
actors.push(actor);
|
||||
}
|
||||
}
|
||||
return actors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle actor drop on the sheet
|
||||
* @override
|
||||
*/
|
||||
async _onDropActor(event, data) {
|
||||
if (!this.document.isOwner) return;
|
||||
|
||||
const droppedActor = await Actor.fromDropData(data);
|
||||
if (!droppedActor) return;
|
||||
|
||||
// Only allow dropping Creature type actors
|
||||
if (droppedActor.type !== 'creature') return;
|
||||
|
||||
// Determine which list to add to based on creature subtype
|
||||
let fieldPath = '';
|
||||
const subType = droppedActor.system.soustype || 'creature';
|
||||
|
||||
switch (subType) {
|
||||
case 'demon':
|
||||
fieldPath = 'system.sorcellerie.demonslies';
|
||||
break;
|
||||
case 'automata':
|
||||
fieldPath = 'system.sorcellerie.enchantements';
|
||||
break;
|
||||
case 'creature':
|
||||
default:
|
||||
fieldPath = 'system.sorcellerie.creaturesinvoquees';
|
||||
break;
|
||||
}
|
||||
|
||||
// Add the actor UUID to the appropriate array
|
||||
const currentValue = foundry.utils.getProperty(this.document.system, fieldPath) || [];
|
||||
|
||||
// Avoid duplicates
|
||||
if (!currentValue.includes(droppedActor.uuid)) {
|
||||
currentValue.push(droppedActor.uuid);
|
||||
await this.document.update({ [fieldPath]: currentValue });
|
||||
}
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle removal of a linked actor from sorcellerie sections
|
||||
* @param {Event} event - The click event
|
||||
* @param {HTMLElement} target - The clicked element
|
||||
*/
|
||||
static async #onRemoveLinkedActor(event, target) {
|
||||
const li = target.closest(".item");
|
||||
if (!li) return;
|
||||
|
||||
const field = target.dataset.field;
|
||||
const uuid = target.dataset.uuid;
|
||||
|
||||
if (!field || !uuid) return;
|
||||
|
||||
const fieldPath = `system.sorcellerie.${field}`;
|
||||
const currentValue = foundry.utils.getProperty(this.document.system, fieldPath) || [];
|
||||
|
||||
// Remove the UUID from the array
|
||||
const newValue = currentValue.filter(u => u !== uuid);
|
||||
|
||||
await this.document.update({ [fieldPath]: newValue });
|
||||
this.render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle click on linked actor name to open its sheet
|
||||
* @param {Event} event - The click event
|
||||
*/
|
||||
static async #onOpenLinkedActor(event) {
|
||||
const target = event.target.closest(".linked-actor-name");
|
||||
if (!target) return;
|
||||
|
||||
const uuid = target.dataset.actorUuid;
|
||||
if (!uuid) return;
|
||||
|
||||
const actor = await fromUuid(uuid);
|
||||
if (actor) {
|
||||
actor.sheet.render(true);
|
||||
}
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_onRender(context, options) {
|
||||
super._onRender(context, options);
|
||||
|
||||
// Add click handler for linked actor names
|
||||
this.element.querySelectorAll('.linked-actor-name').forEach(el => {
|
||||
el.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
this.constructor.#onOpenLinkedActor(event);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +66,10 @@ export default class CreatureDataModel extends foundry.abstract.TypeDataModel {
|
||||
value: new fields.NumberField({ initial: 0, integer: true })
|
||||
}),
|
||||
sante: new fields.SchemaField({
|
||||
vigueur: new fields.NumberField({ initial: 0, integer: true }),
|
||||
etat: new fields.NumberField({ initial: 0, integer: true }),
|
||||
vigueurmodifier: new fields.NumberField({ initial: 0, integer: true }),
|
||||
nbcombativite: new fields.NumberField({ initial: 5, integer: true })
|
||||
vigueur: new fields.NumberField({ initial: 0, integer: true, min: 0 }),
|
||||
etat: new fields.NumberField({ initial: 0, integer: true, min: 0, nullable: true }),
|
||||
vigueurmodifier: new fields.NumberField({ initial: 0, integer: true, nullable: true }),
|
||||
nbcombativite: new fields.NumberField({ initial: 5, integer: true, min: 0, nullable: true })
|
||||
}),
|
||||
ame: new fields.SchemaField({
|
||||
seuilpouvoir: new fields.NumberField({ initial: 0, integer: true }),
|
||||
@@ -110,7 +110,7 @@ export default class CreatureDataModel extends foundry.abstract.TypeDataModel {
|
||||
ressources: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true })
|
||||
}),
|
||||
soustype: new fields.StringField({ initial: "" })
|
||||
soustype: new fields.StringField({ initial: "creature" })
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,9 +106,9 @@ export default class PersonnageDataModel extends foundry.abstract.TypeDataModel
|
||||
// Sorcellerie
|
||||
sorcellerie: new fields.SchemaField({
|
||||
runes: new fields.HTMLField({ initial: "" }),
|
||||
creaturesinvoquees: new fields.HTMLField({ initial: "" }),
|
||||
demonslies: new fields.HTMLField({ initial: "" }),
|
||||
enchantements: new fields.HTMLField({ initial: "" }),
|
||||
creaturesinvoquees: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||
demonslies: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||
enchantements: new fields.ArrayField(new fields.StringField(), { initial: [] }),
|
||||
invocationsencours: new fields.HTMLField({ initial: "" }),
|
||||
coutPouvoirInvocations: new fields.NumberField({ initial: 0, integer: true })
|
||||
})
|
||||
|
||||
@@ -273,6 +273,36 @@ export class MournbladeCYD2Actor extends Actor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_preUpdate(changed, options, user) {
|
||||
// Clean up numeric fields in various schemas to ensure they are valid numbers
|
||||
const numericCleanup = (schemaPath, dataPath) => {
|
||||
if (changed?.system?.[dataPath]) {
|
||||
const schema = foundry.utils.getProperty(this.system.schema.fields, schemaPath);
|
||||
if (schema) {
|
||||
for (const [key, value] of Object.entries(changed.system[dataPath])) {
|
||||
if (schema.fields[key] instanceof foundry.data.fields.NumberField) {
|
||||
if (value === "" || value === null || value === undefined || isNaN(value)) {
|
||||
changed.system[dataPath][key] = 0;
|
||||
} else {
|
||||
changed.system[dataPath][key] = Number(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Apply cleanup to schemas that may have numeric fields submitted from forms
|
||||
numericCleanup("sante", "sante");
|
||||
numericCleanup("ame", "ame");
|
||||
numericCleanup("combat", "combat");
|
||||
numericCleanup("balance", "balance");
|
||||
numericCleanup("adversite", "adversite");
|
||||
numericCleanup("vitesse", "vitesse");
|
||||
numericCleanup("ressources", "ressources");
|
||||
numericCleanup("eclat", "eclat");
|
||||
numericCleanup("bonneaventure", "bonneaventure");
|
||||
numericCleanup("experience", "experience");
|
||||
|
||||
if (changed?.system?.sante?.etat !== undefined && changed.system.sante.etat != this.system.sante.etat) {
|
||||
const oldEtat = this.system.sante.etat
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -120,7 +120,6 @@ export const MOURNBLADECYD2_CONFIG = {
|
||||
{ key: "traitespece", label: "Trait d'espèce" }
|
||||
],
|
||||
optionsSousTypeCreature: [
|
||||
{ key: "", label: localizeOrFallback("MNBL.none", "Aucun") },
|
||||
{ key: "creature", label: localizeOrFallback("MNBL.creature", "Créature") },
|
||||
{ key: "demon", label: localizeOrFallback("MNBL.demon", "Démon") },
|
||||
{ key: "automata", label: localizeOrFallback("MNBL.automata", "Automata") }
|
||||
|
||||
@@ -147,6 +147,7 @@ function welcomeMessage() {
|
||||
<strong>Support</strong>
|
||||
<p>Système développé par LeRatierBretonnien.</p>
|
||||
<a class="welcome-link" href="https://discord.gg/pPSDNJk" target="_blank"><i class="fab fa-discord"></i>Discord FR Foundry</a>
|
||||
<a class="welcome-link" href="https://www.uberwald.me" target="_blank"><i class="fas fa-external-link-alt"></i>Uberwald</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -54,11 +54,11 @@ export class MournbladeCYD2Utility {
|
||||
return text.toUpperCase();
|
||||
})
|
||||
Handlebars.registerHelper('lower', function (text) {
|
||||
return text.toLowerCase()
|
||||
return text.toLowerCase();
|
||||
})
|
||||
Handlebars.registerHelper('upperFirst', function (text) {
|
||||
if (typeof text !== 'string') return text
|
||||
return text.charAt(0).toUpperCase() + text.slice(1)
|
||||
if (typeof text !== 'string') return text;
|
||||
return text.charAt(0).toUpperCase() + text.slice(1);
|
||||
})
|
||||
Handlebars.registerHelper('notEmpty', function (list) {
|
||||
return list.length > 0;
|
||||
@@ -99,11 +99,11 @@ export class MournbladeCYD2Utility {
|
||||
.join(', ');
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('select', function(value, options) {
|
||||
const html = options.fn(this);
|
||||
Handlebars.registerHelper('select', function(value, opts) {
|
||||
const html = opts.fn(this);
|
||||
const escaped = String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
return html.replace(new RegExp(`value="${escaped}"`, 'g'), `value="${value}" selected="selected"`);
|
||||
})
|
||||
});
|
||||
|
||||
game.settings.register("fvtt-mournblade-cyd-2-0", "mournblade-cyd2-pause-logo", {
|
||||
name: "Logo de pause",
|
||||
|
||||
Reference in New Issue
Block a user