diff --git a/module/actor-creature-sheet.js b/module/actor-creature-sheet.js
index e3ad06fd..e0429e53 100644
--- a/module/actor-creature-sheet.js
+++ b/module/actor-creature-sheet.js
@@ -7,6 +7,7 @@
import { HtmlUtility } from "./html-utility.js";
import { RdDUtility } from "./rdd-utility.js";
import { RdDActorSheet } from "./actor-sheet.js";
+import { RdDCarac } from "./rdd-carac.js";
/* -------------------------------------------- */
export class RdDActorCreatureSheet extends RdDActorSheet {
@@ -25,37 +26,21 @@ export class RdDActorCreatureSheet extends RdDActorSheet {
/* -------------------------------------------- */
- getData() {
- let formData = super.getDData();
+ async getData() {
+ let formData = await super.getData();
console.log("Creature : ", formData);
-
- formData.itemsByType = {};
- for (const item of formData.items) {
- let list = formData.itemsByType[item.type];
- if (!list) {
- list = [];
- formData.itemsByType[item.type] = list;
- }
- list.push(item);
+ formData.calc = {
+ caracTotal: RdDCarac.computeTotal(formData.data.carac),
+ resumeBlessures: this.actor.computeResumeBlessure(formData.data.blessures),
+ encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
}
-
- // Compute current carac sum
- let sum = 0;
- Object.values(formData.data.carac).forEach(carac => { if (!carac.derivee) { sum += parseInt(carac.value) } });
- formData.data.caracSum = sum;
-
- formData.data.carac.taille.isTaille = true; // To avoid button link;
- formData.data.blessures.resume = this.actor.computeResumeBlessure(formData.data.blessures);
-
- formData.data.isGM = game.user.isGM;
+ formData.calc.surEncombrementMessage = (formData.data.compteurs.surenc.value < 0) ? "Sur-Encombrement!" : "";
+ formData.options.isGM = game.user.isGM;
formData.data.competencecreature = formData.itemsByType["competencecreature"];
- this.actor.computeEncombrementTotalEtMalusArmure();
RdDUtility.filterItemsPerTypeForSheet(formData);
RdDUtility.buildArbreDeConteneur(this, formData);
- formData.data.encTotal = this.actor.encTotal;
- formData.data.isGM = game.user.isGM;
console.log("Creature : ", this.objetVersConteneur, formData);
diff --git a/module/actor-entite-sheet.js b/module/actor-entite-sheet.js
index 407b6b40..1b7afc01 100644
--- a/module/actor-entite-sheet.js
+++ b/module/actor-entite-sheet.js
@@ -4,6 +4,7 @@
*/
import { HtmlUtility } from "./html-utility.js";
+import { Misc } from "./misc.js";
/* -------------------------------------------- */
export class RdDActorEntiteSheet extends ActorSheet {
@@ -29,22 +30,16 @@ export class RdDActorEntiteSheet extends ActorSheet {
}
/* -------------------------------------------- */
- getData() {
+ async getData() {
let formData = super.getData();
- formData.itemsByType = {};
- for (const item of formData.items) {
- let list = formData.itemsByType[item.type];
- if (!list) {
- list = [];
- formData.itemsByType[item.type] = list;
- }
- list.push(item);
- }
-
+ formData.itemsByType = Misc.classify(formData.items);
+
+ formData.options.isGM = game.user.isGM;
+
formData.data.carac.taille.isTaille = true; // To avoid button link;
formData.data.competencecreature = formData.itemsByType["competencecreature"];
- formData.data.isGM = game.user.isGM;
+
return formData;
}
diff --git a/module/actor-sheet.js b/module/actor-sheet.js
index 6b725a9a..6abc9c39 100644
--- a/module/actor-sheet.js
+++ b/module/actor-sheet.js
@@ -10,6 +10,7 @@ import { RdDItemCompetence } from "./item-competence.js";
import { RdDBonus } from "./rdd-bonus.js";
import { Misc } from "./misc.js";
import { RdDCombatManager } from "./rdd-combat.js";
+import { RdDCarac } from "./rdd-carac.js";
/* -------------------------------------------- */
export class RdDActorSheet extends ActorSheet {
@@ -31,51 +32,66 @@ export class RdDActorSheet extends ActorSheet {
}
/* -------------------------------------------- */
- getData() {
+ async getData() {
let formData = super.getData();
+ // -------------- version 0.7.9
+ // let formData = {
+ // cssClass: this.entity.owner ? "editable" : "locked",
+ // editable: this.isEditable,
+ // entity: duplicate(this.entity.data),
+ // limited: this.entity.limited,
+ // options: this.options,
+ // owner: this.entity.owner,
+ // title: this.title
+ // }
+ // // Entity data
+ // formData.actor = formData.entity;
+ // formData.data = formData.entity.data;
- if (formData.actor.type == 'creature' || formData.actor.type == 'humanoide') return formData; // Shortcut
-
- formData.data.editCaracComp = this.options.editCaracComp;
- formData.data.showCompNiveauBase = this.options.showCompNiveauBase;
- formData.data.montrerArchetype = this.options.montrerArchetype;
+ // // Owned items
+ // formData.items = formData.actor.items;
+ // formData.items.sort((a, b) => (a.sort || 0) - (b.sort || 0));
formData.itemsByType = Misc.classify(formData.items);
+ RdDUtility.filterItemsPerTypeForSheet(formData);
- // Competence per category
- formData.data.comptageArchetype = RdDUtility.getLimitesArchetypes();
- formData.data.competenceXPTotal = 0;
- formData.competenceByCategory = Misc.classify(
- formData.itemsByType.competence,
- item => item.data.categorie,
- item => {
- let archetypeKey = (item.data.niveau_archetype < 0) ? 0 : item.data.niveau_archetype;
- if (formData.data.comptageArchetype[archetypeKey] == undefined) {
- formData.data.comptageArchetype[archetypeKey] = { "niveau": archetypeKey, "nombreMax": 0, "nombre": 0 };
- }
- formData.data.comptageArchetype[archetypeKey].nombre = (formData.data.comptageArchetype[archetypeKey]?.nombre ?? 0) + 1; //Comptage archetype
- item.data.xpNext = RdDItemCompetence.getCompetenceNextXp(item.data.niveau);
- item.data.isLevelUp = item.data.xp >= item.data.xpNext; // Flag de niveau à MAJ
- //this.actor.checkCompetenceXP(item.name); // Petite vérification experience
- item.data.showCompetence = !formData.data.showCompNiveauBase || (Number(item.data.niveau) != Number(RdDItemCompetence.getLevelCategory(item.data.categorie)));
- // Ignorer les compétences 'troncs' à ce stade
- formData.data.competenceXPTotal += RdDItemCompetence.computeCompetenceXPCost(item);
- return item;
- });
- formData.data.competenceXPTotal -= RdDItemCompetence.computeEconomieCompetenceTroncXP(formData.itemsByType.competence);
+ formData.options.isGM = game.user.isGM;
+
+ // la taille est la taille: on ne peut pas l'utiliser pour un jet
+ formData.data.carac.taille.isTaille = true;
+
+ if (this.actor.data.type == 'creature') return formData; // Shortcut
+
+ // toujours avoir une liste d'armes (pour mettre esquive et corps à corps)
+ formData.itemsByType.arme = formData.itemsByType.arme ?? [];
+
+ formData.competenceByCategory = Misc.classify(formData.data.competences, item => item.data.categorie);
+
+ formData.calc = {
+ comptageArchetype: RdDItemCompetence.computeResumeArchetype(formData.data.competences),
+ competenceXPTotal: RdDItemCompetence.computeTotalXP(formData.data.competences),
+ caracTotal: RdDCarac.computeTotal(formData.data.carac, formData.data.beaute),
+ // Mise à jour de l'encombrement total et du prix de l'équipement
+ encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
+ prixTotalEquipement: await this.actor.computePrixTotalEquipement(),
+ surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
+ fatigue: {
+ malus: RdDUtility.calculMalusFatigue(formData.data.sante.fatigue.value, formData.data.sante.endurance.max),
+ html: "
" + RdDUtility.makeHTMLfatigueMatrix(formData.data.sante.fatigue.value, formData.data.sante.endurance.max).html() + "
"
+ },
+ resumeBlessures: this.actor.computeResumeBlessure(formData.data.blessures),
+ };
+ formData.calc.surEncombrementMessage = (formData.data.compteurs.surenc.value < 0) ? "Sur-Encombrement!" : "";
+
+ formData.data.competences.forEach(item => {
+ item.visible = !this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(item);
+ RdDItemCompetence.levelUp(item);
+ });
+
+ Object.values(formData.data.carac).forEach(c => {
+ RdDCarac.levelUp(c);
+ });
- // Compute current carac sum
- let sum = 0;
- for (let caracName in formData.data.carac) {
- let currentCarac = formData.data.carac[caracName];
- if (!currentCarac.derivee) {
- sum += parseInt(currentCarac.value);
- }
- currentCarac.xpNext = RdDUtility.getCaracNextXp(currentCarac.value);
- currentCarac.isLevelUp = (currentCarac.xp >= currentCarac.xpNext);
- }
- sum += (formData.data.beaute >= 0) ? (formData.data.beaute - 10) : 0;
- formData.data.caracSum = sum;
// Force empty arme, at least for Esquive
if (formData.itemsByType.arme == undefined) formData.itemsByType.arme = [];
@@ -112,14 +128,9 @@ export class RdDActorSheet extends ActorSheet {
formData.data.blessures.resume = this.actor.computeResumeBlessure(formData.data.blessures);
// Mise à jour de l'encombrement total et du prix de l'équipement
- this.actor.computeEncombrementTotalEtMalusArmure();
- this.actor.computePrixTotalEquipement();
// Common data
formData.data.competenceByCategory = formData.competenceByCategory;
- formData.data.encTotal = this.actor.encTotal;
- formData.data.prixTotalEquipement = this.actor.prixTotalEquipement;
- formData.data.surprise = RdDBonus.find(this.actor.getSurprise(false)).descr;
formData.data.isGM = game.user.isGM;
formData.ajustementsConditions = CONFIG.RDD.ajustementsConditions;
formData.difficultesLibres = CONFIG.RDD.difficultesLibres;
@@ -135,13 +146,16 @@ export class RdDActorSheet extends ActorSheet {
formData.data.rencontres = duplicate(formData.data.reve.rencontre.list);
formData.data.caseSpeciales = formData.itemsByType['casetmr'];
RdDUtility.buildArbreDeConteneur(this, formData);
- formData.data.surEncombrementMessage = (formData.data.compteurs.surenc.value < 0) ? "Sur-Encombrement!" : "";
formData.data.vehiculesList = this.actor.buildVehiculesList();
formData.data.monturesList = this.actor.buildMonturesList();
formData.data.suivantsList = this.actor.buildSuivantsList();
return formData;
}
+ isCompetenceAffichable(competence) {
+ return !this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(competence);
+ }
+
/* -------------------------------------------- */
async _onDrop(event) {
let toSuper = await RdDUtility.processItemDropEvent(this, event);
diff --git a/module/actor-vehicule-sheet.js b/module/actor-vehicule-sheet.js
index be5f4f19..e9cfc46e 100644
--- a/module/actor-vehicule-sheet.js
+++ b/module/actor-vehicule-sheet.js
@@ -33,7 +33,7 @@ export class RdDActorVehiculeSheet extends ActorSheet {
}
/* -------------------------------------------- */
- getData() {
+ async getData() {
let formData = super.getData();
formData.itemsByType = Misc.classify(formData.items);
@@ -41,9 +41,12 @@ export class RdDActorVehiculeSheet extends ActorSheet {
RdDUtility.filterItemsPerTypeForSheet(formData);
RdDUtility.buildArbreDeConteneur(this, formData);
- this.actor.computeEncombrementTotalEtMalusArmure();
- formData.data.isGM = game.user.isGM;
- formData.data.surEncombrementMessage = (this.encTotal > formData.capacite_encombrement) ? "Sur-Encombrement!" : "";
+ formData.options.isGM = game.user.isGM;
+
+ formData.calc ={
+ encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
+ }
+ formData.calc.surEncombrementMessage = formData.calc.encTotal > formData.data.capacite_encombrement ? "Sur-Encombrement!" : "",
console.log("DATA", formData);
diff --git a/module/actor.js b/module/actor.js
index ce68b6a4..d7ac680c 100644
--- a/module/actor.js
+++ b/module/actor.js
@@ -25,6 +25,7 @@ import { TMRRencontres } from "./tmr-rencontres.js";
import { Poetique } from "./poetique.js";
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
import { Draconique } from "./tmr/draconique.js";
+import { RdDCarac } from "./rdd-carac.js";
/* -------------------------------------------- */
@@ -139,7 +140,7 @@ export class RdDActor extends Actor {
*/
async _prepareCharacterData(actorData) {
// Initialize empty items
- RdDUtility.computeCarac(actorData.data);
+ RdDCarac.computeCarac(actorData.data);
this.computeEncombrementTotalEtMalusArmure();
this.computePrixTotalEquipement();
this.computeEtatGeneral();
@@ -736,7 +737,7 @@ export class RdDActor extends Actor {
let comp = this.getCompetence(compName);
if (comp) {
let troncList = RdDItemCompetence.isTronc(compName);
- let nouveauNiveau = compValue ?? RdDItemCompetence.getLevelCategory(comp.data.categorie);
+ let nouveauNiveau = compValue ?? RdDItemCompetence.getNiveauBase(comp.data.categorie);
if (troncList) {
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 troncList) {
@@ -1015,6 +1016,7 @@ export class RdDActor extends Actor {
malusArmureData.value = newMalusArmure;
await this.update({ "data.attributs.malusarmure": malusArmureData });
}
+ return this.encTotal;
}
/* -------------------------------------------- */
@@ -1032,6 +1034,7 @@ export class RdDActor extends Actor {
}
// Mise à jour valeur totale de l'équipement
this.prixTotalEquipement = prixTotalEquipement;
+ return prixTotalEquipement;
}
/* -------------------------------------------- */
@@ -1310,7 +1313,7 @@ export class RdDActor extends Actor {
if (this.isEntiteCauchemar()) {
return 0;
}
- return RdDUtility.calculSConst(this.data.data.carac.constitution.value);
+ return RdDCarac.calculSConst(this.data.data.carac.constitution.value);
}
/* -------------------------------------------- */
@@ -1716,7 +1719,7 @@ export class RdDActor extends Actor {
async checkCaracXP(caracName) {
let carac = this.data.data.carac[caracName];
if (carac && carac.xp > 0) {
- let xpNeeded = RdDUtility.getCaracNextXp(carac.value + 1);
+ let xpNeeded = RdDCarac.getCaracNextXp(carac.value + 1);
if (carac.xp >= xpNeeded) {
carac = duplicate(carac);
carac.value = Number(carac.value) + 1;
diff --git a/module/item-competence.js b/module/item-competence.js
index 2820001a..2f947f17 100644
--- a/module/item-competence.js
+++ b/module/item-competence.js
@@ -1,9 +1,23 @@
-
const competenceTroncs = [["Esquive", "Dague", "Corps à corps"],
["Epée à 1 main", "Epée à 2 mains", "Hache à 1 main", "Hache à 2 mains", "Lance", "Masse à 1 main", "Masse à 2 mains"]];
const competence_xp_par_niveau = [5, 5, 5, 10, 10, 10, 10, 15, 15, 15, 15, 20, 20, 20, 20, 30, 30, 40, 40, 60, 60, 100, 100, 100, 100, 100, 100, 100, 100, 100];
const competence_niveau_max = competence_xp_par_niveau.length - 10;
+/* -------------------------------------------- */
+const limitesArchetypes = [
+ { "niveau": 0, "nombreMax": 100, "nombre": 0 },
+ { "niveau": 1, "nombreMax": 10, "nombre": 0 },
+ { "niveau": 2, "nombreMax": 9, "nombre": 0 },
+ { "niveau": 3, "nombreMax": 8, "nombre": 0 },
+ { "niveau": 4, "nombreMax": 7, "nombre": 0 },
+ { "niveau": 5, "nombreMax": 6, "nombre": 0 },
+ { "niveau": 6, "nombreMax": 5, "nombre": 0 },
+ { "niveau": 7, "nombreMax": 4, "nombre": 0 },
+ { "niveau": 8, "nombreMax": 3, "nombre": 0 },
+ { "niveau": 9, "nombreMax": 2, "nombre": 0 },
+ { "niveau": 10, "nombreMax": 1, "nombre": 0 },
+ { "niveau": 11, "nombreMax": 1, "nombre": 0 }
+];
/* -------------------------------------------- */
const categorieCompetences = {
@@ -35,10 +49,10 @@ export class RdDItemCompetence extends Item {
static getCategorieCompetences() {
return categorieCompetences;
}
- static getLevelCategory(category) {
+ static getNiveauBase(category) {
return categorieCompetences[category].level;
}
- static getLabelCategory(category) {
+ static getLabelCategorie(category) {
return categorieCompetences[category].label;
}
@@ -77,6 +91,44 @@ export class RdDItemCompetence extends Item {
}
return false;
}
+
+ /* -------------------------------------------- */
+ static computeTotalXP(competences) {
+ const total = competences.map(c => RdDItemCompetence.computeXP(c))
+ .reduce((a, b) => a + b, 0);
+ const economieTronc = RdDItemCompetence.computeEconomieXPTronc(competences);
+ return total - economieTronc;
+ }
+
+ /* -------------------------------------------- */
+ static computeXP(competence) {
+ const factor = competence.name.includes('Thanatos') ? 2 : 1; // Thanatos compte double !
+ const xpNiveau = RdDItemCompetence.computeDeltaXP(competence.data.base, competence.data.niveau ?? competence.data.base);
+ const xp = competence.data.xp ?? 0;
+ const xpSort = competence.data.xp_sort ?? 0;
+ return factor * (xpNiveau + xp) + xpSort;
+ }
+
+ /* -------------------------------------------- */
+ static computeEconomieXPTronc(competences) {
+ return competenceTroncs.map(
+ list => list.map(name => RdDItemCompetence.findCompetence(competences, name))
+ // calcul du coût xp jusqu'au niveau 0 maximum
+ .map(it => RdDItemCompetence.computeDeltaXP(it?.data.base ?? -11, Math.min(it?.data.niveau ?? -11, 0)))
+ .sort((a, b) => b - a) // tri descendant
+ .splice(0, 1) // ignorer le coût xp le plus élevé
+ .reduce((a, b) => a + b, 0)
+ ).reduce((a, b) => a + b, 0);
+ }
+
+ /* -------------------------------------------- */
+ static computeDeltaXP(from, to) {
+ RdDItemCompetence._valideNiveau(from);
+ RdDItemCompetence._valideNiveau(to);
+ return competence_xp_cumul[to] - competence_xp_cumul[from];
+ }
+
+
/* -------------------------------------------- */
static computeCompetenceXPCost(competence) {
let xp = RdDItemCompetence.getDeltaXp(competence.data.base, competence.data.niveau ?? competence.data.base);
@@ -100,6 +152,20 @@ export class RdDItemCompetence extends Item {
return economie;
}
+ static levelUp(item) {
+ item.data.xpNext = RdDItemCompetence.getCompetenceNextXp(item.data.niveau);
+ item.data.isLevelUp = item.data.xp >= item.data.xpNext;
+ }
+
+ static isVisible(item) {
+ return Number(item.data.niveau) != RdDItemCompetence.getNiveauBase(item.data.categorie);
+ }
+
+ /* -------------------------------------------- */
+ static isNiveauBase(item) {
+ return Number(item.data.niveau) == RdDItemCompetence.getNiveauBase(item.data.categorie);
+ }
+
/* -------------------------------------------- */
static findCompetence(list, name) {
name = name.toLowerCase();
@@ -127,8 +193,24 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static _valideNiveau(niveau){
if (niveau < -11 || niveau > competence_niveau_max) {
- console.warn("Niveau en dehors des niveaux de compétences: [-11, " + competence_niveau_max + "]", niveau)
+ console.warn(`Niveau ${niveau} en dehors des niveaux de compétences: [-11, ${competence_niveau_max} ]`);
}
}
+
+ /* -------------------------------------------- */
+ static computeResumeArchetype(competences) {
+ const archetype = RdDItemCompetence.getLimitesArchetypes();
+ competences.forEach(item => {
+ let niveau = (item.data.niveau_archetype < 0) ? 0 : item.data.niveau_archetype;
+ archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 };
+ archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1;
+ });
+ return archetype;
+ }
+ /* -------------------------------------------- */
+ static getLimitesArchetypes() {
+ return duplicate(limitesArchetypes);
+ }
+
}
\ No newline at end of file
diff --git a/module/item-sheet.js b/module/item-sheet.js
index 904e4f6e..1808ec81 100644
--- a/module/item-sheet.js
+++ b/module/item-sheet.js
@@ -111,7 +111,7 @@ export class RdDItemSheet extends ItemSheet {
async _onClickSelectCategorie(event) {
event.preventDefault();
- let level = RdDItemCompetence.getLevelCategory(event.currentTarget.value);
+ let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
this.object.data.data.base = level;
$("#base").val( level );
}
diff --git a/module/rdd-carac.js b/module/rdd-carac.js
index 337212b2..516b4f9f 100644
--- a/module/rdd-carac.js
+++ b/module/rdd-carac.js
@@ -1,4 +1,41 @@
import { Grammar } from "./grammar.js";
+import { RdDUtility } from "./rdd-utility.js";
+
+const tableCaracDerivee = {
+ // xp: coût pour passer du niveau inférieur à ce niveau
+ 1: { xp: 3, poids: "moins de 1kg", plusdom: -5, sconst: 0.5, sust: 0.1 },
+ 2: { xp: 3, poids: "1-5", plusdom: -4, sconst: 0.5, sust: 0.3 },
+ 3: { xp: 4, poids: "6-10", plusdom: -3, sconst: 1, sust: 0.5, beaute: 'hideux' },
+ 4: { xp: 4, poids: "11-20", plusdom: -3, sconst: 1, sust: 1, beaute: 'repoussant' },
+ 5: { xp: 5, poids: "21-30", plusdom: -2, sconst: 1, sust: 1, beaute: 'franchement très laid' },
+ 6: { xp: 5, poids: "31-40", plusdom: -1, sconst: 2, sust: 2, beaute: 'laid' },
+ 7: { xp: 6, poids: "41-50", plusdom: -1, sconst: 2, sust: 2, beaute: 'très désavantagé' },
+ 8: { xp: 6, poids: "51-60", plusdom: 0, sconst: 2, sust: 2, beaute: 'désavantagé' },
+ 9: { xp: 7, poids: "61-65", plusdom: 0, sconst: 3, sust: 2, beaute: 'pas terrible' },
+ 10: { xp: 7, poids: "66-70", plusdom: 0, sconst: 3, sust: 3, beaute: 'commun' },
+ 11: { xp: 8, poids: "71-75", plusdom: 0, sconst: 3, sust: 3, beaute: 'pas mal' },
+ 12: { xp: 8, poids: "76-80", plusdom: +1, sconst: 4, sust: 3, beaute: 'avantagé' },
+ 13: { xp: 9, poids: "81-90", plusdom: +1, sconst: 4, sust: 3, beaute: 'mignon' },
+ 14: { xp: 9, poids: "91-100", plusdom: +2, sconst: 4, sust: 4, beaute: 'beau' },
+ 15: { xp: 10, poids: "101-110", plusdom: +2, sconst: 5, sust: 4, beaute: 'très beau' },
+ 16: { xp: 20, poids: "111-120", plusdom: +3, sconst: 5, sust: 4, beaute: 'éblouissant' },
+ 17: { xp: 30, poids: "121-131", plusdom: +3, sconst: 5, sust: 5 },
+ 18: { xp: 40, poids: "131-141", plusdom: +4, sconst: 6, sust: 5 },
+ 19: { xp: 50, poids: "141-150", plusdom: +4, sconst: 6, sust: 5 },
+ 20: { xp: 60, poids: "151-160", plusdom: +4, sconst: 6, sust: 6 },
+ 21: { xp: 70, poids: "161-180", plusdom: +5, sconst: 7, sust: 6 },
+ 22: { xp: 80, poids: "181-200", plusdom: +5, sconst: 7, sust: 7 },
+ 23: { xp: 90, poids: "201-300", plusdom: +6, sconst: 7, sust: 8 },
+ 24: { xp: 100, poids: "301-400", plusdom: +6, sconst: 8, sust: 9 },
+ 25: { xp: 110, poids: "401-500", plusdom: +7, sconst: 8, sust: 10 },
+ 26: { xp: 120, poids: "501-600", plusdom: +7, sconst: 8, sust: 11 },
+ 27: { xp: 130, poids: "601-700", plusdom: +8, sconst: 9, sust: 12 },
+ 28: { xp: 140, poids: "701-800", plusdom: +8, sconst: 9, sust: 13 },
+ 29: { xp: 150, poids: "801-900", plusdom: +9, sconst: 9, sust: 14 },
+ 30: { xp: 160, poids: "901-1000", plusdom: +9, sconst: 10, sust: 15 },
+ 31: { xp: 170, poids: "1001-1500", plusdom: +10, sconst: 10, sust: 16 },
+ 32: { xp: 180, poids: "1501-2000", plusdom: +11, sconst: 10, sust: 17 }
+};
export class RdDCarac {
@@ -21,6 +58,37 @@ export class RdDCarac {
(RdDCarac.isReve(selectedCarac) && !competence);
}
+
+ static computeTotal(carac, beaute = undefined) {
+ const total = Object.values(carac).filter(c => !c.derivee)
+ .map(it => parseInt(it.value))
+ .reduce((a, b) => a + b, 0);
+ const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0);
+ return total + beauteSuperieur10;
+ }
+
+ static levelUp(it) {
+ it.xpNext = RdDCarac.getCaracNextXp(it.value);
+ it.isLevelUp = (it.xp >= it.xpNext);
+ }
+
+ /* -------------------------------------------- */
+ static calculSConst(constitution) {
+ return Number(tableCaracDerivee[Number(constitution)].sconst);
+ }
+
+ /* -------------------------------------------- */
+ static getCaracNextXp(value) {
+ const nextValue = Number(value) + 1;
+ // xp est le coût pour atteindre cette valeur, on regarde donc le coût de la valeur+1
+ return RdDCarac.getCaracXp(nextValue);
+ }
+
+ static getCaracXp(targetValue) {
+ return tableCaracDerivee[targetValue]?.xp ?? 200;
+ }
+
+
/**
* L’appel à la chance n’est possible que pour recommencer les jets d’actions physiques :
* tous les jets de combat, de FORCE, d’AGILITÉ, de DEXTÉRITÉ, de Dérobée, d’APPARENCE,
@@ -29,4 +97,38 @@ export class RdDCarac {
static isActionPhysique(selectedCarac) {
return Grammar.toLowerCaseNoAccent(selectedCarac?.label).match(/(apparence|force|agilite|dexterite|vue|ouie|odorat|empathie|melee|tir|lancer|derobee)/);
}
+
+ /* -------------------------------------------- */
+ static computeCarac(data) {
+ data.carac.force.value = Math.min(data.carac.force.value, parseInt(data.carac.taille.value) + 4);
+
+ data.carac.derobee.value = Math.floor(parseInt(((21 - data.carac.taille.value)) + parseInt(data.carac.agilite.value)) / 2);
+ let bonusDomKey = Math.floor((parseInt(data.carac.force.value) + parseInt(data.carac.taille.value)) / 2);
+ bonusDomKey = Math.min(Math.max(bonusDomKey, 0), 32); // Clamp de securite
+
+ let tailleData = tableCaracDerivee[bonusDomKey];
+ data.attributs.plusdom.value = tailleData.plusdom;
+
+ data.attributs.sconst.value = RdDCarac.calculSConst(data.carac.constitution.value);
+ data.attributs.sust.value = tableCaracDerivee[Number(data.carac.taille.value)].sust;
+
+ data.attributs.encombrement.value = (parseInt(data.carac.force.value) + parseInt(data.carac.taille.value)) / 2;
+ data.carac.melee.value = Math.floor((parseInt(data.carac.force.value) + parseInt(data.carac.agilite.value)) / 2);
+ data.carac.tir.value = Math.floor((parseInt(data.carac.vue.value) + parseInt(data.carac.dexterite.value)) / 2);
+ data.carac.lancer.value = Math.floor((parseInt(data.carac.tir.value) + parseInt(data.carac.force.value)) / 2);
+
+ data.sante.vie.max = Math.ceil((parseInt(data.carac.taille.value) + parseInt(data.carac.constitution.value)) / 2);
+
+ data.sante.vie.value = Math.min(data.sante.vie.value, data.sante.vie.max)
+ data.sante.endurance.max = Math.max(parseInt(data.carac.taille.value) + parseInt(data.carac.constitution.value), parseInt(data.sante.vie.max) + parseInt(data.carac.volonte.value));
+ data.sante.endurance.value = Math.min(data.sante.endurance.value, data.sante.endurance.max);
+ data.sante.fatigue.max = data.sante.endurance.max * 2;
+ data.sante.fatigue.value = Math.min(data.sante.fatigue.value, data.sante.fatigue.max);
+
+ //Compteurs
+ data.reve.reve.max = data.carac.reve.value;
+ data.compteurs.chance.max = data.carac.chance.value;
+ }
+
+
}
diff --git a/module/rdd-commands.js b/module/rdd-commands.js
index 3c01d0a2..317b62bf 100644
--- a/module/rdd-commands.js
+++ b/module/rdd-commands.js
@@ -3,6 +3,7 @@
import { DeDraconique } from "./de-draconique.js";
import { RdDItemCompetence } from "./item-competence.js";
import { Misc } from "./misc.js";
+import { RdDCarac } from "./rdd-carac.js";
import { RdDDice } from "./rdd-dice.js";
import { RdDNameGen } from "./rdd-namegen.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js";
@@ -266,7 +267,7 @@ export class RdDCommands {
getCoutXpCarac(msg, params) {
if (params && params.length == 1) {
let to = Number(params[0]);
- RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDUtility.getCaracXp(to)}`);
+ RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDCarac.getCaracXp(to)}`);
}
else {
return false;
diff --git a/module/rdd-utility.js b/module/rdd-utility.js
index 979b74b8..939c2d4c 100644
--- a/module/rdd-utility.js
+++ b/module/rdd-utility.js
@@ -5,22 +5,6 @@ import { RdDCombat } from "./rdd-combat.js";
import { Misc } from "./misc.js";
import { Grammar } from "./grammar.js";
-/* -------------------------------------------- */
-const limitesArchetypes = [
- { "niveau": 0, "nombreMax": 100, "nombre": 0 },
- { "niveau": 1, "nombreMax": 10, "nombre": 0 },
- { "niveau": 2, "nombreMax": 9, "nombre": 0 },
- { "niveau": 3, "nombreMax": 8, "nombre": 0 },
- { "niveau": 4, "nombreMax": 7, "nombre": 0 },
- { "niveau": 5, "nombreMax": 6, "nombre": 0 },
- { "niveau": 6, "nombreMax": 5, "nombre": 0 },
- { "niveau": 7, "nombreMax": 4, "nombre": 0 },
- { "niveau": 8, "nombreMax": 3, "nombre": 0 },
- { "niveau": 9, "nombreMax": 2, "nombre": 0 },
- { "niveau": 10, "nombreMax": 1, "nombre": 0 },
- { "niveau": 11, "nombreMax": 1, "nombre": 0 }
-];
-
/* -------------------------------------------- */
// This table starts at 0 -> niveau -10
const carac_array = ["taille", "apparence", "constitution", "force", "agilite", "dexterite", "vue", "ouie", "odoratgout", "volonte", "intellect", "empathie", "reve", "chance", "melee", "tir", "lancer", "derobee"];
@@ -28,42 +12,6 @@ const difficultesLibres = [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10];
const ajustementsConditions = [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, +1, +2, +3, +4, +5, +6, +7, +8, +9, +10];
const ajustementsEncaissement = [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, +1, +2, +3, +4, +5, +6, +7, +8, +9, +10, +11, +12, +13, +14, +15, +16, +17, +18, +19, +20, +21, +22, +23, +24, +25];
-const tableCaracDerivee = {
- // xp: coût pour passer du niveau inférieur à ce niveau
- 1: { xp: 3, poids: "moins de 1kg", plusdom: -5, sconst: 0.5, sust: 0.1 },
- 2: { xp: 3, poids: "1-5", plusdom: -4, sconst: 0.5, sust: 0.3 },
- 3: { xp: 4, poids: "6-10", plusdom: -3, sconst: 1, sust: 0.5, beaute: 'hideux' },
- 4: { xp: 4, poids: "11-20", plusdom: -3, sconst: 1, sust: 1, beaute: 'repoussant' },
- 5: { xp: 5, poids: "21-30", plusdom: -2, sconst: 1, sust: 1, beaute: 'franchement très laid' },
- 6: { xp: 5, poids: "31-40", plusdom: -1, sconst: 2, sust: 2, beaute: 'laid' },
- 7: { xp: 6, poids: "41-50", plusdom: -1, sconst: 2, sust: 2, beaute: 'très désavantagé' },
- 8: { xp: 6, poids: "51-60", plusdom: 0, sconst: 2, sust: 2, beaute: 'désavantagé' },
- 9: { xp: 7, poids: "61-65", plusdom: 0, sconst: 3, sust: 2, beaute: 'pas terrible' },
- 10: { xp: 7, poids: "66-70", plusdom: 0, sconst: 3, sust: 3, beaute: 'commun' },
- 11: { xp: 8, poids: "71-75", plusdom: 0, sconst: 3, sust: 3, beaute: 'pas mal' },
- 12: { xp: 8, poids: "76-80", plusdom: +1, sconst: 4, sust: 3, beaute: 'avantagé' },
- 13: { xp: 9, poids: "81-90", plusdom: +1, sconst: 4, sust: 3, beaute: 'mignon' },
- 14: { xp: 9, poids: "91-100", plusdom: +2, sconst: 4, sust: 4, beaute: 'beau' },
- 15: { xp: 10, poids: "101-110", plusdom: +2, sconst: 5, sust: 4, beaute: 'très beau' },
- 16: { xp: 20, poids: "111-120", plusdom: +3, sconst: 5, sust: 4, beaute: 'éblouissant' },
- 17: { xp: 30, poids: "121-131", plusdom: +3, sconst: 5, sust: 5 },
- 18: { xp: 40, poids: "131-141", plusdom: +4, sconst: 6, sust: 5 },
- 19: { xp: 50, poids: "141-150", plusdom: +4, sconst: 6, sust: 5 },
- 20: { xp: 60, poids: "151-160", plusdom: +4, sconst: 6, sust: 6 },
- 21: { xp: 70, poids: "161-180", plusdom: +5, sconst: 7, sust: 6 },
- 22: { xp: 80, poids: "181-200", plusdom: +5, sconst: 7, sust: 7 },
- 23: { xp: 90, poids: "201-300", plusdom: +6, sconst: 7, sust: 8 },
- 24: { xp: 100, poids: "301-400", plusdom: +6, sconst: 8, sust: 9 },
- 25: { xp: 110, poids: "401-500", plusdom: +7, sconst: 8, sust: 10 },
- 26: { xp: 120, poids: "501-600", plusdom: +7, sconst: 8, sust: 11 },
- 27: { xp: 130, poids: "601-700", plusdom: +8, sconst: 9, sust: 12 },
- 28: { xp: 140, poids: "701-800", plusdom: +8, sconst: 9, sust: 13 },
- 29: { xp: 150, poids: "801-900", plusdom: +9, sconst: 9, sust: 14 },
- 30: { xp: 160, poids: "901-1000", plusdom: +9, sconst: 10, sust: 15 },
- 31: { xp: 170, poids: "1001-1500", plusdom: +10, sconst: 10, sust: 16 },
- 32: { xp: 180, poids: "1501-2000", plusdom: +11, sconst: 10, sust: 17 }
-}
-
/* -------------------------------------------- */
function _buildAllSegmentsFatigue(max) {
const cycle = [5, 2, 4, 1, 3, 0];
@@ -243,10 +191,6 @@ export class RdDUtility {
return loadTemplates(templatePaths);
}
- /* -------------------------------------------- */
- static getLimitesArchetypes() {
- return duplicate(limitesArchetypes);
- }
/* -------------------------------------------- */
static checkNull(items) {
@@ -312,6 +256,7 @@ export class RdDUtility {
.concat(formData.data.potions)
.concat(formData.data.herbes)
.concat(formData.data.ingredients);
+ formData.data.competences = (formData.itemsByType.competence??[]).concat(formData.itemsByType.competencecreature??[]);
}
/* -------------------------------------------- */
@@ -410,53 +355,6 @@ export class RdDUtility {
return definitionsBlessures;
}
- /* -------------------------------------------- */
- static getCaracNextXp(value) {
- const nextValue = Number(value) + 1;
- // xp est le coût pour atteindre cette valeur, on regarde donc le coût de la valeur+1
- return RdDUtility.getCaracXp(nextValue);
- }
-
- static getCaracXp(targetValue) {
- return tableCaracDerivee[targetValue]?.xp ?? 200;
- }
-
- /* -------------------------------------------- */
- static computeCarac(data) {
- data.carac.force.value = Math.min(data.carac.force.value, parseInt(data.carac.taille.value) + 4);
-
- data.carac.derobee.value = Math.floor(parseInt(((21 - data.carac.taille.value)) + parseInt(data.carac.agilite.value)) / 2);
- let bonusDomKey = Math.floor((parseInt(data.carac.force.value) + parseInt(data.carac.taille.value)) / 2);
- bonusDomKey = Math.min(Math.max(bonusDomKey, 0), 32); // Clamp de securite
-
- let tailleData = tableCaracDerivee[bonusDomKey];
- data.attributs.plusdom.value = tailleData.plusdom;
-
- data.attributs.sconst.value = RdDUtility.calculSConst(data.carac.constitution.value);
- data.attributs.sust.value = tableCaracDerivee[Number(data.carac.taille.value)].sust;
-
- data.attributs.encombrement.value = (parseInt(data.carac.force.value) + parseInt(data.carac.taille.value)) / 2;
- data.carac.melee.value = Math.floor((parseInt(data.carac.force.value) + parseInt(data.carac.agilite.value)) / 2);
- data.carac.tir.value = Math.floor((parseInt(data.carac.vue.value) + parseInt(data.carac.dexterite.value)) / 2);
- data.carac.lancer.value = Math.floor((parseInt(data.carac.tir.value) + parseInt(data.carac.force.value)) / 2);
-
- data.sante.vie.max = Math.ceil((parseInt(data.carac.taille.value) + parseInt(data.carac.constitution.value)) / 2);
-
- data.sante.vie.value = Math.min(data.sante.vie.value, data.sante.vie.max)
- data.sante.endurance.max = Math.max(parseInt(data.carac.taille.value) + parseInt(data.carac.constitution.value), parseInt(data.sante.vie.max) + parseInt(data.carac.volonte.value));
- data.sante.endurance.value = Math.min(data.sante.endurance.value, data.sante.endurance.max);
- data.sante.fatigue.max = data.sante.endurance.max * 2;
- data.sante.fatigue.value = Math.min(data.sante.fatigue.value, data.sante.fatigue.max);
-
- //Compteurs
- data.reve.reve.max = data.carac.reve.value;
- data.compteurs.chance.max = data.carac.chance.value;
- }
-
- static calculSConst(constitution) {
- return Number(tableCaracDerivee[Number(constitution)].sconst);
- }
-
/* -------------------------------------------- */
static getSegmentsFatigue(maxEnd) {
maxEnd = Math.max(maxEnd, 1);
diff --git a/templates/actor-creature-sheet.html b/templates/actor-creature-sheet.html
index 1901d9eb..599c23a8 100644
--- a/templates/actor-creature-sheet.html
+++ b/templates/actor-creature-sheet.html
@@ -15,17 +15,17 @@
- {{data.blessures.resume}}
+ {{calc.resumeBlessures}}
- {{#if data.surprise}}{{data.surprise}}! {{/if}}
+ {{#if calc.surprise}}{{calc.surprise}}! {{/if}}
{{#if actor.effects}}
{{#each actor.effects as |effect key|}}
{{/each}}
- {{#if data.isGM}}
+ {{#if options.isGM}}
(enlever tout)
{{/if}}
{{else}}
@@ -199,9 +199,9 @@
{{!-- Equipment Tab --}}
-
Encombrement total/max : {{numberFormat data.encTotal decimals=1}} / {{data.attributs.encombrement.value}} {{data.surEncombrementMessage}} -
+
Encombrement total/max : {{numberFormat calc.encTotal decimals=2}} / {{data.attributs.encombrement.value}} {{calc.surEncombrementMessage}} -
Créer un objet
- {{#if data.isGM}}
+ {{#if options.isGM}}
- Vider tout les conteneurs
{{/if}}
diff --git a/templates/actor-entite-sheet.html b/templates/actor-entite-sheet.html
index 1f03d5cd..907935df 100644
--- a/templates/actor-entite-sheet.html
+++ b/templates/actor-entite-sheet.html
@@ -75,14 +75,11 @@
{{comp.name}}
-
-
-
- Malus de fatigue : {{data.fatigue.malus}}
- {{{data.fatigue.html}}}
+ Malus de fatigue : {{calc.fatigue.malus}}
+ {{{calc.fatigue.html}}}
- {{data.blessures.resume}}
+ {{calc.resumeBlessures}}
{{data.compteurs.etat.label}}: {{data.compteurs.etat.value}}
{{data.compteurs.surenc.label}}: {{data.compteurs.surenc.value}}
- {{#if data.surprise}}{{data.surprise}}! {{/if}}
+ {{#if calc.surprise}}{{calc.surprise}}! {{/if}}
{{#if actor.effects}}
{{#each actor.effects as |effect key|}}
{{/each}}
- {{#if data.isGM}}
+ {{#if options.isGM}}
(enlever tout)
{{/if}}
{{else}}
@@ -112,8 +112,8 @@
@@ -156,7 +156,7 @@
Beauté :
-
+
{{#each data.attributs as |attr key|}}
@@ -217,49 +217,25 @@
+
+
@@ -268,174 +244,45 @@
-
+
+ {{#each data.competenceByCategory.specialisee as |comp key|}}
+ {{> "systems/foundryvtt-reve-de-dragon/templates/actor-sheet-competence-partial.html" comp}}
{{/each}}
-
-
+
+
-
+
-
+
@@ -444,33 +291,7 @@
@@ -479,44 +300,17 @@
Total XP compétences
- {{data.competenceXPTotal}}
+ {{calc.competenceXPTotal}}
- {{#if data.montrerArchetype}}
- {{#each data.comptageArchetype as |archetype key|}}
+ {{#if options.montrerArchetype}}
+ {{#each calc.comptageArchetype as |archetype key|}}
Archetype {{archetype.niveau}} : {{archetype.nombre}} / {{archetype.nombreMax}}
@@ -749,7 +543,7 @@
Position en TMR :
- {{#if data.isGM}}
+ {{#if options.isGM}}
{{else}}
{{data.reve.tmrpos.coord}}
@@ -759,7 +553,7 @@
Seuil de Rêve :
- {{#if data.isGM}}
+ {{#if options.isGM}}
{{else}}
{{data.reve.seuil.value}}
@@ -769,7 +563,7 @@
Refoulement :
- {{#if data.isGM}}
+ {{#if options.isGM}}
{{else}}
{{data.reve.refoulement.value}}
@@ -920,12 +714,12 @@
Equipement porté
- Encombrement total/max : {{numberFormat data.encTotal decimals=1}} / {{data.attributs.encombrement.value}} {{data.surEncombrementMessage}} -
- Estimation de l'équipement : {{numberFormat data.prixTotalEquipement decimals=2}} Sols
+ Encombrement total/max : {{numberFormat calc.encTotal decimals=2}} / {{data.attributs.encombrement.value}} {{calc.surEncombrementMessage}} -
+ Estimation de l'équipement : {{numberFormat calc.prixTotalEquipement decimals=2}} Sols
diff --git a/templates/actor-vehicule-sheet.html b/templates/actor-vehicule-sheet.html
index 4b7bfcde..b63c3391 100644
--- a/templates/actor-vehicule-sheet.html
+++ b/templates/actor-vehicule-sheet.html
@@ -68,9 +68,9 @@
{{!-- Equipment Tab --}}
-
Encombrement total/max : {{numberFormat data.encTotal decimals=1}} / {{data.capacite_encombrement}} {{data.surEncombrementMessage}} -
+
Encombrement total/max : {{numberFormat calc.encTotal decimals=2}} / {{data.capacite_encombrement}} {{calc.surEncombrementMessage}} -
Créer un objet
- {{#if data.isGM}}
+ {{#if options.isGM}}
- Vider tout les conteneurs
{{/if}}