Utilisation Misc.data

This commit is contained in:
Vincent Vandemeulebrouck 2021-03-29 18:08:18 +02:00
parent 592f54af61
commit 31204cbf51
21 changed files with 254 additions and 237 deletions

View File

@ -240,8 +240,12 @@ export class RdDActor extends Actor {
return id ? this.items.find(it => it._id == id) : undefined; return id ? this.items.find(it => it._id == id) : undefined;
} }
getItemOfType(type, id) { getItemOfType(type, id) {
return id ? this.data.items.find(it => it._id == id && it.type == type) : undefined; return id ? this.items.find(it => it._id == id && it.type == type) : undefined;
} }
getMonnaie(id) {
return this.getItemOfType(id, 'monnaie');
}
getTache(id) { getTache(id) {
return this.getItemOfType(id, 'tache'); return this.getItemOfType(id, 'tache');
} }
@ -267,8 +271,12 @@ export class RdDActor extends Actor {
return this.getItemOfType(id, 'recettecuisine'); return this.getItemOfType(id, 'recettecuisine');
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getDraconicList() {
return this.items.filter(it => Misc.data(it).type == 'competence' && Misc.templateData(it).categorie == 'draconic')
}
/* -------------------------------------------- */
getBestDraconic() { getBestDraconic() {
const list = this.getDraconicList().sort((a, b) => b.data.data.niveau - a.data.data.niveau); const list = this.getDraconicList().sort(Misc.descending(it => Misc.templateData(it).niveau));
if (list.length == 0) { if (list.length == 0) {
return { name: "Aucun", data: { name: "Aucun", data: { niveau: -11 } } }; return { name: "Aucun", data: { name: "Aucun", data: { niveau: -11 } } };
} }
@ -296,7 +304,7 @@ export class RdDActor extends Actor {
getSurprise(isCombat = undefined) { getSurprise(isCombat = undefined) {
let niveauSurprise = Array.from(this.effects?.values() ?? []) let niveauSurprise = Array.from(this.effects?.values() ?? [])
.map(effect => StatusEffects.valeurSurprise(effect.data, isCombat)) .map(effect => StatusEffects.valeurSurprise(effect.data, isCombat))
.reduce((a, b) => a + b, 0); .reduce(Misc.sum(), 0);
if (niveauSurprise > 1) { if (niveauSurprise > 1) {
return 'totale'; return 'totale';
} }
@ -600,10 +608,10 @@ export class RdDActor extends Actor {
async resultCombatReveDeDragon(rollData) { async resultCombatReveDeDragon(rollData) {
rollData.queues = []; rollData.queues = [];
if (rollData.rolled.isEchec) { if (rollData.rolled.isEchec) {
rollData.queues.push(await this.ajouterQueue()); rollData.queues.push(Misc.data(await this.ajouterQueue()));
} }
if (rollData.rolled.isETotal) { if (rollData.rolled.isETotal) {
rollData.queues.push(await this.ajouterQueue()); rollData.queues.push(Misc.data(await this.ajouterQueue()));
} }
if (rollData.rolled.isSuccess) { if (rollData.rolled.isSuccess) {
await this.updatePointDeSeuil(); await this.updatePointDeSeuil();
@ -621,31 +629,6 @@ export class RdDActor extends Actor {
}); });
} }
/* -------------------------------------------- */
async appliquerReveDeDragon(roll, force) {
let message = "";
if (roll.isSuccess) {
message += "<br>Vous gagnez " + force + " points de Rêve";
await this.updatePointDeSeuil();
await this.reveActuelIncDec(force);
}
if (roll.isPart) {
// TODO: Dialog pour choix entre HR opu général?
message += "<br>Vous gagnez une Tête de dragon: Demander à votre MJ d'effectuer un tirage sur la table des Hauts Rêvants ou des Vrais Rêvants, selon votre choix.";
}
if (roll.isEchec) {
message += "<br>Vous subissez une Queue de Dragon: " + await this.ajouterQueue();
}
if (roll.isETotal) {
message += "<br>A cause de votre échec total, vous subissez une deuxième Queue de Dragon: " + await this.ajouterQueue();
}
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
content: message
});
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async sortMisEnReserve(rollData, sort) { async sortMisEnReserve(rollData, sort) {
let reserve = duplicate(Misc.templateData(this).reve.reserve.list); let reserve = duplicate(Misc.templateData(this).reve.reserve.list);
@ -690,7 +673,7 @@ export class RdDActor extends Actor {
let comp = this.getCompetence(compName); let comp = this.getCompetence(compName);
//console.log(comp); //console.log(comp);
if (comp) { if (comp) {
const update = { _id: comp._id } const update = { _id: comp.id }
if (fieldName == "niveau") if (fieldName == "niveau")
update['data.niveau'] = compValue; update['data.niveau'] = compValue;
else if (fieldName == "dommages") else if (fieldName == "dommages")
@ -718,7 +701,7 @@ export class RdDActor extends Actor {
content: message content: message
}); });
} }
const update = { _id: comp._id, 'data.niveau': nouveauNiveau }; const update = { _id: comp.id, 'data.niveau': nouveauNiveau };
await this.updateEmbeddedEntity("Item", update); // Updates one EmbeddedEntity await this.updateEmbeddedEntity("Item", update); // Updates one EmbeddedEntity
} else { } else {
console.log("Competence not found", compName); console.log("Competence not found", compName);
@ -731,7 +714,7 @@ export class RdDActor extends Actor {
if (comp) { if (comp) {
compValue = compValue ?? 0; compValue = compValue ?? 0;
this.checkCompetenceXP(compName, compValue); this.checkCompetenceXP(compName, compValue);
const update = { _id: comp._id, 'data.xp': compValue }; const update = { _id: comp.id, 'data.xp': compValue };
await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity
} else { } else {
console.log("Competence not found", compName); console.log("Competence not found", compName);
@ -744,7 +727,7 @@ export class RdDActor extends Actor {
let comp = this.getCompetence(compName); let comp = this.getCompetence(compName);
if (comp) { if (comp) {
compValue = compValue ?? 0; compValue = compValue ?? 0;
const update = { _id: comp._id, 'data.xp_sort': compValue }; const update = { _id: comp.id, 'data.xp_sort': compValue };
await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity
} else { } else {
console.log("Competence not found", compName); console.log("Competence not found", compName);
@ -756,7 +739,7 @@ export class RdDActor extends Actor {
let comp = this.getCompetence(compName); let comp = this.getCompetence(compName);
if (comp) { if (comp) {
compValue = compValue ?? 0; compValue = compValue ?? 0;
const update = { _id: comp._id, 'data.niveau_archetype': compValue }; const update = { _id: comp.id, 'data.niveau_archetype': compValue };
await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity
} else { } else {
console.log("Competence not found", compName); console.log("Competence not found", compName);
@ -813,7 +796,7 @@ export class RdDActor extends Actor {
return Number(tplData.encombrement) * Number(tplData.quantite); return Number(tplData.encombrement) * Number(tplData.quantite);
} }
const encContenus = tplData.contenu.map(idContenu => this.getRecursiveEnc(this.getObjet(idContenu))); const encContenus = tplData.contenu.map(idContenu => this.getRecursiveEnc(this.getObjet(idContenu)));
return encContenus.reduce((a, b) => a + b, 0) return encContenus.reduce(Misc.sum(), 0)
+ Number(tplData.encombrement) /* TODO? Number(tplData.quantite) -- on pourrait avoir plusieurs conteneurs...*/ + Number(tplData.encombrement) /* TODO? Number(tplData.quantite) -- on pourrait avoir plusieurs conteneurs...*/
} }
@ -1099,7 +1082,7 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async ajouterQueue(options = { chat: false }) { async ajouterQueue(options = { chat: false }) {
let queue; let queue;
if (Misc.templateData(this).reve.reve.thanatosused) { if (Misc.data(this).data.reve.reve.thanatosused) {
queue = await RdDRollTables.getOmbre(); queue = await RdDRollTables.getOmbre();
await this.update({ "data.reve.reve.thanatosused": false }); await this.update({ "data.reve.reve.thanatosused": false });
} }
@ -1766,15 +1749,16 @@ export class RdDActor extends Actor {
let draconicList = this.getDraconicList(); let draconicList = this.getDraconicList();
let bestDraconic = this.getBestDraconic(); let bestDraconic = this.getBestDraconic();
for (let sort of sortList) { for (let sort of sortList) {
let voie = sort.data.draconic.toLowerCase(); let voie = sort.data.draconic;
let draconic = draconicList.find(it => it.data.data.categorie == 'draconic' && it.data.name.toLowerCase().includes(voie)); let draconic = RdDItemCompetence.getVoieDraconic(draconicList, voie);
//console.log(draconicList, bestDraconic, draconic, voie); //console.log(draconicList, bestDraconic, draconic, voie);
if (sort.name.toLowerCase().includes('aura')) { if (sort.name.toLowerCase().includes('aura')) {
draconic = bestDraconic; draconic = bestDraconic;
} }
draconic = duplicate(draconic); // TODO: duplicate sur Misc.data?
draconic = duplicate(Misc.data(draconic));
if (draconicDone[draconic.name] == undefined) { if (draconicDone[draconic.name] == undefined) {
draconic.data.data.defaut_carac = 'reve'; draconic.data.defaut_carac = 'reve';
newDraconicList.push(draconic); newDraconicList.push(draconic);
draconicDone[draconic.name] = newDraconicList.length - 1; // Patch local pour relier facilement voie/compétence draconicDone[draconic.name] = newDraconicList.length - 1; // Patch local pour relier facilement voie/compétence
} }
@ -1811,7 +1795,7 @@ export class RdDActor extends Actor {
competence: draconicList[0], competence: draconicList[0],
selectedSort: sortList[0], selectedSort: sortList[0],
tmr: TMRUtility.getTMR(coord), tmr: TMRUtility.getTMR(coord),
diffLibre: sortList[0].data.difficulte, // Per default at startup diffLibre: RdDItemSort.getDifficulte(sortList[0], -7), // Per default at startup
coutreve: Array(30).fill().map((item, index) => 1 + index), coutreve: Array(30).fill().map((item, index) => 1 + index),
carac: { 'reve': duplicate(actorData.data.carac.reve) } carac: { 'reve': duplicate(actorData.data.carac.reve) }
} }
@ -2054,23 +2038,25 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollTache(id) { async rollTache(id) {
let tache = duplicate(this.getTache(id)); const actorData = Misc.data(this);
let competence = this.getCompetence(tache.data.competence); const tacheData = Misc.data(this.getTache(id));
competence.data.data.defaut_carac = tache.data.carac; // Patch ! const compData = duplicate(Misc.data(this.getCompetence(tacheData.data.competence)));
compData.data.defaut_carac = tacheData.data.carac; // Patch !
let rollData = { let rollData = {
competence: competence, competence: compData,
tache: tache, tache: tacheData,
diffConditions: tache.data.difficulte, diffConditions: tacheData.data.difficulte,
use: { libre: false, conditions: false }, use: { libre: false, conditions: false },
carac: {} carac: {}
}; };
rollData.carac[tache.data.carac] = duplicate(Misc.templateData(this).carac[tache.data.carac]); // Single carac rollData.carac[tacheData.data.carac] = duplicate(actorData.data.carac[tacheData.data.carac]); // Single carac
console.log("rollTache !!!", rollData); console.log("rollTache !!!", rollData);
const dialog = await RdDRoll.create(this, rollData, { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html' }, { const dialog = await RdDRoll.create(this, rollData, { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html' }, {
name: 'jet-competence', name: 'jet-competence',
label: 'Jet de Tâche ' + tache.name, label: 'Jet de Tâche ' + tacheData.name,
callbacks: [ callbacks: [
this.createCallbackExperience(), this.createCallbackExperience(),
this.createCallbackAppelAuMoral(), this.createCallbackAppelAuMoral(),
@ -2465,11 +2451,6 @@ export class RdDActor extends Actor {
return this.data.items.filter(it => it.data.type == "sort"); return this.data.items.filter(it => it.data.type == "sort");
} }
/* -------------------------------------------- */
getDraconicList() {
return this.data.items.filter(it => it.data.data.categorie == 'draconic')
}
/* -------------------------------------------- */ /* -------------------------------------------- */
countMonteeLaborieuse() { // Return +1 par queue/ombre/souffle Montée Laborieuse présente countMonteeLaborieuse() { // Return +1 par queue/ombre/souffle Montée Laborieuse présente
let countMonteeLaborieuse = this.data.items.filter(it => EffetsDraconiques.isMonteeLaborieuse(it)).length; let countMonteeLaborieuse = this.data.items.filter(it => EffetsDraconiques.isMonteeLaborieuse(it)).length;
@ -2928,9 +2909,9 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async monnaieIncDec(id, value) { async monnaieIncDec(id, value) {
let monnaie = this.data.items.find(item => item.type == 'monnaie' && item.id == id); let monnaie = this.getMonnaie(id);
if (monnaie) { if (monnaie) {
const quantite = Math.max(0, monnaie.data.data.quantite + value); const quantite = Math.max(0, Misc.templateData(monnaie).quantite + value);
await this.updateEmbeddedEntity("OwnedItem", { _id: monnaie.id, 'data.quantite': quantite }); await this.updateEmbeddedEntity("OwnedItem", { _id: monnaie.id, 'data.quantite': quantite });
} }
} }

View File

@ -1,10 +1,11 @@
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
const competenceTroncs = [["Esquive", "Dague", "Corps à corps"], 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"]]; ["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 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 niveau_max = xp_par_niveau.length - 10;
/* -------------------------------------------- */ /* -------------------------------------------- */
const limitesArchetypes = [ const limitesArchetypes = [
{ "niveau": 0, "nombreMax": 100, "nombre": 0 }, { "niveau": 0, "nombreMax": 100, "nombre": 0 },
@ -43,9 +44,9 @@ const compendiumCompetences = {
function _buildCumulXP() { function _buildCumulXP() {
let cumulXP = { "-11": 0 }; let cumulXP = { "-11": 0 };
let cumul = 0; let cumul = 0;
for (let i = 0; i <= competence_xp_par_niveau.length; i++) { for (let i = 0; i <= xp_par_niveau.length; i++) {
let level = i - 10; let level = i - 10;
cumul += competence_xp_par_niveau[i]; cumul += xp_par_niveau[i];
cumulXP[level] = cumul; cumulXP[level] = cumul;
} }
return cumulXP; return cumulXP;
@ -73,6 +74,20 @@ export class RdDItemCompetence extends Item {
return categorieCompetences[category].label; return categorieCompetences[category].label;
} }
/* -------------------------------------------- */
static getCategorie(competence) {
return Misc.data(competence)?.data.categorie;
}
static isDraconic(competence) {
return Misc.data(competence).data.categorie == 'draconic';
}
/* -------------------------------------------- */
static getVoieDraconic(competences, voie) {
voie = Grammar.toLowerCaseNoAccent(voie);
return competences.find(it => RdDItemCompetence.isDraconic(it) && Grammar.toLowerCaseNoAccent(Misc.data(it).name).includes(voie));
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static getEsquive(competences) { static getEsquive(competences) {
return { name: 'Esquive', niveau: RdDItemCompetence.findCompetence(competences, 'Esquive')?.data.niveau ?? -6 }; return { name: 'Esquive', niveau: RdDItemCompetence.findCompetence(competences, 'Esquive')?.data.niveau ?? -6 };
@ -80,9 +95,9 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isCompetenceArme(competence) { static isCompetenceArme(competence) {
switch (competence.data.data.categorie) { switch (Misc.templateData(competence).categorie) {
case 'melee': case 'melee':
return competence.data.name != 'Esquive'; return Misc.data(competence).name != 'Esquive';
case 'tir': case 'tir':
case 'lancer': case 'lancer':
return true; return true;
@ -92,15 +107,15 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isArmeUneMain(competence) { static isArmeUneMain(competence) {
return competence?.name.toLowerCase().includes("1 main"); return Misc.data(competence)?.name.toLowerCase().includes("1 main");
} }
static isArme2Main(competence) { static isArme2Main(competence) {
return competence?.name.toLowerCase().includes("2 main"); return Misc.data(competence)?.name.toLowerCase().includes("2 main");
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static isMalusEncombrementTotal(competence) { static isMalusEncombrementTotal(competence) {
return competence?.name.toLowerCase().match(/(natation|acrobatie)/); return Misc.data(competence)?.name.toLowerCase().match(/(natation|acrobatie)/);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -117,17 +132,18 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeTotalXP(competences) { static computeTotalXP(competences) {
const total = competences.map(c => RdDItemCompetence.computeXP(c)) const total = competences.map(c => RdDItemCompetence.computeXP(c))
.reduce((a, b) => a + b, 0); .reduce(Misc.sum(), 0);
const economieTronc = RdDItemCompetence.computeEconomieXPTronc(competences); const economieTronc = RdDItemCompetence.computeEconomieXPTronc(competences);
return total - economieTronc; return total - economieTronc;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeXP(competence) { static computeXP(competence) {
const factor = competence.name.includes('Thanatos') ? 2 : 1; // Thanatos compte double ! const itemData = Misc.data(competence);
const xpNiveau = RdDItemCompetence.computeDeltaXP(competence.data.base, competence.data.niveau ?? competence.data.base); const factor = itemData.name.includes('Thanatos') ? 2 : 1; // Thanatos compte double !
const xp = competence.data.xp ?? 0; const xpNiveau = RdDItemCompetence.computeDeltaXP(itemData.data.base, itemData.data.niveau ?? itemData.data.base);
const xpSort = competence.data.xp_sort ?? 0; const xp = itemData.data.xp ?? 0;
const xpSort = itemData.data.xp_sort ?? 0;
return factor * (xpNiveau + xp) + xpSort; return factor * (xpNiveau + xp) + xpSort;
} }
@ -137,10 +153,10 @@ export class RdDItemCompetence extends Item {
list => list.map(name => RdDItemCompetence.findCompetence(competences, name)) list => list.map(name => RdDItemCompetence.findCompetence(competences, name))
// calcul du coût xp jusqu'au niveau 0 maximum // 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))) .map(it => RdDItemCompetence.computeDeltaXP(it?.data.base ?? -11, Math.min(it?.data.niveau ?? -11, 0)))
.sort((a, b) => b - a) // tri descendant .sort(Misc.descending(x => x))
.splice(0, 1) // ignorer le coût xp le plus élevé .splice(0, 1) // ignorer le coût xp le plus élevé
.reduce((a, b) => a + b, 0) .reduce(Misc.sum(), 0)
).reduce((a, b) => a + b, 0); ).reduce(Misc.sum(), 0);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -153,10 +169,11 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeCompetenceXPCost(competence) { static computeCompetenceXPCost(competence) {
let xp = RdDItemCompetence.getDeltaXp(competence.data.base, competence.data.niveau ?? competence.data.base); const compData = Misc.data(competence);
xp += competence.data.xp ?? 0; let xp = RdDItemCompetence.getDeltaXp(compData.data.base, compData.data.niveau ?? compData.data.base);
if (competence.name.includes('Thanatos')) xp *= 2; /// Thanatos compte double ! xp += compData.data.xp ?? 0;
xp += competence.data.xp_sort ?? 0; if (compData.name.includes('Thanatos')) xp *= 2; /// Thanatos compte double !
xp += compData.data.xp_sort ?? 0;
return xp; return xp;
} }
@ -165,10 +182,10 @@ export class RdDItemCompetence extends Item {
let economie = 0; let economie = 0;
for (let troncList of competenceTroncs) { for (let troncList of competenceTroncs) {
let list = troncList.map(name => RdDItemCompetence.findCompetence(competences, name)) 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 .sort(Misc.descending(c => Misc.templateData(c).niveau)); // tri du plus haut au plus bas
list.splice(0, 1); // ignorer la plus élevée list.splice(0, 1); // ignorer la plus élevée
list.forEach(c => { list.map(c => Misc.templateData(c)).forEach(tplData => {
economie += RdDItemCompetence.getDeltaXp(c.data.base, Math.min(c.data.niveau, 0)); economie += RdDItemCompetence.getDeltaXp(tplData.base, Math.min(tplData.niveau, 0));
}); });
} }
return economie; return economie;
@ -216,7 +233,7 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static getCompetenceXp(niveau) { static getCompetenceXp(niveau) {
RdDItemCompetence._valideNiveau(niveau); RdDItemCompetence._valideNiveau(niveau);
return niveau < -10 ? 0 : competence_xp_par_niveau[niveau + 10]; return niveau < -10 ? 0 : xp_par_niveau[niveau + 10];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -228,16 +245,16 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static _valideNiveau(niveau) { static _valideNiveau(niveau) {
if (niveau < -11 || niveau > competence_niveau_max) { if (niveau < -11 || niveau > niveau_max) {
console.warn(`Niveau ${niveau} en dehors des niveaux de compétences: [-11, ${competence_niveau_max} ]`); console.warn(`Niveau ${niveau} en dehors des niveaux de compétences: [-11, ${niveau_max} ]`);
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeResumeArchetype(competences) { static computeResumeArchetype(competences) {
const archetype = RdDItemCompetence.getLimitesArchetypes(); const archetype = RdDItemCompetence.getLimitesArchetypes();
competences.forEach(it => { competences.map(it => Math.max(0, Misc.templateData(it).niveau_archetype))
let niveau = Math.max(0, it.data.niveau_archetype); .forEach(niveau => {
archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 }; archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 };
archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1; archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1;
}); });

View File

@ -52,13 +52,16 @@ export class RdDItemSheet extends ItemSheet {
console.log("3", objectData); console.log("3", objectData);
let formData ={ let formData ={
title: this.title, title: objectData.name,
id: objectData.id, id: objectData.id,
type: objectData.type, type: objectData.type,
img: objectData.img, img: objectData.img,
name: objectData.name, name: objectData.name,
data: objectData.data, data: objectData.data,
isGM: game.user.isGM isGM: game.user.isGM,
owner: this.document.isOwner,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
} }
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences(); formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences();
if ( formData.type == 'tache' || formData.type == 'livre' || formData.type == 'meditation' || formData.type == 'oeuvre') { if ( formData.type == 'tache' || formData.type == 'livre' || formData.type == 'meditation' || formData.type == 'oeuvre') {
@ -90,15 +93,15 @@ export class RdDItemSheet extends ItemSheet {
if (!this.options.editable) return; if (!this.options.editable) return;
// Select competence categorie // Select competence categorie
html.find("#categorie").on("click", this._onClickSelectCategorie.bind(this) ); html.find(".categorie").on("click", this._onClickSelectCategorie.bind(this) );
html.find('#sheet-competence-xp').change((event) => { html.find('.sheet-competence-xp').change((event) => {
if ( this.object.data.type == 'competence') { if ( this.object.data.type == 'competence') {
RdDUtility.checkThanatosXP( this.object.data.name ); RdDUtility.checkThanatosXP( this.object.data.name );
} }
} ); } );
html.find('#creer-tache-livre').click((event) => { html.find('.creer-tache-livre').click((event) => {
let actorId = event.currentTarget.attributes['data-actor-id'].value; let actorId = event.currentTarget.attributes['data-actor-id'].value;
let actor = game.actors.get( actorId ); let actor = game.actors.get( actorId );
actor.creerTacheDepuisLivre( this.item ); actor.creerTacheDepuisLivre( this.item );

View File

@ -18,6 +18,24 @@ export class Misc {
return isPositiveNumber ? "+" + number : number return isPositiveNumber ? "+" + number : number
} }
static sum() {
return (a, b) => a + b;
}
static ascending(orderFunction) {
return (a, b) => Misc.sortingBy(orderFunction(a), orderFunction(b));
}
static descending(orderFunction) {
return (a, b) => Misc.sortingBy(orderFunction(b), orderFunction(a));
}
static sortingBy(a, b) {
if (a > b) return 1;
if (a < b) return -1;
return 0;
}
/** /**
* Converts the value to an integer, or to 0 if undefined/null/not representing integer * Converts the value to an integer, or to 0 if undefined/null/not representing integer
* @param {*} value value to convert to an integer using parseInt * @param {*} value value to convert to an integer using parseInt

View File

@ -1,4 +1,5 @@
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
const tableCaracDerivee = { const tableCaracDerivee = {
// xp: coût pour passer du niveau inférieur à ce niveau // xp: coût pour passer du niveau inférieur à ce niveau
@ -61,7 +62,7 @@ export class RdDCarac {
static computeTotal(carac, beaute = undefined) { static computeTotal(carac, beaute = undefined) {
const total = Object.values(carac).filter(c => !c.derivee) const total = Object.values(carac).filter(c => !c.derivee)
.map(it => parseInt(it.value)) .map(it => parseInt(it.value))
.reduce((a, b) => a + b, 0); .reduce(Misc.sum(), 0);
const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0); const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0);
return total + beauteSuperieur10; return total + beauteSuperieur10;
} }

View File

@ -165,13 +165,7 @@ export class RdDCombatManager extends Combat {
} }
} }
} }
return armesEquipe.sort((a, b) => { return armesEquipe.sort(Misc.ascending(armeData => armeData.name + (armeData.data.mainInfo ?? '')));
const nameA = a.name + (a.data.mainInfo ?? '');
const nameB = b.name + (b.data.mainInfo ?? '');
if (nameA > nameB) return 1;
if (nameA < nameB) return -1;
return 0;
});
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -808,8 +802,8 @@ export class RdDCombat {
const paramChatDefense = { const paramChatDefense = {
passeArme: attackerRoll.passeArme, passeArme: attackerRoll.passeArme,
essais: attackerRoll.essais, essais: attackerRoll.essais,
defender: this.defender, defender: Misc.data(this.defender),
attacker: this.attacker, attacker: Misc.data(this.attacker),
attackerId: this.attackerId, attackerId: this.attackerId,
esquiveUsage: esquiveUsage, esquiveUsage: esquiveUsage,
defenderTokenId: this.defenderTokenId, defenderTokenId: this.defenderTokenId,
@ -851,7 +845,7 @@ export class RdDCombat {
attackerId: this.attacker?.data._id, attackerId: this.attacker?.data._id,
defenderId: this.defender?.data._id, defenderId: this.defender?.data._id,
defenderTokenId: this.defenderTokenId, defenderTokenId: this.defenderTokenId,
defenderRoll: duplicate(defenderRoll), defenderRoll: defenderRoll,
paramChatDefense: paramChatDefense, paramChatDefense: paramChatDefense,
rollMode: true rollMode: true
} }
@ -887,7 +881,7 @@ export class RdDCombat {
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name), whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', { content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', {
attackerId: this.attackerId, attackerId: this.attackerId,
attacker: this.attacker, attacker: Misc.data(this.attacker),
defenderTokenId: this.defenderTokenId, defenderTokenId: this.defenderTokenId,
essais: attackerRoll.essais essais: attackerRoll.essais
}) })

View File

@ -144,10 +144,10 @@ export class RdDRoll extends Dialog {
console.log(rollData); console.log(rollData);
// Update html, according to data // Update html, according to data
if (rollData.competence) { if (rollData.competence) {
let compData = rollData.competence.data.data || rollData.competence.data; const defaut_carac = Misc.templateData(rollData.competence).defaut_carac;
// Set the default carac from the competence item // Set the default carac from the competence item
rollData.selectedCarac = rollData.carac[compData.defaut_carac]; rollData.selectedCarac = rollData.carac[defaut_carac];
$("#carac").val(compData.defaut_carac); $("#carac").val(defaut_carac);
} }
if (rollData.selectedSort) { if (rollData.selectedSort) {
$("#draconic").val(rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer $("#draconic").val(rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer
@ -184,8 +184,10 @@ export class RdDRoll extends Dialog {
let sortKey = Misc.toInt(event.currentTarget.value); let sortKey = Misc.toInt(event.currentTarget.value);
this.rollData.selectedSort = this.rollData.sortList[sortKey]; // Update the selectedCarac this.rollData.selectedSort = this.rollData.sortList[sortKey]; // Update the selectedCarac
this.rollData.bonus = RdDItemSort.getCaseBonus(this.rollData.selectedSort, this.rollData.tmr.coord); this.rollData.bonus = RdDItemSort.getCaseBonus(this.rollData.selectedSort, this.rollData.tmr.coord);
this.rollData.diffLibre = RdDItemSort.getDifficulte(this.rollData.selectedSort, -7)
RdDItemSort.setCoutReveReel(this.rollData.selectedSort); RdDItemSort.setCoutReveReel(this.rollData.selectedSort);
$("#draconic").val(this.rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer $("#draconic").val(this.rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer
$("#diffLibre").val(this.rollData.diffLibre);
this.updateRollResult(); this.updateRollResult();
}); });
html.find('#ptreve-variable').change((event) => { html.find('#ptreve-variable').change((event) => {

View File

@ -319,28 +319,28 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async _tentativeMaitrise(rencontreData, presentCite) { async _tentativeMaitrise(rencData, presentCite) {
console.log("-> matriser", rencontreData); console.log("-> matriser", rencData);
rencontreData.reve = this.actor.getReveActuel(); rencData.reve = this.actor.getReveActuel();
rencontreData.etat = this.actor.getEtatGeneral(); rencData.etat = this.actor.getEtatGeneral();
RollDataAjustements.calcul(rencontreData, this.actor); RollDataAjustements.calcul(rencData, this.actor);
rencontreData.rolled = rencontreData.presentCite rencData.rolled = rencData.presentCite
? this._rollPresentCite(rencontreData) ? this._rollPresentCite(rencData)
: await RdDResolutionTable.roll(rencontreData.reve, RollDataAjustements.sum(rencontreData.ajustements)); : await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements));
let postProcess = await TMRRencontres.gererRencontre(this, rencontreData); let postProcess = await TMRRencontres.gererRencontre(this, rencData);
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencontreData) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencData)
}); });
if (postProcess) { if (postProcess) {
/** Gère les rencontres avec du post-processing (passeur, messagers, tourbillons, ...) */ /** Gère les rencontres avec du post-processing (passeur, messagers, tourbillons, ...) */
await postProcess(this, rencontreData); await postProcess(this, rencData);
} }
else { else {
this.currentRencontre = undefined; this.currentRencontre = undefined;
@ -350,12 +350,12 @@ export class RdDTMRDialog extends Dialog {
if (this.checkQuitterTMR()) { if (this.checkQuitterTMR()) {
return; return;
} }
else if (rencontreData.rolled.isEchec && rencontreData.rencontre.isPersistant) { else if (rencData.rolled.isEchec && rencData.rencontre.isPersistant) {
setTimeout(() => { setTimeout(() => {
rencontreData.nbRounds++; rencData.nbRounds++;
this.cumulFatigue += this.fatigueParCase; this.cumulFatigue += this.fatigueParCase;
this._tentativeMaitrise(rencontreData); this._tentativeMaitrise(rencData);
this._deleteTmrMessages(rencontreData.actor, rencontreData.nbRounds); this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
}, 2000); }, 2000);
} }
} }

View File

@ -667,8 +667,9 @@ export class RdDUtility {
label: "Annuler" label: "Annuler"
} }
} }
if (objet.data.type == 'conteneur' && objet.data.data.contenu.length > 0) { const docData = Misc.data(objet);
msgTxt += "<br>Cet objet est aussi un conteneur avec du contenu : choisissez l'option de suppression"; if (docData.type == 'conteneur' && docData.data.contenu.length > 0) {
msgTxt += "<br>Ce conteneur n'est pas vide. Choisissez l'option de suppression";
buttons['deleteall'] = { buttons['deleteall'] = {
icon: '<i class="fas fa-check"></i>', icon: '<i class="fas fa-check"></i>',
label: "Supprimer le conteneur et tout son contenu", label: "Supprimer le conteneur et tout son contenu",

View File

@ -8,11 +8,11 @@ import { TMRType } from "./tmr-utility.js";
const typeRencontres = { const typeRencontres = {
messager: { messager: {
msgSucces: (data) => `Le ${data.rencontre.name} vous propose d'emmener le message de votre un sort à ${data.rencontre.force} cases ${data.tmr.label}.`, msgSucces: (rencData) => `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort à ${rencData.rencontre.force} cases ${rencData.tmr.label}.`,
msgEchec: (data) => `Le ${data.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`, msgEchec: (rencData) => `Le ${rencData.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`,
postSucces: (tmrDialog, data) => { postSucces: (tmrDialog, rencData) => {
tmrDialog.setStateRencontre(data.rencontre.type); tmrDialog.setStateRencontre(rencData.rencontre.type);
tmrDialog.choisirCasePortee(data.tmr.coord, data.rencontre.force); tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force);
}, },
poesieSucces: { poesieSucces: {
reference: "La chevelure, Charles Baudelaire", reference: "La chevelure, Charles Baudelaire",
@ -28,11 +28,11 @@ const typeRencontres = {
}, },
passeur: { passeur: {
msgSucces: (data) => `Le ${data.rencontre.name} vous propose de vous transporter à ${data.rencontre.force} cases des ${data.tmr.label}.`, msgSucces: (rencData) => `Le ${rencData.rencontre.name} vous propose de vous transporter à ${rencData.rencontre.force} cases des ${rencData.tmr.label}.`,
msgEchec: (data) => `Le prix que demande le ${data.rencontre.name} est trop élevé, vous êtes réduit à poursuivre votre chemin par vos propres moyens.`, msgEchec: (rencData) => `Le prix que demande le ${rencData.rencontre.name} est trop élevé, vous êtes réduit à poursuivre votre chemin par vos propres moyens.`,
postSucces: (tmrDialog, data) => { postSucces: (tmrDialog, rencData) => {
tmrDialog.setStateRencontre(data.rencontre.type); tmrDialog.setStateRencontre(rencData.rencontre.type);
tmrDialog.choisirCasePortee(data.tmr.coord, data.rencontre.force); tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force);
}, },
poesieSucces: { poesieSucces: {
reference: "Femmes damnées (2), Charles Baudelaire", reference: "Femmes damnées (2), Charles Baudelaire",
@ -49,9 +49,9 @@ const typeRencontres = {
}, },
fleur: { fleur: {
msgSucces: (data) => `Vous cueillez la ${data.rencontre.name}, son parfum vous apporte ${data.rencontre.force} points de Rêve.`, msgSucces: (rencData) => `Vous cueillez la ${rencData.rencontre.name}, son parfum vous apporte ${rencData.rencontre.force} points de Rêve.`,
msgEchec: (data) => `La ${data.rencontre.name} se fâne et disparaît entre vos doigts.`, msgEchec: (rencData) => `La ${rencData.rencontre.name} se fâne et disparaît entre vos doigts.`,
postSucces: (tmrDialog, data) => tmrDialog.actor.reveActuelIncDec(data.rencontre.force), postSucces: (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(rencData.rencontre.force),
poesieSucces: { poesieSucces: {
reference: "L'Ennemi, Charles Baudelaire", reference: "L'Ennemi, Charles Baudelaire",
extrait: `Et qui sait si les fleurs nouvelles que je rêve extrait: `Et qui sait si les fleurs nouvelles que je rêve
@ -66,9 +66,9 @@ const typeRencontres = {
}, },
mangeur: { mangeur: {
msgSucces: (data) => `Le ${data.rencontre.name} claque de sa machoire dans le vide avant de fuir.`, msgSucces: (rencData) => `Le ${rencData.rencontre.name} claque de sa machoire dans le vide avant de fuir.`,
msgEchec: (data) => `Le ${data.rencontre.name} croque votre Rêve ! Il emporte ${data.rencontre.force} de vos points de rêve actuels`, msgEchec: (rencData) => `Le ${rencData.rencontre.name} croque votre Rêve ! Il emporte ${rencData.rencontre.force} de vos points de rêve actuels`,
postEchec: (tmrDialog, data) => tmrDialog.actor.reveActuelIncDec(-data.rencontre.force), postEchec: (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(-rencData.rencontre.force),
poesieSucces: { poesieSucces: {
reference: "Conseil, Victor Hugo", reference: "Conseil, Victor Hugo",
extrait: `Rois ! la bure est souvent jalouse du velours. extrait: `Rois ! la bure est souvent jalouse du velours.
@ -85,16 +85,16 @@ const typeRencontres = {
}, },
changeur: { changeur: {
msgSucces: (data) => `Le ${data.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[data.tmr.type].name} de votre choix en échange de sa liberté.`, msgSucces: (rencData) => `Le ${rencData.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[rencData.tmr.type].name} de votre choix en échange de sa liberté.`,
msgEchec: (data) => { msgEchec: (rencData) => {
data.newTMR = TMRUtility.getTMRAleatoire(it => it.type = data.tmr.type); rencData.newTMR = TMRUtility.getTMRAleatoire(it => it.type = rencData.tmr.type);
return `Le ${data.rencontre.name} vous embobine avec des promesses, et vous transporte en ${data.newTMR.label} sans attendre votre avis.`; return `Le ${rencData.rencontre.name} vous embobine avec des promesses, et vous transporte en ${rencData.newTMR.label} sans attendre votre avis.`;
}, },
postSucces: (tmrDialog, data) => { postSucces: (tmrDialog, rencData) => {
tmrDialog.setStateRencontre(data.rencontre.type); tmrDialog.setStateRencontre(rencData.rencontre.type);
tmrDialog.choisirCaseType(data.tmr.type); tmrDialog.choisirCaseType(rencData.tmr.type);
}, },
postEchec: (tmrDialog, data) => tmrDialog.forceDemiRevePosition(data.newTMR.coord), postEchec: (tmrDialog, rencData) => tmrDialog.forceDemiRevePosition(rencData.newTMR.coord),
poesieSucces: { poesieSucces: {
reference: "Caligula - IIIème chant, Gérard de Nerval", reference: "Caligula - IIIème chant, Gérard de Nerval",
extrait: `Allez, que le caprice emporte extrait: `Allez, que le caprice emporte
@ -111,9 +111,9 @@ const typeRencontres = {
}, },
briseur: { briseur: {
msgSucces: (data) => `Le ${data.rencontre.name} tente vainement de vous déconcentrer, avant de fuir sans demander son reste.`, msgSucces: (rencData) => `Le ${rencData.rencontre.name} tente vainement de vous déconcentrer, avant de fuir sans demander son reste.`,
msgEchec: (data) => `Le ${data.rencontre.name} vous déconcentre au point de briser votre demi-rêve.`, msgEchec: (rencData) => `Le ${rencData.rencontre.name} vous déconcentre au point de briser votre demi-rêve.`,
postEchec: (tmrDialog, data) => tmrDialog.close(), postEchec: (tmrDialog, rencData) => tmrDialog.close(),
poesieSucces: { poesieSucces: {
reference: "Rêve de Dragon, Denis Gerfaud", reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `La légende affirme que ce sont les Gnomes qui furent extrait: `La légende affirme que ce sont les Gnomes qui furent
@ -134,8 +134,8 @@ const typeRencontres = {
}, },
reflet: { reflet: {
msgSucces: (data) => `Le ${data.rencontre.name} s'estompe dans l'oubli.`, msgSucces: (rencData) => `Le ${rencData.rencontre.name} s'estompe dans l'oubli.`,
msgEchec: (data) => `Vous êtes submergé par un ${data.rencontre.name}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!`, msgEchec: (rencData) => `Vous êtes submergé par un ${rencData.rencontre.name}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!`,
poesieSucces: { poesieSucces: {
reference: "Une charogne, Charles Baudelaire", reference: "Une charogne, Charles Baudelaire",
extrait: `Les formes s'effaçaient et n'étaient plus qu'un rêve, extrait: `Les formes s'effaçaient et n'étaient plus qu'un rêve,
@ -152,9 +152,9 @@ const typeRencontres = {
}, },
passeurfou: { passeurfou: {
msgSucces: (data) => `Le ${data.rencontre.name} tente vainement de découvrir où vous avez caché vos réserves. Vous le chassez, et en déroute il part harceler un autre voyageur du rêve.`, msgSucces: (rencData) => `Le ${rencData.rencontre.name} tente vainement de découvrir où vous avez caché vos réserves. Vous le chassez, et en déroute il part harceler un autre voyageur du rêve.`,
msgEchec: (data) => TMRRencontres.msgEchecPasseurFou(data), msgEchec: (rencData) => TMRRencontres.msgEchecPasseurFou(rencData),
postEchec: (tmrDialog, data) => TMRRencontres.postEchecPasseurFou(tmrDialog, data), postEchec: (tmrDialog, rencData) => TMRRencontres.postEchecPasseurFou(tmrDialog, rencData),
poesieSucces: { poesieSucces: {
reference: "Un Fou et un Sage, Jean de La Fontaine", reference: "Un Fou et un Sage, Jean de La Fontaine",
extrait: `Certain Fou poursuivait à coups de pierre un Sage. extrait: `Certain Fou poursuivait à coups de pierre un Sage.
@ -174,9 +174,9 @@ const typeRencontres = {
}, },
tbblanc: { tbblanc: {
msgSucces: (data) => `Le ${data.rencontre.name} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.`, msgSucces: (rencData) => `Le ${rencData.rencontre.name} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.`,
msgEchec: (data) => `Le souffle du ${data.rencontre.name} vous déstabilise et vous emmène dans un nuage de poussière.`, msgEchec: (rencData) => `Le souffle du ${rencData.rencontre.name} vous déstabilise et vous emmène dans un nuage de poussière.`,
postEchec: (tmrDialog, data) => TMRRencontres.onPostEchecTourbillon(tmrDialog, data, 1), postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 1),
poesieSucces: { poesieSucces: {
reference: "Rêve de Dragon, Denis Gerfaud", reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `Le Premier Âge fut appelé l'Âge des Dragons. Ce fut le commencement extrait: `Le Premier Âge fut appelé l'Âge des Dragons. Ce fut le commencement
@ -191,9 +191,9 @@ const typeRencontres = {
}, },
tbnoir: { tbnoir: {
msgSucces: (data) => `Le ${data.rencontre.name} orageux vous enveloppe de fureur et d'éclairs, vous tenez bon face à la tempête qui s'éloigne sans vous éloigner de votre chemin.`, msgSucces: (rencData) => `Le ${rencData.rencontre.name} orageux vous enveloppe de fureur et d'éclairs, vous tenez bon face à la tempête qui s'éloigne sans vous éloigner de votre chemin.`,
msgEchec: (data) => `Le ${data.rencontre.name} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.`, msgEchec: (rencData) => `Le ${rencData.rencontre.name} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.`,
postEchec: (tmrDialog, data) => TMRRencontres.onPostEchecTourbillon(tmrDialog, data, 2), postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 2),
poesieSucces: { poesieSucces: {
reference: "Rêve de Dragon, Denis Gerfaud", reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `Car le Second Âge fut bel et bien celui des Magiciens. Durant cette période, les extrait: `Car le Second Âge fut bel et bien celui des Magiciens. Durant cette période, les
@ -207,9 +207,9 @@ const typeRencontres = {
}, },
tbrouge: { tbrouge: {
msgSucces: (data) => `Le ${data.rencontre.name} s'abat avec violence mais vous êtes plus rapide et parvenez à lui échapper.`, msgSucces: (rencData) => `Le ${rencData.rencontre.name} s'abat avec violence mais vous êtes plus rapide et parvenez à lui échapper.`,
msgEchec: (data) => `Le ${data.rencontre.name} vous frappe de milliers de morsure et vous malmène à travers les terres médianes.`, msgEchec: (rencData) => `Le ${rencData.rencontre.name} vous frappe de milliers de morsure et vous malmène à travers les terres médianes.`,
postEchec: (tmrDialog, data) => TMRRencontres.onPostEchecTourbillonRouge(tmrDialog, data), postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillonRouge(tmrDialog, rencData),
poesieSucces: { poesieSucces: {
reference: "Qu'est-ce de votre vie ? une bouteille molle, Jean-Baptiste Chassignet", reference: "Qu'est-ce de votre vie ? une bouteille molle, Jean-Baptiste Chassignet",
extrait: `Qu'est-ce de votre vie ? un tourbillon rouant extrait: `Qu'est-ce de votre vie ? un tourbillon rouant
@ -228,10 +228,10 @@ const typeRencontres = {
}, },
rdd: { rdd: {
msgSucces: (data) => `A tout seigneur, tout honneur, vous faites face à un ${data.rencontre.name}. Vous le maîtrisez et récupérez ses rêves. Vous gagnez ses ${data.rencontre.force} points de rêve`, msgSucces: (rencData) => `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. Vous le maîtrisez et récupérez ses rêves. Vous gagnez ses ${rencData.rencontre.force} points de rêve`,
msgEchec: (data) => `A tout seigneur, tout honneur, vous faites face à un ${data.rencontre.name}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez ${data.rolled.isETotal ? 'deux queues' : 'une queue'} de dragon!`, msgEchec: (rencData) => `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez ${rencData.rolled.isETotal ? 'deux queues' : 'une queue'} de dragon!`,
postSucces: (tmrDialog, data) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, data), postSucces: (tmrDialog, rencData) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, rencData),
postEchec: (tmrDialog, data) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, data), postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, rencData),
poesieSucces: { poesieSucces: {
reference: "Rêve de Dragon, Denis Gerfaud", reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `Le monde est Rêve de Dragons, mais nous ne savons extrait: `Le monde est Rêve de Dragons, mais nous ne savons
@ -407,58 +407,58 @@ export class TMRRencontres {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async gererRencontre(tmrDialog, data) { static async gererRencontre(tmrDialog, rencData) {
let gestion = TMRRencontres.getGestionRencontre(data.rencontre.type); let gestion = TMRRencontres.getGestionRencontre(rencData.rencontre.type);
if (data.rolled.isSuccess) { if (rencData.rolled.isSuccess) {
data.message = gestion.msgSucces(data); rencData.message = gestion.msgSucces(rencData);
if (data.nbRounds > 1) { if (rencData.nbRounds > 1) {
data.message += ` Au total, vous avez passé ${data.nbRounds} rounds à vous battre!`; rencData.message += ` Au total, vous avez passé ${rencData.nbRounds} rounds à vous battre!`;
} }
data.poesie = gestion.poesieSucces; rencData.poesie = gestion.poesieSucces;
return gestion.postSucces; return gestion.postSucces;
} }
data.message = gestion.msgEchec(data); rencData.message = gestion.msgEchec(rencData);
if (data.nbRounds > 1) { if (rencData.nbRounds > 1) {
data.message += ` Vous avez passé ${data.nbRounds} rounds à lutter!`; rencData.message += ` Vous avez passé ${rencData.nbRounds} rounds à lutter!`;
} }
data.poesie = gestion.poesieEchec; rencData.poesie = gestion.poesieEchec;
return gestion.postEchec; return gestion.postEchec;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static msgEchecPasseurFou(data) { static msgEchecPasseurFou(tmrData) {
data.sortReserve = data.actor.data.data.reve.reserve.list[0]; tmrData.sortReserve = Misc.templateData(tmrData.actor).reve.reserve.list[0];
if (data.sortReserve) { if (tmrData.sortReserve) {
// Passeur fou positionne sur la case d'un ort en réserve // TODO : Choisir le sort le plus loin ou au hasard // Passeur fou positionne sur la case d'un ort en réserve // TODO : Choisir le sort le plus loin ou au hasard
data.newTMR = TMRUtility.getTMR(data.sortReserve.coord); tmrData.newTMR = TMRUtility.getTMR(tmrData.sortReserve.coord);
} else { } else {
// Déplacement aléatoire de la force du Passeur Fou // Déplacement aléatoire de la force du Passeur Fou
const newCoord = Misc.rollOneOf(TMRUtility.getTMRPortee(data.tmr.coord, data.rencontre.force)); const newCoord = Misc.rollOneOf(TMRUtility.getTMRPortee(tmrData.tmr.coord, tmrData.rencontre.force));
data.newTMR = TMRUtility.getTMR(newCoord); tmrData.newTMR = TMRUtility.getTMR(newCoord);
} }
if (data.sortReserve) { if (tmrData.sortReserve) {
return `Le ${data.rencontre.name} vous dérobe la clé de vos sorts. Vous vous saisissez de lui, mais dans un nuage violet, il vous emporte en ${data.newTMR.label} déclencher votre sort en réserve de ${data.sortReserve.name}.`; return `Le ${tmrData.rencontre.name} vous dérobe la clé de vos sorts. Vous vous saisissez de lui, mais dans un nuage violet, il vous emporte en ${tmrData.newTMR.label} déclencher votre sort en réserve de ${tmrData.sortReserve.name}.`;
} }
else { else {
return `Le ${data.rencontre.name} tente de vous dérober la clé de vos sorts. Ne la trouvant pas, il déclenche un nuage violet et vous emporte en ${data.newTMR.label}`; return `Le ${tmrData.rencontre.name} tente de vous dérober la clé de vos sorts. Ne la trouvant pas, il déclenche un nuage violet et vous emporte en ${tmrData.newTMR.label}`;
} }
} }
static async postEchecPasseurFou(tmrDialog, data) { static async postEchecPasseurFou(tmrDialog, tmrData) {
if (data.sortReserve) { if (tmrData.sortReserve) {
await tmrDialog.processSortReserve(data.sortReserve); await tmrDialog.processSortReserve(tmrData.sortReserve);
} }
await tmrDialog.forceDemiRevePosition(data.newTMR.coord); await tmrDialog.forceDemiRevePosition(tmrData.newTMR.coord);
if (data.sortReserve) { if (tmrData.sortReserve) {
tmrDialog.close(); tmrDialog.close();
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async onPostEchecTourbillon(tmrDialog, data, cases) { static async onPostEchecTourbillon(tmrDialog, tmrData, cases) {
await data.actor.reveActuelIncDec(-cases); await tmrData.actor.reveActuelIncDec(-cases);
await TMRRencontres._toubillonner(tmrDialog, data.actor, cases); await TMRRencontres._toubillonner(tmrDialog, tmrData.actor, cases);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -469,22 +469,22 @@ export class TMRRencontres {
} }
static async _toubillonner(tmrDialog, actor, cases) { static async _toubillonner(tmrDialog, actor, cases) {
let coord = actor.data.data.reve.tmrpos.coord; let coord = Misc.templateData(actor).reve.tmrpos.coord;
for (let i = 0; i < cases; i++) { for (let i = 0; i < cases; i++) {
coord = TMRUtility.deplaceTMRAleatoire(actor, coord).coord; coord = TMRUtility.deplaceTMRAleatoire(actor, coord).coord;
} }
await tmrDialog.forceDemiRevePosition(coord) await tmrDialog.forceDemiRevePosition(coord)
} }
static async onPostSuccessReveDeDragon(tmrDialog, data) { static async onPostSuccessReveDeDragon(tmrDialog, tmrData) {
if (data.rolled.isPart) { if (tmrData.rolled.isPart) {
await data.actor.appliquerExperience(data.rolled, 'reve', data.competence); await tmrData.actor.appliquerExperience(tmrData.rolled, 'reve', tmrData.competence);
} }
await data.actor.resultCombatReveDeDragon(data); await tmrData.actor.resultCombatReveDeDragon(tmrData);
} }
static async onPostEchecReveDeDragon(tmrDialog, data) { static async onPostEchecReveDeDragon(tmrDialog, tmrData) {
await data.actor.resultCombatReveDeDragon(data); await tmrData.actor.resultCombatReveDeDragon(tmrData);
tmrDialog.close(); tmrDialog.close();
} }
} }

View File

@ -1,5 +1,6 @@
import { ChatUtility } from "../chat-utility.js"; import { ChatUtility } from "../chat-utility.js";
import { Grammar } from "../grammar.js"; import { Grammar } from "../grammar.js";
import { Misc } from "../misc.js";
import { RdDRollTables } from "../rdd-rolltables.js"; import { RdDRollTables } from "../rdd-rolltables.js";
import { tmrColors, tmrConstants, tmrTokenZIndex, TMRUtility } from "../tmr-utility.js"; import { tmrColors, tmrConstants, tmrTokenZIndex, TMRUtility } from "../tmr-utility.js";
import { Draconique } from "./draconique.js"; import { Draconique } from "./draconique.js";
@ -14,22 +15,22 @@ export class UrgenceDraconique extends Draconique {
match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); } match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); }
manualMessage() { return false } manualMessage() { return false }
async onActorCreateOwned(actor, queue) { async onActorCreateOwned(actor, queue) {
let coordSortsReserve = (actor.data.data.reve.reserve?.list.map(it => it.coord)) ?? []; const coordSortsReserve = (Misc.templateData(actor).reve.reserve?.list.map(it => it.coord)) ?? [];
if (coordSortsReserve.length == 0) { if (coordSortsReserve.length == 0) {
// La queue se transforme en idée fixe // La queue se transforme en idée fixe
let ideeFixe = await RdDRollTables.getIdeeFixe(); const ideeFixe = await RdDRollTables.getIdeeFixe();
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: `En l'absence de sorts en réserve, l'urgence draconique de ${actor.name} se transforme en ${queue.name}` content: `En l'absence de sorts en réserve, l'urgence draconique de ${actor.name} se transforme en ${ideeFixe.name}`
}); });
await actor.createEmbeddedDocuments('Item',[ideeFixe]); await actor.createEmbeddedDocuments('Item',[ideeFixe]);
await actor.deleteOwnedItem(queue._id); await actor.deleteOwnedItem(queue._id);
return; return;
} }
else { else {
let demiReve = actor.getDemiReve(); const demiReve = actor.getDemiReve();
coordSortsReserve.sort((a, b) => TMRUtility.distanceTMR(a, demiReve) - TMRUtility.distanceTMR(b, demiReve)); coordSortsReserve.sort(Misc.ascending(t => TMRUtility.distanceTMR(t, demiReve)));
let tmr = TMRUtility.getTMR(coordSortsReserve[0]); const tmr = TMRUtility.getTMR(coordSortsReserve[0]);
await this.createCaseTmr(actor, 'Urgence draconique: ' + tmr.label, tmr, queue._id); await this.createCaseTmr(actor, 'Urgence draconique: ' + tmr.label, tmr, queue._id);
} }
} }

View File

@ -863,7 +863,6 @@
<article class="flexcol"> <article class="flexcol">
<h3>Biographie : </h3> <h3>Biographie : </h3>
<div class="form-group editor"> <div class="form-group editor">
{{log 'biographie' data.biographie}}
{{editor content=data.biographie target="data.biographie" button=true owner=owner editable=editable}} {{editor content=data.biographie target="data.biographie" button=true owner=owner editable=editable}}
</div> </div>
<h3>Notes : </h3> <h3>Notes : </h3>

View File

@ -27,7 +27,7 @@
<ol class="carac-list alterne-list"> <ol class="carac-list alterne-list">
<li class="competence flexrow list-item" data-attribute="{{key}}"> <li class="competence flexrow list-item" data-attribute="{{key}}">
<span class="carac-label flexrow" name="categorie">Catégorie</span> <span class="carac-label flexrow" name="categorie">Catégorie</span>
<select name="data.categorie" id="categorie" data-dtype="String"> <select name="data.categorie" class="categorie" data-dtype="String">
{{#select data.categorie}} {{#select data.categorie}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html"}} {{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html"}}
{{/select}} {{/select}}

View File

@ -1,14 +1,14 @@
<div data-passearme="{{passeArme}}"> <div data-passearme="{{passeArme}}">
<h4 class="rdd-roll-etotal"><strong>Echec total en attaque</strong></h4> <h4 class="rdd-roll-etotal"><strong>Echec total en attaque</strong></h4>
<br> <br>
{{#if (eq attacker.data.type 'personnage')}} {{#if (eq attacker.type 'personnage')}}
{{#unless essais.attaqueChance}} {{#unless essais.attaqueChance}}
<a class='chat-card-button' id='appel-chance-attaque' data-attackerId='{{attackerId}}' <a class='chat-card-button' id='appel-chance-attaque' data-attackerId='{{attackerId}}'
data-defenderTokenId='{{defenderTokenId}}'>Faire appel à la chance</a> data-defenderTokenId='{{defenderTokenId}}'>Faire appel à la chance</a>
</a> </a>
<br> <br>
{{/unless}} {{/unless}}
{{#if (gt attacker.data.data.compteurs.destinee.value 0)}} {{#if (gt attacker.data.compteurs.destinee.value 0)}}
<a class='chat-card-button' id='appel-destinee-attaque' data-attackerId='{{attackerId}}' <a class='chat-card-button' id='appel-destinee-attaque' data-attackerId='{{attackerId}}'
data-defenderTokenId='{{defenderTokenId}}'>Utiliser la destinée</a> data-defenderTokenId='{{defenderTokenId}}'>Utiliser la destinée</a>
</a> </a>

View File

@ -19,14 +19,14 @@
{{#unless (eq surprise 'totale')}} {{#unless (eq surprise 'totale')}}
{{#if essais.defense}} {{#if essais.defense}}
{{#unless essais.defenseChance}} {{#unless essais.defenseChance}}
{{#if (eq defender.data.type 'personnage')}} {{#if (eq defender.type 'personnage')}}
<a class='chat-card-button' id='appel-chance-defense' data-attackerId='{{attackerId}}' <a class='chat-card-button' id='appel-chance-defense' data-attackerId='{{attackerId}}'
data-defenderTokenId='{{defenderTokenId}}'>Faire appel à la chance</a> data-defenderTokenId='{{defenderTokenId}}'>Faire appel à la chance</a>
</a> </a>
<br> <br>
{{/if}} {{/if}}
{{#if (eq defender.data.type 'personnage')}} {{#if (eq defender.type 'personnage')}}
{{#if (gt defender.data.data.compteurs.destinee.value 0)}} {{#if (gt defender.data.compteurs.destinee.value 0)}}
<a class='chat-card-button' id='appel-destinee-defense' data-attackerId='{{attackerId}}' <a class='chat-card-button' id='appel-destinee-defense' data-attackerId='{{attackerId}}'
data-defenderTokenId='{{defenderTokenId}}'>Utiliser la destinée</a> data-defenderTokenId='{{defenderTokenId}}'>Utiliser la destinée</a>
</a> </a>

View File

@ -15,7 +15,7 @@
Vous ne parvenez pas à vaincre le Rêve de Dragon, et prennez un violent coup de queue. Vous ne parvenez pas à vaincre le Rêve de Dragon, et prennez un violent coup de queue.
Vous subissez {{#if rolled.isETotal}}deux queues{{else}}une queue{{/if}} de dragon! Vous subissez {{#if rolled.isETotal}}deux queues{{else}}une queue{{/if}} de dragon!
{{#each queues as | queue key|}} {{#each queues as | queue key|}}
<br>{{queue.name}}: {{{queue.data.data.description}}} <br>{{queue.name}}: {{{queue.data.description}}}
{{/each}} {{/each}}
{{/if}} {{/if}}
</span> </span>

View File

@ -16,7 +16,7 @@
<section class="sheet-body"> <section class="sheet-body">
<div class="form-group"> <div class="form-group">
<label>Catégorie </label> <label>Catégorie </label>
<select name="data.categorie" id="categorie" data-dtype="String"> <select name="data.categorie" class="categorie" data-dtype="String">
{{#select data.categorie}} {{#select data.categorie}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-competence.html"}} {{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-competence.html"}}
{{/select}} {{/select}}
@ -28,7 +28,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="xp">XP </label> <label for="xp">XP </label>
<input class="attribute-value" id="sheet-competence-xp" type="text" name="data.xp" value="{{data.xp}}" data-dtype="Number"/> <input class="attribute-value sheet-competence-xp" type="text" name="data.xp" value="{{data.xp}}" data-dtype="Number"/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="base">Niveau de base </label> <label for="base">Niveau de base </label>

View File

@ -27,7 +27,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Fréquence</label> <label>Fréquence</label>
<select name="data.rarete" id="rarete" data-dtype="String"> <select name="data.rarete" class="rarete" data-dtype="String">
{{#select data.rarete}} {{#select data.rarete}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}} {{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}}
{{/select}} {{/select}}
@ -35,7 +35,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Catégorie</label> <label>Catégorie</label>
<select name="data.categorie" id="categorie" data-dtype="String"> <select name="data.categorie" class="categorie" data-dtype="String">
{{#select data.categorie}} {{#select data.categorie}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html"}} {{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html"}}
{{/select}} {{/select}}

View File

@ -32,7 +32,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Fréquence</label> <label>Fréquence</label>
<select name="data.rarete" id="rarete" data-dtype="String"> <select name="data.rarete" class="rarete" data-dtype="String">
{{#select data.rarete}} {{#select data.rarete}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}} {{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}}
{{/select}} {{/select}}
@ -40,7 +40,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Catégorie</label> <label>Catégorie</label>
<select name="data.categorie" id="categorie" data-dtype="String"> <select name="data.categorie" class="categorie" data-dtype="String">
{{#select data.categorie}} {{#select data.categorie}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html"}} {{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html"}}
{{/select}} {{/select}}

View File

@ -56,7 +56,7 @@
</div> </div>
{{#if isOwned}} {{#if isOwned}}
<div class="form-group"> <div class="form-group">
<span for="xp"><a id="creer-tache-livre" data-actor-id="{{actorId}}">Créer une tâche de lecture</a></span> <span for="xp"><a class="creer-tache-livre" data-actor-id="{{actorId}}">Créer une tâche de lecture</a></span>
</div> </div>
{{/if}} {{/if}}
<div class="flexcol"> <div class="flexcol">

View File

@ -22,7 +22,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Fréquence</label> <label>Fréquence</label>
<select name="data.rarete" id="rarete" data-dtype="String"> <select name="data.rarete" class="rarete" data-dtype="String">
{{#select data.rarete}} {{#select data.rarete}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}} {{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}}
{{/select}} {{/select}}
@ -30,7 +30,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Catégorie</label> <label>Catégorie</label>
<select name="data.categorie" id="categorie" data-dtype="String"> <select name="data.categorie" class="categorie" data-dtype="String">
{{#select data.categorie}} {{#select data.categorie}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html"}} {{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html"}}
{{/select}} {{/select}}