diff --git a/changelog.md b/changelog.md
index 178fa015..d69694bd 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,6 +1,13 @@
---
# v10.7 - L'os de Semolosse
+## v10.7.14 - l'expérience de Semolosse
+- Affichage des personnages accordés sur les fiches des entités
+- Refonte du journal d'expérience
+ - disponible pour les personnages des joueurs
+ - explication "comptable" des changements (dépense ou ajout, changements de niveaux, ...)
+- tri alphabétique des différentes listes (sorts, recettes, oeuvres, ...)
+
## v10.7.13 - l'armure de Semolosse
- Fix: en cas d'armure variable, la détérioration diminue le dé d'armure
diff --git a/module/actor-entite-sheet.js b/module/actor-entite-sheet.js
index d7a96ce0..50f505bf 100644
--- a/module/actor-entite-sheet.js
+++ b/module/actor-entite-sheet.js
@@ -1,4 +1,6 @@
import { RdDActorSheet } from "./actor-sheet.js";
+import { RdDSheetUtility } from "./rdd-sheet-utility.js";
+import { RdDUtility } from "./rdd-utility.js";
export class RdDActorEntiteSheet extends RdDActorSheet {
@@ -13,6 +15,12 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
});
}
+ async getData() {
+ let formData = await super.getData();
+ formData.resonances = this.actor.system.sante.resonnance.actors.map(actorId => game.actors.get(actorId))
+ .map(actor => { return { id: actor.id, name: actor.name, img: actor.img } })
+ return formData
+ }
/* -------------------------------------------- */
/** @override */
@@ -35,6 +43,23 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value));
});
+ this.html.find('.resonance-delete').click(async event => {
+ const li = RdDSheetUtility.getEventElement(event);
+ const actorId = li.data("actor-id");
+ if (actorId) {
+ const actorResonance = game.actors.get(actorId);
+ RdDUtility.confirmerSuppressionSubacteur(this, actorResonance, li, () => {
+ console.log('Delete : ', actorId);
+ this.removeSubacteur(actorId);
+ RdDUtility.slideOnDelete(this, li);
+ });
+ }
+ });
+ }
+
+ async removeSubacteur(actorId) {
+ let newResonances = this.actor.system.sante.resonnance.actors.filter(id => id != actorId);
+ await this.actor.update({ 'system.sante.resonnance.actors': newResonances }, { renderSheet: false });
}
}
diff --git a/module/actor-sheet.js b/module/actor-sheet.js
index d19ef734..9ff645e3 100644
--- a/module/actor-sheet.js
+++ b/module/actor-sheet.js
@@ -129,7 +129,11 @@ export class RdDActorSheet extends RdDBaseActorSheet {
const actorId = li.data("actor-id");
if (actorId) {
const subActor = game.actors.get(actorId);
- RdDUtility.confirmerSuppressionSubacteur(this, subActor, li);
+ RdDUtility.confirmerSuppressionSubacteur(this, subActor, li, () => {
+ console.log('Delete : ', subActor.id);
+ this.actor.removeSubacteur(subActor.id);
+ RdDUtility.slideOnDelete(this, li);
+ });
}
});
this.html.find('.experiencelog-delete').click(async event => {
@@ -142,6 +146,13 @@ export class RdDActorSheet extends RdDBaseActorSheet {
const key = Number(li.data("key") ?? -1);
await this.actor.deleteExperienceLog(0, key + 1);
});
+ this.html.find("input.derivee-value[name='system.compteurs.stress.value']").change(async event => {
+ this.actor.updateCompteurValue("stress", parseInt(event.target.value));
+ });
+ this.html.find("input.derivee-value[name='system.compteurs.experience.value']").change(async event => {
+ this.actor.updateCompteurValue("experience", parseInt(event.target.value));
+ });
+
this.html.find('.encaisser-direct').click(async event => {
this.actor.encaisser();
})
diff --git a/module/actor.js b/module/actor.js
index ed20d6ab..64adae39 100644
--- a/module/actor.js
+++ b/module/actor.js
@@ -37,6 +37,7 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDItemBlessure } from "./item/blessure.js";
import { AppAstrologie } from "./sommeil/app-astrologie.js";
import { RdDEmpoignade } from "./rdd-empoignade.js";
+import { ExperienceLog, XP_TOPIC } from "./actor/experience-log.js";
const POSSESSION_SANS_DRACONIC = {
img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp',
@@ -821,31 +822,40 @@ export class RdDActor extends RdDBaseActor {
}
/* -------------------------------------------- */
- async updateCarac(caracName, caracValue) {
+ async updateCarac(caracName, to) {
if (caracName == "force") {
- if (Number(caracValue) > this.getTaille() + 4) {
+ if (Number(to) > this.getTaille() + 4) {
ui.notifications.warn("Votre FORCE doit être au maximum de TAILLE+4");
return;
}
}
if (caracName == "reve") {
- if (caracValue > Misc.toInt(this.system.reve.seuil.value)) {
- this.setPointsDeSeuil(caracValue);
+ if (to > Misc.toInt(this.system.reve.seuil.value)) {
+ this.setPointsDeSeuil(to);
}
}
if (caracName == "chance") {
- if (caracValue > Misc.toInt(this.system.compteurs.chance.value)) {
- this.setPointsDeChance(caracValue);
+ if (to > Misc.toInt(this.system.compteurs.chance.value)) {
+ this.setPointsDeChance(to);
}
}
- await this.update({ [`system.carac.${caracName}.value`]: caracValue });
+ let selectedCarac = RdDActor._findCaracByName(this.system.carac, caracName);
+ const from = selectedCarac.value
+ await this.update({ [`system.carac.${caracName}.value`]: to });
+ await ExperienceLog.add(this, XP_TOPIC.CARAC, from, to, caracName);
}
/* -------------------------------------------- */
- async updateCaracXP(caracName, caracXP) {
+ async updateCaracXP(caracName, to) {
if (caracName == 'Taille') {
return;
}
+ let selectedCarac = RdDActor._findCaracByName(this.system.carac, caracName);
+ if (!selectedCarac.derivee) {
+ const from = Number(selectedCarac.xp);
+ await this.update({ [`system.carac.${caracName}.xp`]: to });
+ await ExperienceLog.add(this, XP_TOPIC.XPCARAC, from, to, caracName);
+ }
this.checkCaracXP(caracName);
}
@@ -857,16 +867,19 @@ export class RdDActor extends RdDBaseActor {
let carac = RdDActor._findCaracByName(this.system.carac, caracName);
if (carac) {
carac = duplicate(carac);
- let xp = Number(carac.xp);
- let value = Number(carac.value);
- while (xp >= RdDCarac.getCaracNextXp(value) && xp > 0) {
- xp -= RdDCarac.getCaracNextXp(value);
- value++;
+ const fromXp = Number(carac.xp);
+ const fromValue = Number(carac.value);
+ let toXp = fromXp;
+ let toValue = fromValue;
+ while (toXp >= RdDCarac.getCaracNextXp(toValue) && toXp > 0) {
+ toXp -= RdDCarac.getCaracNextXp(toValue);
+ toValue++;
}
- carac.xp = xp;
- carac.value = value;
+ carac.xp = toXp;
+ carac.value = toValue;
await this.update({ [`system.carac.${caracName}`]: carac });
- this.updateExperienceLog("Carac +", xp, caracName + " passée à " + value);
+ await ExperienceLog.add(this, XP_TOPIC.XPCARAC, fromXp, toXp, caracName);
+ await ExperienceLog.add(this, XP_TOPIC.CARAC, fromValue, toValue, caracName);
}
}
@@ -874,17 +887,20 @@ export class RdDActor extends RdDBaseActor {
async updateCompetenceXPAuto(idOrName) {
let competence = this.getCompetence(idOrName);
if (competence) {
- let xp = Number(competence.system.xp);
- let niveau = Number(competence.system.niveau);
- while (xp >= RdDItemCompetence.getCompetenceNextXp(niveau) && xp > 0) {
- xp -= RdDItemCompetence.getCompetenceNextXp(niveau);
- niveau++;
+ const fromXp = Number(competence.system.xp);
+ const fromNiveau = Number(competence.system.niveau);
+ let toXp = fromXp;
+ let toNiveau = fromNiveau;
+ while (toXp >= RdDItemCompetence.getCompetenceNextXp(toNiveau) && toXp > 0) {
+ toXp -= RdDItemCompetence.getCompetenceNextXp(toNiveau);
+ toNiveau++;
}
await competence.update({
- "system.xp": xp,
- "system.niveau": niveau,
+ "system.xp": toXp,
+ "system.niveau": toNiveau,
});
- this.updateExperienceLog("Compétence +", xp, competence.name + " passée à " + niveau);
+ await ExperienceLog.add(this, XP_TOPIC.XP, fromXp, toXp, competence.name);
+ await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name);
}
}
@@ -893,29 +909,33 @@ export class RdDActor extends RdDBaseActor {
if (!competence) {
return;
}
- const stress = this.system.compteurs.experience.value;
- const niveau = Number(competence.system.niveau);
- const xpSuivant = RdDItemCompetence.getCompetenceNextXp(niveau);
- const xpRequis = xpSuivant - competence.system.xp;
- if (stress <= 0 || niveau >= competence.system.niveau_archetype) {
+ const fromXp = competence.system.xp;
+ const fromXpStress = this.system.compteurs.experience.value;
+ const fromNiveau = Number(competence.system.niveau);
+ const xpSuivant = RdDItemCompetence.getCompetenceNextXp(fromNiveau);
+ const xpRequis = xpSuivant - fromXp;
+ if (fromXpStress <= 0 || fromNiveau >= competence.system.niveau_archetype) {
ui.notifications.info(`La compétence ne peut pas augmenter!
- stress disponible: ${stress}
+ stress disponible: ${fromXpStress}
expérience requise: ${xpRequis}
- niveau : ${niveau}
+ niveau : ${fromNiveau}
archétype : ${competence.system.niveau_archetype}`);
return;
}
- const xpUtilise = Math.max(0, Math.min(stress, xpRequis));
+ const xpUtilise = Math.max(0, Math.min(fromXpStress, xpRequis));
const gainNiveau = (xpUtilise >= xpRequis || xpRequis <= 0) ? 1 : 0;
- const nouveauNiveau = niveau + gainNiveau;
- const nouveauXp = gainNiveau > 0 ? Math.max(competence.system.xp - xpSuivant, 0) : (competence.system.xp + xpUtilise);
+ const toNiveau = fromNiveau + gainNiveau;
+ const newXp = gainNiveau > 0 ? Math.max(fromXp - xpSuivant, 0) : (fromXp + xpUtilise);
await competence.update({
- "system.xp": nouveauXp,
- "system.niveau": nouveauNiveau,
+ "system.xp": newXp,
+ "system.niveau": toNiveau,
});
- const stressTransformeRestant = Math.max(0, stress - xpUtilise);
- await this.update({ "system.compteurs.experience.value": stressTransformeRestant });
- this.updateExperienceLog('Dépense stress', xpUtilise, `Stress en ${competence.name} ${gainNiveau ? "pour passer à " + nouveauNiveau : ""}`);
+ const toXpStress = Math.max(0, fromXpStress - xpUtilise);
+ await this.update({ "system.compteurs.experience.value": toXpStress });
+
+ await ExperienceLog.add(this, XP_TOPIC.TRANSFORM, fromXpStress, toXpStress, `Dépense stress`);
+ await ExperienceLog.add(this, XP_TOPIC.XP, fromXp, newXp, competence.name);
+ await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name);
}
/* -------------------------------------------- */
@@ -941,49 +961,57 @@ export class RdDActor extends RdDBaseActor {
async updateCompetence(idOrName, compValue) {
let competence = this.getCompetence(idOrName);
if (competence) {
- let nouveauNiveau = compValue ?? RdDItemCompetence.getNiveauBase(competence.system.categorie);
- const tronc = RdDItemCompetence.getListTronc(competence.name).filter(it => {
- const comp = this.getCompetence(it);
- const niveauTr = competence ? competence.system.niveau : 0;
- return niveauTr < 0 && niveauTr < nouveauNiveau;
- });
- if (tronc.length > 0) {
- let message = "Vous avez modifié une compétence 'tronc'. Vérifiez que les compétences suivantes évoluent ensemble jusqu'au niveau 0 : ";
- for (let troncName of tronc) {
- message += "
" + troncName;
- }
- ui.notifications.info(message);
+ let toNiveau = compValue ?? RdDItemCompetence.getNiveauBase(competence.system.categorie);
+ this.notifyCompetencesTronc(competence, toNiveau);
+ const fromNiveau = competence.system.niveau;
+ await this.updateEmbeddedDocuments('Item', [{ _id: competence.id, 'system.niveau': toNiveau }]);
+ await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name, true);
+ } else {
+ console.log("Competence not found", idOrName);
+ }
+ }
+
+ notifyCompetencesTronc(competence, toNiveau) {
+ const listTronc = RdDItemCompetence.getListTronc(competence.name).filter(it => {
+ const autreComp = this.getCompetence(it);
+ const niveauTr = autreComp?.system.niveau ?? 0;
+ return niveauTr < 0 && niveauTr < toNiveau;
+ });
+ if (listTronc.length > 0) {
+ ui.notifications.info(
+ "Vous avez modifié une compétence 'tronc'. Vérifiez que les compétences suivantes évoluent ensemble jusqu'au niveau 0 :
"
+ + Misc.join(listTronc, '
'));
+ }
+ }
+
+ /* -------------------------------------------- */
+ async updateCompetenceXP(idOrName, toXp) {
+ let competence = this.getCompetence(idOrName);
+ if (competence) {
+ if (isNaN(toXp) || typeof (toXp) != 'number') toXp = 0;
+ const fromXp = competence.system.xp;
+ this.checkCompetenceXP(idOrName, toXp);
+ await this.updateEmbeddedDocuments('Item', [{ _id: competence.id, 'system.xp': toXp }]);
+ await ExperienceLog.add(this, XP_TOPIC.XP, fromXp, toXp, competence.name, true);
+ if (toXp > fromXp) {
+ RdDUtility.checkThanatosXP(idOrName);
}
- const update = { _id: competence.id, 'system.niveau': nouveauNiveau };
- await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
} else {
console.log("Competence not found", idOrName);
}
}
/* -------------------------------------------- */
- async updateCompetenceXP(idOrName, newXp) {
+ async updateCompetenceXPSort(idOrName, toXpSort) {
let competence = this.getCompetence(idOrName);
if (competence) {
- if (isNaN(newXp) || typeof (newXp) != 'number') newXp = 0;
- this.checkCompetenceXP(idOrName, newXp);
- const update = { _id: competence.id, 'system.xp': newXp };
- await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
- this.updateExperienceLog("XP", newXp, "XP modifié en " + competence.name);
- } else {
- console.log("Competence not found", idOrName);
- }
- RdDUtility.checkThanatosXP(idOrName);
- }
-
- /* -------------------------------------------- */
- async updateCompetenceXPSort(idOrName, compValue) {
- let competence = this.getCompetence(idOrName);
- if (competence) {
- if (isNaN(compValue) || typeof (compValue) != 'number') compValue = 0;
- const update = { _id: competence.id, 'system.xp_sort': compValue };
- await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
- this.updateExperienceLog("XP Sort", compValue, "XP modifié en sort de " + competence.name);
+ if (isNaN(toXpSort) || typeof (toXpSort) != 'number') toXpSort = 0;
+ const fromXpSort = competence.system.xp_sort;
+ await this.updateEmbeddedDocuments('Item', [{ _id: competence.id, 'system.xp_sort': toXpSort }]);
+ await ExperienceLog.add(this, XP_TOPIC.XPSORT, fromXpSort, toXpSort, competence.name, true);
+ if (toXpSort > fromXpSort) {
+ RdDUtility.checkThanatosXP(idOrName);
+ }
} else {
console.log("Competence not found", idOrName);
}
@@ -993,26 +1021,12 @@ export class RdDActor extends RdDBaseActor {
async updateCompetenceArchetype(idOrName, compValue) {
let competence = this.getCompetence(idOrName);
if (competence) {
- compValue = compValue ?? 0;
- const update = { _id: competence.id, 'system.niveau_archetype': compValue };
- await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
+ await this.updateEmbeddedDocuments('Item', [{ _id: competence.id, 'system.niveau_archetype': Math.max(compValue ?? 0, 0) }]);
} else {
console.log("Competence not found", idOrName);
}
}
- /* -------------------------------------------- */
- async updateExperienceLog(modeXP, valeurXP, raisonXP = 'Inconnue') {
- let d = new Date();
- let expLog = duplicate(this.system.experiencelog);
- expLog.push({
- mode: Misc.upperFirst(modeXP), valeur: valeurXP, raison: Misc.upperFirst(raisonXP),
- daterdd: game.system.rdd.calendrier.dateCourante(),
- datereel: `${d.getDate()}/${d.getMonth() + 1}/${d.getFullYear()}`
- });
- await this.update({ [`system.experiencelog`]: expLog });
- }
-
async deleteExperienceLog(from, count) {
if (from >= 0 && count > 0) {
let expLog = duplicate(this.system.experiencelog);
@@ -1021,24 +1035,27 @@ export class RdDActor extends RdDBaseActor {
}
}
-
/* -------------------------------------------- */
- async updateCompteurValue(fieldName, fieldValue, raison = 'Inconnue') {
- await this.update({ [`system.compteurs.${fieldName}.value`]: fieldValue });
- await this.addStressExperienceLog(fieldName, fieldValue, 'forcé: ' + raison);
+ async updateCompteurValue(fieldName, to) {
+ const from = this.system.compteurs[fieldName].value
+ await this.update({ [`system.compteurs.${fieldName}.value`]: to });
+ await this.addStressExperienceLog(fieldName, from, to, fieldName, true);
}
/* -------------------------------------------- */
- async addCompteurValue(fieldName, fieldValue, raison = 'Inconnue') {
- let oldValue = this.system.compteurs[fieldName].value;
- await this.update({ [`system.compteurs.${fieldName}.value`]: Number(oldValue) + Number(fieldValue) });
- await this.addStressExperienceLog(fieldName, fieldValue, raison);
+ async addCompteurValue(fieldName, add, raison) {
+ let from = this.system.compteurs[fieldName].value;
+ const to = Number(from) + Number(add);
+ await this.update({ [`system.compteurs.${fieldName}.value`]: to });
+ await this.addStressExperienceLog(fieldName, from, to, raison);
}
- async addStressExperienceLog(fieldName, fieldValue, raison) {
- switch (fieldName) {
- case 'stress': case 'experience':
- await this.updateExperienceLog(fieldName, fieldValue, raison);
+ async addStressExperienceLog(topic, from, to, raison, manuel) {
+ switch (topic) {
+ case 'stress':
+ return await ExperienceLog.add(this, XP_TOPIC.STRESS, from, to, raison, manuel)
+ case 'experience':
+ return await ExperienceLog.add(this, XP_TOPIC.TRANSFORM, from, to, raison, manuel)
}
}
@@ -1843,14 +1860,14 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async transformerStress() {
- const stress = Number(this.system.compteurs.stress.value);
- if (this.system.sommeil?.insomnie || stress <= 0) {
+ const fromStress = Number(this.system.compteurs.stress.value);
+ if (this.system.sommeil?.insomnie || fromStress <= 0) {
return;
}
const stressRoll = await this._stressRoll(this.getReveActuel());
- const conversion = Math.floor(stress * stressRoll.factor / 100);
+ const conversion = Math.floor(fromStress * stressRoll.factor / 100);
let dissolution = Math.max(0, Number(this.system.compteurs.dissolution.value));
let exaltation = Math.max(0, Number(this.system.compteurs.exaltation.value));
const annule = Math.min(dissolution, exaltation);
@@ -1862,8 +1879,8 @@ export class RdDActor extends RdDBaseActor {
alias: this.name,
selectedCarac: this.system.carac.reve,
rolled: stressRoll,
- stress: stress,
- perte: Math.min(conversion, stress),
+ stress: fromStress,
+ perte: Math.min(conversion, fromStress),
convertis: conversion - perteDissolution,
xp: conversion - perteDissolution + exaltation,
dissolution: dissolution,
@@ -1875,15 +1892,18 @@ export class RdDActor extends RdDBaseActor {
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-transformer-stress.html`, stressRollData)
});
+ const toStress = Math.max(fromStress - stressRollData.perte - 1, 0);
+ const fromXpSress = Number(this.system.compteurs.experience.value);
+ const toXpStress = fromXpSress + Number(stressRollData.xp);
const updates = {
- "system.compteurs.stress.value": Math.max(stress - stressRollData.perte - 1, 0),
- "system.compteurs.experience.value": Number(this.system.compteurs.experience.value) + Number(stressRollData.xp),
+ "system.compteurs.stress.value": toStress,
+ "system.compteurs.experience.value": toXpStress,
"system.compteurs.dissolution.value": dissolution - perteDissolution,
"system.compteurs.exaltation.value": 0
}
await this.update(updates);
-
- this.updateExperienceLog('XP', stressRollData.xp, "Transformation du stress");
+ await ExperienceLog.add(this, XP_TOPIC.STRESS, fromStress, toStress, 'Transformation')
+ await ExperienceLog.add(this, XP_TOPIC.TRANSFORM, fromXpSress, toXpStress, 'Transformation')
}
/* -------------------------------------------- */
@@ -2709,8 +2729,10 @@ export class RdDActor extends RdDBaseActor {
}
rollData.xpSort = RdDItemSigneDraconique.getXpSortSigneDraconique(rollData.rolled.code, rollData.signe);
if (rollData.xpSort > 0) {
- await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': Misc.toInt(compData.system.xp_sort) + rollData.xpSort }]);
- await this.updateExperienceLog("XP Sort", rollData.xpSort, "Signe draconique en " + rollData.competence.name);
+ const fromXp = Number(compData.system.xp_sort);
+ const toXp = fromXp + rollData.xpSort;
+ await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': toXp }]);
+ await ExperienceLog.add(this, XP_TOPIC.XPSORT, fromXp, toXp, `${rollData.competence.name} : signe draconique`);
}
await this.deleteEmbeddedDocuments("Item", [rollData.signe._id]);
await RdDResolutionTable.displayRollData(rollData, this.name, 'chat-resultat-lecture-signedraconique.html');
@@ -2824,11 +2846,12 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async _xpCompetence(xpData) {
if (xpData.competence) {
- const newXp = Misc.toInt(xpData.competence.system.xp) + xpData.xpCompetence;
- let update = { _id: xpData.competence._id, 'system.xp': newXp };
+ const from = Number(xpData.competence.system.xp);
+ const to = from + xpData.xpCompetence;
+ let update = { _id: xpData.competence._id, 'system.xp': to };
await this.updateEmbeddedDocuments('Item', [update]);
xpData.checkComp = await this.checkCompetenceXP(xpData.competence.name, undefined, false);
- this.updateExperienceLog("XP", xpData.xpCompetence, "XP gagné en " + xpData.competence.name);
+ await ExperienceLog.add(this, XP_TOPIC.XP, from, to, xpData.competence.name);
}
}
@@ -2838,10 +2861,12 @@ export class RdDActor extends RdDBaseActor {
let carac = duplicate(this.system.carac);
let selectedCarac = RdDActor._findCaracByName(carac, xpData.caracName);
if (!selectedCarac.derivee) {
- selectedCarac.xp = Misc.toInt(selectedCarac.xp) + xpData.xpCarac;
+ const from = Number(selectedCarac.xp);
+ const to = from + xpData.xpCarac;
+ selectedCarac.xp = to;
await this.update({ "system.carac": carac });
xpData.checkCarac = await this.checkCaracXP(selectedCarac.label, false);
- this.updateExperienceLog("XP", xpData.xpCarac, "XP gagné en " + xpData.caracName);
+ await ExperienceLog.add(this, XP_TOPIC.XPCARAC, from, to, xpData.caracName);
} else {
xpData.caracRepartitionManuelle = true;
}
diff --git a/module/actor/experience-log.js b/module/actor/experience-log.js
new file mode 100644
index 00000000..2d60ed9e
--- /dev/null
+++ b/module/actor/experience-log.js
@@ -0,0 +1,39 @@
+
+export const XP_TOPIC = {
+ XP: { code: 'xp', label: 'xp' },
+ XPSORT: { code: 'xpsort', label: 'xp sort' },
+ NIVEAU: { code: 'niveau', label: 'Niveau' },
+ XPCARAC: { code: 'xpcarac', label: 'xp carac' },
+ CARAC: { code: 'carac', label: 'Carac' },
+ STRESS: { code: 'stress', label: 'Stress' },
+ TRANSFORM: { code: 'xps', label: 'Transformé' },
+}
+
+export class ExperienceLog {
+
+ static async add(actor, topic, from, to, raison, manuel = false) {
+ if (!actor.hasPlayerOwner || !actor.isPersonnage()) {
+ return
+ }
+ if (from == to) {
+ return
+ }
+ const newXpLog = {
+ mode: topic?.code ?? topic,
+ raison: (manuel ? '(manuel) ' : '') + raison,
+ from: from,
+ to: to,
+ valeur: to - from,
+ daterdd: game.system.rdd.calendrier.dateCourante(),
+ datereel: game.system.rdd.calendrier.dateReel().replace('T', ' ')
+ };
+ console.log('ExperienceLog.add', newXpLog)
+ const newExperienceLog = (actor.system.experiencelog ?? []).concat([newXpLog]);
+ await actor.update({ [`system.experiencelog`]: newExperienceLog });
+ }
+
+ static labelTopic(topic) {
+ const xpt = Object.values(XP_TOPIC).find(it => it.code == topic);
+ return xpt?.label ?? xpt?.code ?? topic;
+ }
+}
\ No newline at end of file
diff --git a/module/dialog-chronologie.js b/module/dialog-chronologie.js
index 911942c8..2f698056 100644
--- a/module/dialog-chronologie.js
+++ b/module/dialog-chronologie.js
@@ -25,23 +25,13 @@ export class DialogChronologie extends Dialog {
journalId: game.settings.get(SYSTEM_RDD, LATEST_USED_JOURNAL_ID),
journaux: game.journal.filter(it => it.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)),
timestamp: game.system.rdd.calendrier.timestamp,
- dateReel: DialogChronologie.getCurrentDateTime()
+ dateReel: game.system.rdd.calendrier.dateReel()
};
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-chronologie.html", dialogData);
const dialog = new DialogChronologie(html, dialogData);
dialog.render(true);
}
- static getCurrentDateTime() {
- return new Date().toLocaleString("sv-SE", {
- year: "numeric",
- month: "2-digit",
- day: "2-digit",
- hour: "2-digit",
- minute: "2-digit"
- }).replace(" ", "T");
- }
-
constructor(html, dialogData) {
const options = {
classes: ["DialogChronologie"],
@@ -124,7 +114,7 @@ export class DialogChronologie extends Dialog {
heure: RdDTimestamp.definition(this.html.find("form.rdddialogchrono :input[name='chronologie.heure']").val()),
minute: this.html.find("form.rdddialogchrono :input[name='chronologie.minute']").val(),
},
- dateReel: this.html.find("form.rdddialogchrono :input[name='dateReel']").val().replace('T', ' ')
+ dateReel: this.html.find("form.rdddialogchrono :input[name='dateReel']").val()
}
}
diff --git a/module/rdd-utility.js b/module/rdd-utility.js
index 50e47113..00c05279 100644
--- a/module/rdd-utility.js
+++ b/module/rdd-utility.js
@@ -16,6 +16,7 @@ import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDRaretes } from "./item/raretes.js";
import { RdDEmpoignade } from "./rdd-empoignade.js";
+import { ExperienceLog } from "./actor/experience-log.js";
/* -------------------------------------------- */
// This table starts at 0 -> niveau -10
@@ -136,6 +137,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/actor/blessure.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/maladies-poisons.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/possessions.html',
+ 'systems/foundryvtt-reve-de-dragon/templates/actor/resonances.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.html',
@@ -283,6 +285,9 @@ export class RdDUtility {
Handlebars.registerHelper('uniteQuantite', (itemId, actorId) => RdDUtility.getItem(itemId, actorId)?.getUniteQuantite());
Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field));
Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field));
+
+ Handlebars.registerHelper('experienceLog-topic', topic => ExperienceLog.labelTopic(topic));
+
return loadTemplates(templatePaths);
}
@@ -859,17 +864,13 @@ export class RdDUtility {
}
/* -------------------------------------------- */
- static confirmerSuppressionSubacteur(sheet, subActor, htmlToDelete) {
+ static confirmerSuppressionSubacteur(sheet, subActor, htmlToDelete, onSuppression = ()=>{}) {
RdDConfirm.confirmer({
settingConfirmer: "confirmation-supprimer-lien-acteur",
content: `
Etes vous certain de vouloir supprimer le lien vers ${subActor.name} ?
`, title: 'Confirmer la suppression', buttonLabel: 'Supprimer le lien', - onAction: () => { - console.log('Delete : ', subActor.id); - sheet.actor.removeSubacteur(subActor.id); - RdDUtility.slideOnDelete(sheet, htmlToDelete); - } + onAction: onSuppression }) } diff --git a/module/time/rdd-calendrier.js b/module/time/rdd-calendrier.js index 11f83bbe..68aa1888 100644 --- a/module/time/rdd-calendrier.js +++ b/module/time/rdd-calendrier.js @@ -182,6 +182,16 @@ export class RdDCalendrier extends Application { return this.timestamp.formatDate(); } + dateReel() { + return new Date().toLocaleString("sv-SE", { + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit" + }); + } + isAfterIndexDate(indexDate) { // TODO: standardize return indexDate < this.timestamp.indexDate; diff --git a/module/tmr/effets-rencontres.js b/module/tmr/effets-rencontres.js index e8dee148..ec507768 100644 --- a/module/tmr/effets-rencontres.js +++ b/module/tmr/effets-rencontres.js @@ -1,3 +1,4 @@ +import { ExperienceLog, XP_TOPIC } from "../actor/experience-log.js"; import { ChatUtility } from "../chat-utility.js"; import { Poetique } from "../poetique.js"; import { RdDDice } from "../rdd-dice.js"; @@ -53,9 +54,10 @@ export class EffetsRencontre { static xp_sort_force = async (dialog, context) => { let competence = context.competence; if (competence) { - const xpSort = Misc.toInt(competence.system.xp_sort) + context.rencontre.system.force; - await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': xpSort }]); - await this.updateExperienceLog("XP Sort", xpSort, `Rencontre d'un ${context.rencontre.name} en TMR`); + const fromXpSort = Number(competence.system.xp_sort); + const toXpSort = fromXpSort + context.rencontre.system.force; + await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': toXpSort }]); + await ExperienceLog.add(this, XP_TOPIC.XPSORT, fromXpSort, toXpSort, `${competence.name} - ${context.rencontre.name} en TMR`); } } diff --git a/system.json b/system.json index 642ddf03..ba9bff93 100644 --- a/system.json +++ b/system.json @@ -1,8 +1,8 @@ { "id": "foundryvtt-reve-de-dragon", "title": "Rêve de Dragon", - "version": "10.7.13", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.7.13.zip", + "version": "10.7.14", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.7.14.zip", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v10/system.json", "compatibility": { "minimum": "10", diff --git a/templates/actor-entite-sheet.html b/templates/actor-entite-sheet.html index 5706efde..fe6c1018 100644 --- a/templates/actor-entite-sheet.html +++ b/templates/actor-entite-sheet.html @@ -41,6 +41,9 @@ {{>"systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.html"}} {{>"systems/foundryvtt-reve-de-dragon/templates/actor/comp-possession.html"}} +