Refonte du journal d'expérience
Reprise du journal d'expérience pour: - afficher ancienne/nouvelle valeur - la valeur du changement - si c'est manuel / automatique - identifier les dépenses de stress - identifier les augmentations de compétences - les changements des compteurs
This commit is contained in:
parent
994eaad9a9
commit
92e93cbbea
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
## v10.7.14 - l'expérience de Semolosse
|
## v10.7.14 - l'expérience de Semolosse
|
||||||
- Affichage des personnages accordés sur les fiches des entités
|
- 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, ...)
|
||||||
|
|
||||||
## v10.7.13 - l'armure de Semolosse
|
## v10.7.13 - l'armure de Semolosse
|
||||||
- Fix: en cas d'armure variable, la détérioration diminue le dé d'armure
|
- Fix: en cas d'armure variable, la détérioration diminue le dé d'armure
|
||||||
|
@ -146,6 +146,13 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
const key = Number(li.data("key") ?? -1);
|
const key = Number(li.data("key") ?? -1);
|
||||||
await this.actor.deleteExperienceLog(0, 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.html.find('.encaisser-direct').click(async event => {
|
||||||
this.actor.encaisser();
|
this.actor.encaisser();
|
||||||
})
|
})
|
||||||
|
247
module/actor.js
247
module/actor.js
@ -37,6 +37,7 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
|||||||
import { RdDItemBlessure } from "./item/blessure.js";
|
import { RdDItemBlessure } from "./item/blessure.js";
|
||||||
import { AppAstrologie } from "./sommeil/app-astrologie.js";
|
import { AppAstrologie } from "./sommeil/app-astrologie.js";
|
||||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||||
|
import { ExperienceLog, XP_TOPIC } from "./actor/experience-log.js";
|
||||||
|
|
||||||
const POSSESSION_SANS_DRACONIC = {
|
const POSSESSION_SANS_DRACONIC = {
|
||||||
img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp',
|
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 (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");
|
ui.notifications.warn("Votre FORCE doit être au maximum de TAILLE+4");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (caracName == "reve") {
|
if (caracName == "reve") {
|
||||||
if (caracValue > Misc.toInt(this.system.reve.seuil.value)) {
|
if (to > Misc.toInt(this.system.reve.seuil.value)) {
|
||||||
this.setPointsDeSeuil(caracValue);
|
this.setPointsDeSeuil(to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (caracName == "chance") {
|
if (caracName == "chance") {
|
||||||
if (caracValue > Misc.toInt(this.system.compteurs.chance.value)) {
|
if (to > Misc.toInt(this.system.compteurs.chance.value)) {
|
||||||
this.setPointsDeChance(caracValue);
|
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') {
|
if (caracName == 'Taille') {
|
||||||
return;
|
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);
|
this.checkCaracXP(caracName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -857,16 +867,19 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
let carac = RdDActor._findCaracByName(this.system.carac, caracName);
|
let carac = RdDActor._findCaracByName(this.system.carac, caracName);
|
||||||
if (carac) {
|
if (carac) {
|
||||||
carac = duplicate(carac);
|
carac = duplicate(carac);
|
||||||
let xp = Number(carac.xp);
|
const fromXp = Number(carac.xp);
|
||||||
let value = Number(carac.value);
|
const fromValue = Number(carac.value);
|
||||||
while (xp >= RdDCarac.getCaracNextXp(value) && xp > 0) {
|
let toXp = fromXp;
|
||||||
xp -= RdDCarac.getCaracNextXp(value);
|
let toValue = fromValue;
|
||||||
value++;
|
while (toXp >= RdDCarac.getCaracNextXp(toValue) && toXp > 0) {
|
||||||
|
toXp -= RdDCarac.getCaracNextXp(toValue);
|
||||||
|
toValue++;
|
||||||
}
|
}
|
||||||
carac.xp = xp;
|
carac.xp = toXp;
|
||||||
carac.value = value;
|
carac.value = toValue;
|
||||||
await this.update({ [`system.carac.${caracName}`]: carac });
|
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) {
|
async updateCompetenceXPAuto(idOrName) {
|
||||||
let competence = this.getCompetence(idOrName);
|
let competence = this.getCompetence(idOrName);
|
||||||
if (competence) {
|
if (competence) {
|
||||||
let xp = Number(competence.system.xp);
|
const fromXp = Number(competence.system.xp);
|
||||||
let niveau = Number(competence.system.niveau);
|
const fromNiveau = Number(competence.system.niveau);
|
||||||
while (xp >= RdDItemCompetence.getCompetenceNextXp(niveau) && xp > 0) {
|
let toXp = fromXp;
|
||||||
xp -= RdDItemCompetence.getCompetenceNextXp(niveau);
|
let toNiveau = fromNiveau;
|
||||||
niveau++;
|
while (toXp >= RdDItemCompetence.getCompetenceNextXp(toNiveau) && toXp > 0) {
|
||||||
|
toXp -= RdDItemCompetence.getCompetenceNextXp(toNiveau);
|
||||||
|
toNiveau++;
|
||||||
}
|
}
|
||||||
await competence.update({
|
await competence.update({
|
||||||
"system.xp": xp,
|
"system.xp": toXp,
|
||||||
"system.niveau": niveau,
|
"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) {
|
if (!competence) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const stress = this.system.compteurs.experience.value;
|
const fromXp = competence.system.xp;
|
||||||
const niveau = Number(competence.system.niveau);
|
const fromXpStress = this.system.compteurs.experience.value;
|
||||||
const xpSuivant = RdDItemCompetence.getCompetenceNextXp(niveau);
|
const fromNiveau = Number(competence.system.niveau);
|
||||||
const xpRequis = xpSuivant - competence.system.xp;
|
const xpSuivant = RdDItemCompetence.getCompetenceNextXp(fromNiveau);
|
||||||
if (stress <= 0 || niveau >= competence.system.niveau_archetype) {
|
const xpRequis = xpSuivant - fromXp;
|
||||||
|
if (fromXpStress <= 0 || fromNiveau >= competence.system.niveau_archetype) {
|
||||||
ui.notifications.info(`La compétence ne peut pas augmenter!
|
ui.notifications.info(`La compétence ne peut pas augmenter!
|
||||||
stress disponible: ${stress}
|
stress disponible: ${fromXpStress}
|
||||||
expérience requise: ${xpRequis}
|
expérience requise: ${xpRequis}
|
||||||
niveau : ${niveau}
|
niveau : ${fromNiveau}
|
||||||
archétype : ${competence.system.niveau_archetype}`);
|
archétype : ${competence.system.niveau_archetype}`);
|
||||||
return;
|
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 gainNiveau = (xpUtilise >= xpRequis || xpRequis <= 0) ? 1 : 0;
|
||||||
const nouveauNiveau = niveau + gainNiveau;
|
const toNiveau = fromNiveau + gainNiveau;
|
||||||
const nouveauXp = gainNiveau > 0 ? Math.max(competence.system.xp - xpSuivant, 0) : (competence.system.xp + xpUtilise);
|
const newXp = gainNiveau > 0 ? Math.max(fromXp - xpSuivant, 0) : (fromXp + xpUtilise);
|
||||||
await competence.update({
|
await competence.update({
|
||||||
"system.xp": nouveauXp,
|
"system.xp": newXp,
|
||||||
"system.niveau": nouveauNiveau,
|
"system.niveau": toNiveau,
|
||||||
});
|
});
|
||||||
const stressTransformeRestant = Math.max(0, stress - xpUtilise);
|
const toXpStress = Math.max(0, fromXpStress - xpUtilise);
|
||||||
await this.update({ "system.compteurs.experience.value": stressTransformeRestant });
|
await this.update({ "system.compteurs.experience.value": toXpStress });
|
||||||
this.updateExperienceLog('Dépense stress', xpUtilise, `Stress en ${competence.name} ${gainNiveau ? "pour passer à " + nouveauNiveau : ""}`);
|
|
||||||
|
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) {
|
async updateCompetence(idOrName, compValue) {
|
||||||
let competence = this.getCompetence(idOrName);
|
let competence = this.getCompetence(idOrName);
|
||||||
if (competence) {
|
if (competence) {
|
||||||
let nouveauNiveau = compValue ?? RdDItemCompetence.getNiveauBase(competence.system.categorie);
|
let toNiveau = compValue ?? RdDItemCompetence.getNiveauBase(competence.system.categorie);
|
||||||
const tronc = RdDItemCompetence.getListTronc(competence.name).filter(it => {
|
this.notifyCompetencesTronc(competence, toNiveau);
|
||||||
const comp = this.getCompetence(it);
|
const fromNiveau = competence.system.niveau;
|
||||||
const niveauTr = competence ? competence.system.niveau : 0;
|
await this.updateEmbeddedDocuments('Item', [{ _id: competence.id, 'system.niveau': toNiveau }]);
|
||||||
return niveauTr < 0 && niveauTr < nouveauNiveau;
|
await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name, true);
|
||||||
});
|
|
||||||
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 += "<br>" + troncName;
|
|
||||||
}
|
|
||||||
ui.notifications.info(message);
|
|
||||||
}
|
|
||||||
const update = { _id: competence.id, 'system.niveau': nouveauNiveau };
|
|
||||||
await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
|
|
||||||
} else {
|
} else {
|
||||||
console.log("Competence not found", idOrName);
|
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 : <br>"
|
||||||
|
+ Misc.join(listTronc, '<br>'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async updateCompetenceXP(idOrName, newXp) {
|
async updateCompetenceXP(idOrName, toXp) {
|
||||||
let competence = this.getCompetence(idOrName);
|
let competence = this.getCompetence(idOrName);
|
||||||
if (competence) {
|
if (competence) {
|
||||||
if (isNaN(newXp) || typeof (newXp) != 'number') newXp = 0;
|
if (isNaN(toXp) || typeof (toXp) != 'number') toXp = 0;
|
||||||
this.checkCompetenceXP(idOrName, newXp);
|
const fromXp = competence.system.xp;
|
||||||
const update = { _id: competence.id, 'system.xp': newXp };
|
this.checkCompetenceXP(idOrName, toXp);
|
||||||
await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
|
await this.updateEmbeddedDocuments('Item', [{ _id: competence.id, 'system.xp': toXp }]);
|
||||||
this.updateExperienceLog("XP", newXp, "XP modifié en " + competence.name);
|
await ExperienceLog.add(this, XP_TOPIC.XP, fromXp, toXp, competence.name, true);
|
||||||
} else {
|
if (toXp > fromXp) {
|
||||||
console.log("Competence not found", idOrName);
|
|
||||||
}
|
|
||||||
RdDUtility.checkThanatosXP(idOrName);
|
RdDUtility.checkThanatosXP(idOrName);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
console.log("Competence not found", idOrName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async updateCompetenceXPSort(idOrName, compValue) {
|
async updateCompetenceXPSort(idOrName, toXpSort) {
|
||||||
let competence = this.getCompetence(idOrName);
|
let competence = this.getCompetence(idOrName);
|
||||||
if (competence) {
|
if (competence) {
|
||||||
if (isNaN(compValue) || typeof (compValue) != 'number') compValue = 0;
|
if (isNaN(toXpSort) || typeof (toXpSort) != 'number') toXpSort = 0;
|
||||||
const update = { _id: competence.id, 'system.xp_sort': compValue };
|
const fromXpSort = competence.system.xp_sort;
|
||||||
await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
|
await this.updateEmbeddedDocuments('Item', [{ _id: competence.id, 'system.xp_sort': toXpSort }]);
|
||||||
this.updateExperienceLog("XP Sort", compValue, "XP modifié en sort de " + competence.name);
|
await ExperienceLog.add(this, XP_TOPIC.XPSORT, fromXpSort, toXpSort, competence.name, true);
|
||||||
|
if (toXpSort > fromXpSort) {
|
||||||
|
RdDUtility.checkThanatosXP(idOrName);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("Competence not found", idOrName);
|
console.log("Competence not found", idOrName);
|
||||||
}
|
}
|
||||||
@ -993,26 +1021,12 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
async updateCompetenceArchetype(idOrName, compValue) {
|
async updateCompetenceArchetype(idOrName, compValue) {
|
||||||
let competence = this.getCompetence(idOrName);
|
let competence = this.getCompetence(idOrName);
|
||||||
if (competence) {
|
if (competence) {
|
||||||
compValue = compValue ?? 0;
|
await this.updateEmbeddedDocuments('Item', [{ _id: competence.id, 'system.niveau_archetype': Math.max(compValue ?? 0, 0) }]);
|
||||||
const update = { _id: competence.id, 'system.niveau_archetype': compValue };
|
|
||||||
await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
|
|
||||||
} else {
|
} else {
|
||||||
console.log("Competence not found", idOrName);
|
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) {
|
async deleteExperienceLog(from, count) {
|
||||||
if (from >= 0 && count > 0) {
|
if (from >= 0 && count > 0) {
|
||||||
let expLog = duplicate(this.system.experiencelog);
|
let expLog = duplicate(this.system.experiencelog);
|
||||||
@ -1021,24 +1035,27 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async updateCompteurValue(fieldName, fieldValue, raison = 'Inconnue') {
|
async updateCompteurValue(fieldName, to) {
|
||||||
await this.update({ [`system.compteurs.${fieldName}.value`]: fieldValue });
|
const from = this.system.compteurs[fieldName].value
|
||||||
await this.addStressExperienceLog(fieldName, fieldValue, 'forcé: ' + raison);
|
await this.update({ [`system.compteurs.${fieldName}.value`]: to });
|
||||||
|
await this.addStressExperienceLog(fieldName, from, to, fieldName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async addCompteurValue(fieldName, fieldValue, raison = 'Inconnue') {
|
async addCompteurValue(fieldName, add, raison) {
|
||||||
let oldValue = this.system.compteurs[fieldName].value;
|
let from = this.system.compteurs[fieldName].value;
|
||||||
await this.update({ [`system.compteurs.${fieldName}.value`]: Number(oldValue) + Number(fieldValue) });
|
const to = Number(from) + Number(add);
|
||||||
await this.addStressExperienceLog(fieldName, fieldValue, raison);
|
await this.update({ [`system.compteurs.${fieldName}.value`]: to });
|
||||||
|
await this.addStressExperienceLog(fieldName, from, to, raison);
|
||||||
}
|
}
|
||||||
|
|
||||||
async addStressExperienceLog(fieldName, fieldValue, raison) {
|
async addStressExperienceLog(topic, from, to, raison, manuel) {
|
||||||
switch (fieldName) {
|
switch (topic) {
|
||||||
case 'stress': case 'experience':
|
case 'stress':
|
||||||
await this.updateExperienceLog(fieldName, fieldValue, raison);
|
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() {
|
async transformerStress() {
|
||||||
const stress = Number(this.system.compteurs.stress.value);
|
const fromStress = Number(this.system.compteurs.stress.value);
|
||||||
if (this.system.sommeil?.insomnie || stress <= 0) {
|
if (this.system.sommeil?.insomnie || fromStress <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const stressRoll = await this._stressRoll(this.getReveActuel());
|
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 dissolution = Math.max(0, Number(this.system.compteurs.dissolution.value));
|
||||||
let exaltation = Math.max(0, Number(this.system.compteurs.exaltation.value));
|
let exaltation = Math.max(0, Number(this.system.compteurs.exaltation.value));
|
||||||
const annule = Math.min(dissolution, exaltation);
|
const annule = Math.min(dissolution, exaltation);
|
||||||
@ -1862,8 +1879,8 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
alias: this.name,
|
alias: this.name,
|
||||||
selectedCarac: this.system.carac.reve,
|
selectedCarac: this.system.carac.reve,
|
||||||
rolled: stressRoll,
|
rolled: stressRoll,
|
||||||
stress: stress,
|
stress: fromStress,
|
||||||
perte: Math.min(conversion, stress),
|
perte: Math.min(conversion, fromStress),
|
||||||
convertis: conversion - perteDissolution,
|
convertis: conversion - perteDissolution,
|
||||||
xp: conversion - perteDissolution + exaltation,
|
xp: conversion - perteDissolution + exaltation,
|
||||||
dissolution: dissolution,
|
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)
|
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 = {
|
const updates = {
|
||||||
"system.compteurs.stress.value": Math.max(stress - stressRollData.perte - 1, 0),
|
"system.compteurs.stress.value": toStress,
|
||||||
"system.compteurs.experience.value": Number(this.system.compteurs.experience.value) + Number(stressRollData.xp),
|
"system.compteurs.experience.value": toXpStress,
|
||||||
"system.compteurs.dissolution.value": dissolution - perteDissolution,
|
"system.compteurs.dissolution.value": dissolution - perteDissolution,
|
||||||
"system.compteurs.exaltation.value": 0
|
"system.compteurs.exaltation.value": 0
|
||||||
}
|
}
|
||||||
await this.update(updates);
|
await this.update(updates);
|
||||||
|
await ExperienceLog.add(this, XP_TOPIC.STRESS, fromStress, toStress, 'Transformation')
|
||||||
this.updateExperienceLog('XP', stressRollData.xp, "Transformation du stress");
|
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);
|
rollData.xpSort = RdDItemSigneDraconique.getXpSortSigneDraconique(rollData.rolled.code, rollData.signe);
|
||||||
if (rollData.xpSort > 0) {
|
if (rollData.xpSort > 0) {
|
||||||
await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': Misc.toInt(compData.system.xp_sort) + rollData.xpSort }]);
|
const fromXp = Number(compData.system.xp_sort);
|
||||||
await this.updateExperienceLog("XP Sort", rollData.xpSort, "Signe draconique en " + rollData.competence.name);
|
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 this.deleteEmbeddedDocuments("Item", [rollData.signe._id]);
|
||||||
await RdDResolutionTable.displayRollData(rollData, this.name, 'chat-resultat-lecture-signedraconique.html');
|
await RdDResolutionTable.displayRollData(rollData, this.name, 'chat-resultat-lecture-signedraconique.html');
|
||||||
@ -2824,11 +2846,12 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _xpCompetence(xpData) {
|
async _xpCompetence(xpData) {
|
||||||
if (xpData.competence) {
|
if (xpData.competence) {
|
||||||
const newXp = Misc.toInt(xpData.competence.system.xp) + xpData.xpCompetence;
|
const from = Number(xpData.competence.system.xp);
|
||||||
let update = { _id: xpData.competence._id, 'system.xp': newXp };
|
const to = from + xpData.xpCompetence;
|
||||||
|
let update = { _id: xpData.competence._id, 'system.xp': to };
|
||||||
await this.updateEmbeddedDocuments('Item', [update]);
|
await this.updateEmbeddedDocuments('Item', [update]);
|
||||||
xpData.checkComp = await this.checkCompetenceXP(xpData.competence.name, undefined, false);
|
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 carac = duplicate(this.system.carac);
|
||||||
let selectedCarac = RdDActor._findCaracByName(carac, xpData.caracName);
|
let selectedCarac = RdDActor._findCaracByName(carac, xpData.caracName);
|
||||||
if (!selectedCarac.derivee) {
|
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 });
|
await this.update({ "system.carac": carac });
|
||||||
xpData.checkCarac = await this.checkCaracXP(selectedCarac.label, false);
|
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 {
|
} else {
|
||||||
xpData.caracRepartitionManuelle = true;
|
xpData.caracRepartitionManuelle = true;
|
||||||
}
|
}
|
||||||
|
39
module/actor/experience-log.js
Normal file
39
module/actor/experience-log.js
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,7 @@ import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
|||||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||||
import { RdDRaretes } from "./item/raretes.js";
|
import { RdDRaretes } from "./item/raretes.js";
|
||||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||||
|
import { ExperienceLog } from "./actor/experience-log.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// This table starts at 0 -> niveau -10
|
// This table starts at 0 -> niveau -10
|
||||||
@ -284,6 +285,9 @@ export class RdDUtility {
|
|||||||
Handlebars.registerHelper('uniteQuantite', (itemId, actorId) => RdDUtility.getItem(itemId, actorId)?.getUniteQuantite());
|
Handlebars.registerHelper('uniteQuantite', (itemId, actorId) => RdDUtility.getItem(itemId, actorId)?.getUniteQuantite());
|
||||||
Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field));
|
Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field));
|
||||||
Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field));
|
Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field));
|
||||||
|
|
||||||
|
Handlebars.registerHelper('experienceLog-topic', topic => ExperienceLog.labelTopic(topic));
|
||||||
|
|
||||||
return loadTemplates(templatePaths);
|
return loadTemplates(templatePaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +183,16 @@ export class RdDCalendrier extends Application {
|
|||||||
return this.timestamp.formatDate();
|
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) {
|
isAfterIndexDate(indexDate) {
|
||||||
// TODO: standardize
|
// TODO: standardize
|
||||||
return indexDate < this.timestamp.indexDate;
|
return indexDate < this.timestamp.indexDate;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { ExperienceLog, XP_TOPIC } from "../actor/experience-log.js";
|
||||||
import { ChatUtility } from "../chat-utility.js";
|
import { ChatUtility } from "../chat-utility.js";
|
||||||
import { Poetique } from "../poetique.js";
|
import { Poetique } from "../poetique.js";
|
||||||
import { RdDDice } from "../rdd-dice.js";
|
import { RdDDice } from "../rdd-dice.js";
|
||||||
@ -53,9 +54,10 @@ export class EffetsRencontre {
|
|||||||
static xp_sort_force = async (dialog, context) => {
|
static xp_sort_force = async (dialog, context) => {
|
||||||
let competence = context.competence;
|
let competence = context.competence;
|
||||||
if (competence) {
|
if (competence) {
|
||||||
const xpSort = Misc.toInt(competence.system.xp_sort) + context.rencontre.system.force;
|
const fromXpSort = Number(competence.system.xp_sort);
|
||||||
await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': xpSort }]);
|
const toXpSort = fromXpSort + context.rencontre.system.force;
|
||||||
await this.updateExperienceLog("XP Sort", xpSort, `Rencontre d'un ${context.rencontre.name} en TMR`);
|
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`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<li class="item flexrow">
|
<li class="item flexrow">
|
||||||
<label class="derivee-label" for="system.compteurs.experience.value">Stress transformé</label>
|
<label class="derivee-label" for="system.compteurs.experience.value">Stress transformé</label>
|
||||||
{{#if options.vueDetaillee}}
|
{{#if options.vueDetaillee}}
|
||||||
<input type="number" name="system.compteurs.experience.value" value="{{system.compteurs.experience.value}}" data-dtype="number" size="3"/>
|
<input class="derivee-value" type="number" name="system.compteurs.experience.value" value="{{system.compteurs.experience.value}}" data-dtype="number" size="3"/>
|
||||||
{{else}}
|
{{else}}
|
||||||
<label name="system.compteurs.experience.value">{{system.compteurs.experience.value}}</label>
|
<label name="system.compteurs.experience.value">{{system.compteurs.experience.value}}</label>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
<h3>Journal d'Experience</h3>
|
<h3>Journal d'Experience</h3>
|
||||||
<div class="form-group large-editor">
|
<div class="form-group large-editor">
|
||||||
<ul class="item-list alterne-list">
|
<ul class="item-list alterne-list">
|
||||||
{{#each system.experiencelog as |xp key|}}
|
{{#each system.experiencelog as |xplog key|}}
|
||||||
<li class="experiencelog flexrow list-item" data-key="{{key}}">
|
<li class="experiencelog flexrow list-item" data-key="{{key}}">
|
||||||
<label class="flex-grow">{{xp.valeur}} {{xp.raison}}</label>
|
<label class="flex-shrink">{{xplog.valeur}} {{experienceLog-topic xplog.mode}} </label>
|
||||||
<label class="flex-shrink">{{xp.mode}}</label>
|
{{#if (or xplog.from xplog.to)}}
|
||||||
<label class="flex-shrink">{{xp.daterdd}}</label>
|
<label class="flex-grow">{{xplog.raison}}: de {{xplog.from}} à {{xplog.to}}</label>
|
||||||
<label class="flex-shrink">{{xp.datereel}}</label>
|
{{else}}
|
||||||
|
<label class="flex-grow">{{xplog.raison}}</label>
|
||||||
|
{{/if}}
|
||||||
|
<label class="flex-shrink">{{xplog.daterdd}}</label>
|
||||||
|
<label class="flex-shrink">{{xplog.datereel}}</label>
|
||||||
{{#if @root.options.isGM}}
|
{{#if @root.options.isGM}}
|
||||||
<span>
|
<span class="flex-shrink">
|
||||||
<a class="experiencelog-delete" title="Supprimer">
|
<a class="experiencelog-delete" title="Supprimer">
|
||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</a>
|
</a>
|
||||||
|
Loading…
Reference in New Issue
Block a user