diff --git a/module/actor-sheet.js b/module/actor-sheet.js
index 33e4f2c3..06db623b 100644
--- a/module/actor-sheet.js
+++ b/module/actor-sheet.js
@@ -41,7 +41,7 @@ export class RdDActorSheet extends ActorSheet {
data.itemsByType = RdDItem.buildItemsClassification(data.items);
// Competence per category
- let competenceXPTotal = 0;
+ data.data.competenceXPTotal = 0;
data.competenceByCategory = RdDItem.classify(
data.itemsByType.competence,
item => item.data.categorie,
@@ -51,11 +51,10 @@ export class RdDActorSheet extends ActorSheet {
//this.actor.checkCompetenceXP(item.name); // Petite vérification experience
item.data.showCompetence = !data.data.showCompNiveauBase || (Number(item.data.niveau) != Number(RdDUtility.getLevelCategory(item.data.categorie)));
// Ignorer les compétences 'troncs' à ce stade
- competenceXPTotal += RdDItemCompetence.isTronc(item.name) ? 0 : RdDItemCompetence.computeCompetenceXPCost(item);
+ data.data.competenceXPTotal += RdDItemCompetence.computeCompetenceXPCost(item);
return item;
});
- competenceXPTotal += RdDItemCompetence.computeCompetenceTroncXP(data.itemsByType.competence);
- data.data.competenceXPTotal = competenceXPTotal;
+ data.data.competenceXPTotal -= RdDItemCompetence.computeEconomieCompetenceTroncXP(data.itemsByType.competence);
// Compute current carac sum
let sum = 0;
diff --git a/module/item-competence.js b/module/item-competence.js
index 4c08b548..8bd78974 100644
--- a/module/item-competence.js
+++ b/module/item-competence.js
@@ -3,6 +3,20 @@ 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;
+
+function _buildCumulXP() {
+ let cumulXP = { "-11": 0 };
+ let cumul = 0;
+ for (let i = 0; i <= competence_xp_par_niveau.length; i++) {
+ let level = i - 10;
+ cumul += competence_xp_par_niveau[i];
+ cumulXP[level] = cumul;
+ }
+ return cumulXP;
+}
+
+const competence_xp_cumul = _buildCumulXP();
export class RdDItemCompetence extends Item {
@@ -43,44 +57,25 @@ export class RdDItemCompetence extends Item {
}
/* -------------------------------------------- */
static computeCompetenceXPCost(competence) {
- let minLevel = competence.data.base;
- if (minLevel == competence.data.niveau) return 0;
- if (competence.data.niveau < -10) return 0;
-
- let xp = 0;
- for (let i = minLevel + 1; i <= competence.data.niveau; i++) {
- xp += competence_xp_par_niveau[i + 10];
- //console.log(i, i+10, competence_xp_par_niveau[i+10]);
- }
- if (competence.data.categorie == 'draconic') {
- xp += competence.data.xp_sort;
- }
+ let xp = RdDItemCompetence.getDeltaXp(competence.data.base, competence.data.niveau ?? competence.data.base);
+ xp += competence.data.xp ?? 0;
+ xp += competence.data.xp_sort ?? 0;
return xp;
}
- /* -------------------------------------------- */
- static computeCompetenceTroncXP(competences) {
- let xp = 0;
+ static computeEconomieCompetenceTroncXP(competences) {
+ let economie = 0;
for (let troncList of competenceTroncs) {
- let minNiveau = 0;
- for (let troncName of troncList) {
- let comp = RdDItemCompetence.findCompetence(competences, troncName);
- if (comp) {
- minNiveau = Math.min(comp.data.niveau, minNiveau);
- }
- }
- minNiveau = Math.max(minNiveau, 0); // Clamp à 0, pour le tronc commun
- let minNiveauXP = competence_xp_par_niveau[minNiveau + 10];
- xp += minNiveauXP;
- for (let troncName of troncList) {
- let comp = RdDItemCompetence.findCompetence(competences, troncName);
- if (comp) {
- xp += competence_xp_par_niveau[comp.data.niveau + 10] - minNiveauXP;
- }
- }
+ let list = troncList.map(name => RdDItemCompetence.findCompetence(competences, name))
+ .sort( (c1, c2) => c2.data.niveau - c1.data.niveau); // tri du plus haut au plus bas
+ list.splice(0,1); // ignorer la plus élevée
+ list.forEach(c => {
+ economie += RdDItemCompetence.getDeltaXp(c.data.base, Math.min(c.data.niveau, 0) );
+ });
}
- return xp;
+ return economie;
}
+
/* -------------------------------------------- */
static findCompetence(list, name) {
name = name.toLowerCase();
@@ -89,7 +84,24 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static getCompetenceNextXp(niveau) {
- return competence_xp_par_niveau[niveau + 10];
+ return RdDItemCompetence.getCompetenceXp(niveau + 1);
+ }
+
+ static getCompetenceXp(niveau) {
+ RdDItemCompetence._valideNiveau(niveau);
+ return niveau < -10 ? 0 : competence_xp_par_niveau[niveau + 10];
+ }
+
+ static getDeltaXp(from, to) {
+ RdDItemCompetence._valideNiveau(from);
+ RdDItemCompetence._valideNiveau(to);
+ return competence_xp_cumul[to] - competence_xp_cumul[from];
+ }
+
+ 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)
+ }
}
}
\ No newline at end of file
diff --git a/module/rdd-commands.js b/module/rdd-commands.js
index c1ea3d85..a9ecde4d 100644
--- a/module/rdd-commands.js
+++ b/module/rdd-commands.js
@@ -2,6 +2,7 @@
import { ChatUtility } from "./chat-utility.js";
import { DeDraconique } from "./de-draconique.js";
+import { RdDItemCompetence } from "./item-competence.js";
import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js";
@@ -30,8 +31,21 @@ export class RdDCommands {
rddCommands.registerCommand({ path: ["/tmra"], func: (content, msg, params) => TMRUtility.getTMRAleatoire(), descr: "Tire une case aléatoire des Terres médianes" });
rddCommands.registerCommand({
- path: ["/tmrr"], func: (content, msg, params) => rddCommands.getRencontreTMR(params),
- descr: "Syntaxe: /tmrr case jet
Détermine quelle est la rencontre dans la case pour le jet
Exemple: /tmrr forêt 50"
+ path: ["/tmrr"], func: (content, msg, params) => rddCommands.getRencontreTMR(msg, params),
+ descr: "Exemple: /tmrr forêt 47
Détermine quelle est la rencontre dans une case 'forêt' pour un jet de dé de 47"
+ });
+
+ rddCommands.registerCommand({
+ path: ["/xp", "comp"], func: (content, msg, params) => rddCommands.getCoutXpComp(msg, params),
+ descr: `Détermine le coût d'expérience pour augmenter une compétence. Exemples:
+
/xp comp -6 1: pour passer de -6 à +1
+
/xp comp +4: pour atteindre le niveau 4 (depuis +3)`
+ });
+
+ rddCommands.registerCommand({
+ path: ["/xp", "carac"], func: (content, msg, params) => rddCommands.getCoutXpCarac(msg, params),
+ descr: `Détermine le coût d'expérience pour augmenter une caractéristique. Exemples:
+
/xp carac 15: coût pour atteindre 15 (depuis 14)`
});
rddCommands.registerCommand({
@@ -129,8 +143,9 @@ export class RdDCommands {
}
}
if (command && command.func) {
- if (command.func(content, msg, params) === false) {
- this._displayHelp(msg, `${path}: ${command.descr}`);
+ const result = command.func(content, msg, params);
+ if (result == false) {
+ RdDCommands._chatAnswer(msg, command.descr);
}
return true;
}
@@ -142,8 +157,13 @@ export class RdDCommands {
let list = []
this._buildSubTableHelp(list, table || this.commandsTable);
const messageAide = list.reduce((a, b) => a + '