Merge branch 'master-fixes' into 'master'

Fix: recalcul des nombres astraux

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!172
This commit is contained in:
Leratier Bretonnien 2021-03-20 17:42:29 +00:00
commit 2b6d1d8de1
13 changed files with 253 additions and 233 deletions

View File

@ -26,6 +26,7 @@ import { Poetique } from "./poetique.js";
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
import { Draconique } from "./tmr/draconique.js";
import { RdDCarac } from "./rdd-carac.js";
import { Monnaie } from "./item-monnaie.js";
/* -------------------------------------------- */
@ -56,36 +57,25 @@ export class RdDActor extends Actor {
*/
static async create(data, options) {
// Case of compendium global import
if (data instanceof Array) {
return super.create(data, options);
}
const isPersonnage = data.type == "personnage";
// If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic
if (data.items) {
let actor = super.create(data, options);
if (data.type == "personnage") {
if (isPersonnage) {
await actor.checkMonnaiePresence(data.items);
}
return actor;
}
let compendiumName;
if (data.type == "personnage") {
compendiumName = "foundryvtt-reve-de-dragon.competences";
} else if (data.type == "creature") {
compendiumName = "foundryvtt-reve-de-dragon.competences-creatures";
} else if (data.type == "entite") {
compendiumName = "foundryvtt-reve-de-dragon.competences-entites";
data.items = await RdDUtility.loadCompendium(RdDItemCompetence.actorCompendium(data.type));
if (isPersonnage) {
data.items = data.items.concat(Monnaie.monnaiesData());
}
if (compendiumName) {
data.items = await RdDUtility.loadCompendium(compendiumName);
}
// Ajout monnaie
if (data.type == "personnage" && data.items) {
await RdDActor.ajouterMonnaie(data.items);
}
return super.create(data, options);
}
@ -151,41 +141,10 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
async checkMonnaiePresence(items) { // Ajout opportuniste si les pièces n'existent pas.
if (!items) return; // Sanity check during import
let piece = items.find(item => item.type == 'monnaie' && Number(item.data.valeur_deniers) == 1);
let newMonnaie = [];
if (!piece) {
newMonnaie.push(RdDUtility.createMonnaie("Etain (1 denier)", 1, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp"));
let manquantes = Monnaie.monnaiesManquantes(items);
if (manquantes.length > 0) {
await this.createOwnedItem(manquantes);
}
piece = items.find(item => item.type == 'monnaie' && Number(item.data.valeur_deniers) == 10);
if (!piece) {
newMonnaie.push(RdDUtility.createMonnaie("Bronze (10 deniers)", 10, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp"));
}
piece = items.find(item => item.type == 'monnaie' && Number(item.data.valeur_deniers) == 100);
if (!piece) {
newMonnaie.push(RdDUtility.createMonnaie("Argent (1 sol)", 100, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp"));
}
piece = items.find(item => item.type == 'monnaie' && Number(item.data.valeur_deniers) == 1000);
if (!piece) {
newMonnaie.push(RdDUtility.createMonnaie("Or (10 sols)", 1000, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp"));
}
if (newMonnaie.length > 0) {
await this.createOwnedItem(newMonnaie);
}
}
/* -------------------------------------------- */
static async ajouterMonnaie(items) { // Creation auto à la création du personnage
let etain = RdDUtility.createMonnaie("Etain (1 denier)", 1, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp");
items.push(etain);
let bronze = RdDUtility.createMonnaie("Bronze (10 deniers)", 10, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp");
items.push(bronze);
let argent = RdDUtility.createMonnaie("Argent (1 sol)", 100, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp");
items.push(argent);
let or = RdDUtility.createMonnaie("Or (10 sols)", 1000, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp");
items.push(or);
}
/* -------------------------------------------- */
@ -307,7 +266,7 @@ export class RdDActor extends Actor {
getBestDraconic() {
const list = this.getDraconicList().sort((a, b) => b.data.niveau - a.data.niveau);
if (list.length == 0) {
return { name: "none", data: { niveau: -11 } };
return { name: "Aucun", data: { niveau: -11 } };
}
return duplicate(list[0]);
}
@ -350,27 +309,30 @@ export class RdDActor extends Actor {
};
const blessures = duplicate(this.data.data.blessures);
console.log("dormirChateauDormant", blessures)
await this._recupererBlessures(message, "legere", blessures.legeres.liste.filter(b => b.active), []);
await this._recupererBlessures(message, "grave", blessures.graves.liste.filter(b => b.active), blessures.legeres.liste);
await this._recupererBlessures(message, "critique", blessures.critiques.liste.filter(b => b.active), blessures.graves.liste);
await this.update({ "data.blessures": blessures });
await this._recupererVie(message);
await this.jetDeMoral('neutre');
// On ne récupère un point de chance que si aucun appel à la chance dans la journée
let utilisationChance = duplicate(this.getFlag('foundryvtt-reve-de-dragon', 'utilisationChance') ?? false);
if (!utilisationChance) {
await this.chanceActuelleIncDec(1);
}
await this.unsetFlag('foundryvtt-reve-de-dragon', 'utilisationChance'); // Nouveau jour, suppression du flag
this.transformerStress();
await this._recupereChance();
await this.transformerStress();
await this.retourSeuilDeReve(message);
message.content = `A la fin Chateau Dormant, ${message.content}<br>Un nouveau jour se lève`;
ChatMessage.create(message);
}
async _recupereChance() {
// On ne récupère un point de chance que si aucun appel à la chance dans la journée
if (this.getFlag('foundryvtt-reve-de-dragon', 'utilisationChance')) {
// Nouveau jour, suppression du flag
await this.unsetFlag('foundryvtt-reve-de-dragon', 'utilisationChance');
}
else {
await this.chanceActuelleIncDec(1);
}
}
/* -------------------------------------------- */
async _recupererBlessures(message, type, liste, moindres) {
let count = 0;
@ -480,9 +442,7 @@ export class RdDActor extends Actor {
await this.santeIncDec("vie", this.data.data.sante.vie.max - this.data.data.sante.vie.value);
await this.santeIncDec("endurance", this.data.data.sante.endurance.max - this.data.data.sante.endurance.value);
if (this.data.data.sante.fatigue) {
let fatigue = duplicate(this.data.data.sante.fatigue)
fatigue.value = 0;
await this.update({ "data.sante.fatigue": fatigue });
await this.update({ "data.sante.fatigue.value": 0 });
}
}
ChatMessage.create(message);
@ -532,16 +492,16 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
async recupererFatigue(message) {
let fatigue = duplicate(this.data.data.sante.fatigue)
let fatigue = this.data.data.sante.fatigue.value;
const fatigueMin = this._computeFatigueMin();
if (fatigue.value <= fatigueMin) {
if (fatigue <= fatigueMin) {
message.content += "Vous êtes déjà reposé. ";
return;
}
fatigue.value = Math.max(fatigueMin, this._calculRecuperationSegment(fatigue.value));
fatigue = Math.max(fatigueMin, this._calculRecuperationSegment(fatigue));
console.log("recupererFatigue", fatigue)
await this.update({ "data.sante.fatigue": fatigue });
if (fatigue.value == 0) {
await this.update({ "data.sante.fatigue.value": fatigue });
if (fatigue == 0) {
message.content += "Vous êtes complêtement reposé. ";
}
}
@ -680,9 +640,9 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
async sortMisEnReserve(rollData, sort) {
let reserve = duplicate(this.data.data.reve.reserve);
reserve.list.push({ coord: rollData.tmr.coord, sort: sort, draconic: duplicate(rollData.competence) });
await this.update({ "data.reve.reserve": reserve });
let reserve = duplicate(this.data.data.reve.reserve.list);
reserve.push({ coord: rollData.tmr.coord, sort: sort, draconic: duplicate(rollData.competence) });
await this.update({ "data.reve.reserve.list": reserve });
this.currentTMR.updateTokens();
}
@ -752,7 +712,7 @@ export class RdDActor extends Actor {
});
}
const update = { _id: comp._id, 'data.niveau': nouveauNiveau };
const updated = await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity
await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity
} else {
console.log("Competence not found", compName);
}
@ -765,7 +725,7 @@ export class RdDActor extends Actor {
compValue = compValue ?? 0;
this.checkCompetenceXP(compName, compValue);
const update = { _id: comp._id, 'data.xp': compValue };
const updated = await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity
await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity
} else {
console.log("Competence not found", compName);
}
@ -778,7 +738,7 @@ export class RdDActor extends Actor {
if (comp) {
compValue = compValue ?? 0;
const update = { _id: comp._id, 'data.xp_sort': compValue };
const updated = await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity
await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity
} else {
console.log("Competence not found", compName);
}
@ -790,7 +750,7 @@ export class RdDActor extends Actor {
if (comp) {
compValue = compValue ?? 0;
const update = { _id: comp._id, 'data.niveau_archetype': compValue };
const updated = await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity
await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity
} else {
console.log("Competence not found", compName);
}
@ -798,7 +758,6 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
async updateCompteurValue(fieldName, fieldValue) {
//console.log("Update", fieldName, fieldValue);
let compteurs = duplicate(this.data.data.compteurs);
compteurs[fieldName].value = fieldValue;
await this.update({ "data.compteurs": compteurs });
@ -992,8 +951,6 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
async computeEncombrementTotalEtMalusArmure() {
let encTotal = 0;
let malusArmureData = (this.data.data.attributs && this.data.data.attributs.malusarmure) ? duplicate(this.data.data.attributs.malusarmure) : {};
let newMalusArmure = 0;
for (const item of this.data.items) {
if (item.type == 'armure' && item.data.equipe) { // Armure équipée, intégration du malus armure total
@ -1014,10 +971,10 @@ export class RdDActor extends Actor {
// Mise à jour valeur totale et états
this.encTotal = encTotal;
this.detectSurEncombrement();
// Mise à jour éventuelle du malus armure
if (this.data.data.attributs && this.data.data.attributs.malusarmure && newMalusArmure != malusArmureData.value) {
malusArmureData.value = newMalusArmure;
await this.update({ "data.attributs.malusarmure": malusArmureData });
if (this.data.data.attributs?.malusarmure && newMalusArmure != this.data.data.attributs.malusarmure.value) {
await this.update({ "data.attributs.malusarmure.value ": newMalusArmure });
}
return this.encTotal;
}
@ -1049,12 +1006,12 @@ export class RdDActor extends Actor {
let resume = "Blessures:";
if (nbCritiques > 0 || nbGraves > 0 || nbLegeres > 0) {
if (nbLegeres > 0) {
resume += " " + nbLegeres + " légères";
resume += " " + nbLegeres + " légère" + (nbLegeres > 1 ? "s" : "");
}
if (nbGraves > 0) {
if (nbLegeres > 0)
resume += ",";
resume += " " + nbGraves + " graves";
resume += " " + nbGraves + " grave" + (nbGraves > 1 ? "s" : "");
}
if (nbCritiques > 0) {
if (nbGraves > 0 || nbLegeres > 0)
@ -1063,7 +1020,7 @@ export class RdDActor extends Actor {
}
}
else {
resume += " aucune";
resume = "Aucune blessure";
}
return resume;
}
@ -1093,20 +1050,14 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
async ajouterRefoulement(value = 1) {
let ret = "none";
let refoulement = duplicate(this.data.data.reve.refoulement);
refoulement.value = refoulement.value + value;
let refoulement = this.data.data.reve.refoulement.value + value;
let total = new Roll("1d20").roll().total;
if (total <= refoulement.value) {
refoulement.value = 0;
this.ajouterSouffle({ chat: true });
ret = "souffle";
if (total <= refoulement) {
refoulement = 0;
await this.ajouterSouffle({ chat: true });
}
await this.update({ "data.reve.refoulement": refoulement });
return ret;
await this.update({ "data.reve.refoulement.value": refoulement });
return refoulement == 0 ? "souffle" : "none";
}
/* -------------------------------------------- */
@ -1119,7 +1070,6 @@ export class RdDActor extends Actor {
content: this.name + " subit un Souffle de Dragon : " + souffle.name
});
}
// TODO: fermeture cité
return souffle;
}
@ -1128,9 +1078,7 @@ export class RdDActor extends Actor {
let queue;
if (this.data.data.reve.reve.thanatosused) {
queue = await RdDRollTables.getOmbre();
let myReve = duplicate(this.data.data.reve.reve);
myReve.thanatosused = false;
await this.update({ "data.reve.reve": myReve });
await this.update({ "data.reve.reve.thanatosused": false });
}
else {
queue = await RdDRollTables.getQueue();
@ -1165,40 +1113,25 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
getTMRRencontres() {
return this.data.data.reve.rencontre;
return this.data.data.reve.rencontre.list;
}
/* -------------------------------------------- */
async deleteTMRRencontreAtPosition() {
let rencontres = duplicate(this.getTMRRencontres());
let len = rencontres.list.length;
let i = 0;
//console.log("List", rencontres, len);
let newTable = [];
for (i = 0; i < len; i++) {
if (rencontres.list[i].coord != this.getDemiReve())
newTable.push(rencontres.list[i]);
}
if (newTable.length != len) {
rencontres.list = newTable;
//console.log("Result: ", rencontres);
await this.update({ "data.reve.rencontre": rencontres });
let rencontres = this.getTMRRencontres();
let newRencontres = rencontres.filter(it => it.coord != this.getDemiReve());
if (newRencontres.length != rencontres.length) {
await this.update({ "data.reve.rencontre.list": newRencontres });
}
}
/* -------------------------------------------- */
async addTMRRencontre(currentRencontre) {
let rencontres = duplicate(this.getTMRRencontres());
let len = rencontres.list.length;
let i = 0;
let already = false;
for (i = 0; i < len; i++) {
if (rencontres.list[i].coord == this.getDemiReve())
already = true;
}
if (!already) {
rencontres.list.push(currentRencontre);
await this.update({ "data.reve.rencontre": rencontres });
let rencontres = this.getTMRRencontres();
let newRencontres = rencontres.filter(it => it.coord != this.getDemiReve());
if (newRencontres.length == rencontres.length) {
newRencontres.push(currentRencontre);
await this.update({ "data.reve.rencontre": newRencontres });
}
}
@ -1220,9 +1153,8 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
async reveActuelIncDec(value) {
let reve = duplicate(this.data.data.reve.reve);
reve.value = Math.max(reve.value + value, 0);
await this.update({ "data.reve.reve": reve });
let reve = Math.max(this.data.data.reve.reve.value + value, 0);
await this.update({ "data.reve.reve.value": reve });
}
/* -------------------------------------------- */
@ -1235,17 +1167,13 @@ export class RdDActor extends Actor {
}
/* -------------------------------------------- */
async setPointsDeSeuil(value) {
let seuil = duplicate(this.data.data.reve.seuil);
seuil.value = value;
await this.update({ "data.reve.seuil": seuil });
async setPointsDeSeuil(seuil) {
await this.update({ "data.reve.seuil.value": seuil });
}
/* -------------------------------------------- */
async setPointsDeChance(value) {
let chance = duplicate(this.data.data.compteurs.chance);
chance.value = value;
await this.update({ "data.compteurs.chance": chance });
async setPointsDeChance(chance) {
await this.update({ "data.compteurs.chance.value": chance });
}
/* -------------------------------------------- */
@ -1299,7 +1227,7 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
async testSiSonne(sante, endurance) {
const roll = new Roll("1d20").roll();
const roll = new Roll("1d20").evaluate();
roll.showDice = true;
RdDDice.show(roll);
let result = {
@ -1307,18 +1235,20 @@ export class RdDActor extends Actor {
sonne: roll.total > endurance || roll.total == 20 // 20 is always a failure
}
if (roll.total == 1) {
let xp = Misc.toInt(this.data.data.carac.constitution.xp) + 1;
this.update({ "data.carac.constitution.xp": xp }); // +1 XP !
await this.ajoutXpConstitution(1); // +1 XP !
ChatMessage.create({ content: `${this.name} a obenu 1 sur son Jet d'Endurance et a gagné 1 point d'Expérience en Constitution. Ce point d'XP a été ajouté automatiquement).` });
}
if (result.sonne) {
await this.setSonne();
sante.sonne.value = true;
}
return result;
}
async ajoutXpConstitution(xp) {
await this.update({ "data.carac.constitution.xp": Misc.toInt(this.data.data.carac.constitution.xp) + xp });
}
/* -------------------------------------------- */
countBlessures(blessuresListe) {
return blessuresListe.filter(b => b.active).length
@ -1338,14 +1268,12 @@ export class RdDActor extends Actor {
if (myRoll.total == 1 || (myRoll.total != 20 && myRoll.total <= this.data.data.sante.endurance.value)) {
msgText += `${this.name} a réussi son Jet d'Endurance !`;
if (myRoll.total == 1) {
await this.ajoutXpConstitution();
msgText += `et gagne 1 Point d'Experience en Constitution`;
let constit = duplicate(this.data.data.carac.constitution)
constit.xp += 1;
await this.update({ "data.carac.constitution": constit });
}
} else {
msgText += `${this.name} a échoué son Jet d'Endurance et devient Sonné`;
await this.setSonne();
msgText += `${this.name} a échoué son Jet d'Endurance et devient Sonné`;
}
const message = {
content: msgText,
@ -1454,29 +1382,25 @@ export class RdDActor extends Actor {
}
/* -------------------------------------------- */
async manageBlessureFromSheet(bType, index, active) {
let bList = duplicate(this.data.data.blessures);
let blessure = bList[bType + "s"].liste[index];
async manageBlessureFromSheet(gravite, index) {
let listBlessures = duplicate(this.data.data.blessures);
let blessure = listBlessures[gravite + "s"].liste[index];
blessure.active = !blessure.active;
if (!blessure.active) {
blessure.premiers_soins = 0;
blessure.soins_complets = 0;
blessure.jours = 0;
blessure.loc = "";
this._supprimerBlessure(blessure);
}
//console.log("Blessure update", bType, index, blessure, bList );
await this.update({ 'data.blessures': bList });
await this.update({ 'data.blessures': listBlessures });
}
/* -------------------------------------------- */
async setDataBlessureFromSheet(bType, index, psoins, pcomplets, jours, loc) {
let bList = duplicate(this.data.data.blessures);
let blessure = bList[bType + "s"].liste[index];
async setDataBlessureFromSheet(gravite, index, psoins, pcomplets, jours, loc) {
let listBlessures = duplicate(this.data.data.blessures);
let blessure = listBlessures[gravite + "s"].liste[index];
blessure.premiers_soins = psoins;
blessure.soins_complets = pcomplets;
blessure.jours = jours;
blessure.loc = loc;
await this.update({ 'data.blessures': bList });
await this.update({ 'data.blessures': listBlessures });
}
/* -------------------------------------------- */
@ -1499,24 +1423,21 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
async moralIncDec(ajustementMoral) {
let compteurs = duplicate(this.data.data.compteurs);
compteurs.moral.value = Misc.toInt(compteurs.moral.value);;
if (ajustementMoral != 0) {
compteurs.moral.value += ajustementMoral;
if (compteurs.moral.value > 3) {
// exaltation
compteurs.moral.value--;
compteurs.exaltation.value = Misc.toInt(compteurs.exaltation.value) + 1;
let moral = Misc.toInt(this.data.data.compteurs.moral.value) + ajustementMoral
if (moral > 3) { // exaltation
const exaltation = Misc.toInt(this.data.data.compteurs.exaltation.value) + moral - 3;
await this.update({ 'data.compteurs.exaltation.value': exaltation });
}
if (compteurs.moral.value < -3) {
// dissolution
compteurs.moral.value++;
compteurs.dissolution.value = Misc.toInt(compteurs.dissolution.value) + 1;
if (moral < -3) { // dissolution
const dissolution = Misc.toInt(this.data.data.compteurs.dissolution.value) + 3 - moral;
await this.update({ 'data.compteurs.dissolution.value': dissolution });
}
await this.update({ 'data.compteurs': compteurs });
moral = Math.max(-3, Math.min(moral, 3));
await this.update({ 'data.compteurs.moral.value': moral });
}
return compteurs.moral.value;
return this.data.data.compteurs.moral.value;
}
/* -------------------------------------------- */
@ -1576,11 +1497,14 @@ export class RdDActor extends Actor {
const ajustementEthylique = ethylisme.value;
// Qui a bu boira (p 164)
let rollVolonte = await RdDResolutionTable.roll(this.data.data.carac.volonte.value, Math.min(ajustementEthylique, 0) + this.data.data.compteurs.moral.value);
msgText += `Vous avez échoué à votre jet d'éthylisme, vous êtes maintenant ${RdDUtility.getNomEthylisme(ajustementEthylique)} (${ajustementEthylique}).`
msgText += "<br>" + RdDResolutionTable.explain(rollVolonte) + "<br>";
msgText += "Qui a bu boira : " + (rollVolonte.isSuccess
const quiABuBoira = (rollVolonte.isSuccess
? "vous êtes libre de continuer à boire ou pas."
: "vous avez une envie irrépréssible de reprendre un verre.");
msgText += `Vous avez échoué à votre jet d'éthylisme, vous êtes
maintenant ${RdDUtility.getNomEthylisme(ajustementEthylique)} (${ajustementEthylique}).
<br> ${RdDResolutionTable.explain(rollVolonte)}
<br>Qui a bu boira : ${quiABuBoira}`;
}
ChatMessage.create({
@ -1774,7 +1698,7 @@ export class RdDActor extends Actor {
if (!rollData.useMoral) return;
if (rollData.rolled.isEchec ||
(rollData.ajustements.diviseurSignificative && (rollData.rolled.roll * rollData.ajustements.diviseurSignificative > rollData.score))) {
rollData.perteMoralEchec = rollData.moral<=-3? 'dissolution' : 'perte';
rollData.perteMoralEchec = rollData.moral <= -3 ? 'dissolution' : 'perte';
rollData.moral = await this.moralIncDec(-1); /* L'appel au moral a échoué. Le personnage perd un point de moral */
}
}
@ -2863,42 +2787,29 @@ export class RdDActor extends Actor {
return;
}
/* -------------------------------------------- */
async optimizeArgent(sumDenier) {
let sols = Math.floor(sumDenier / 100);
let deniers = sumDenier - (sols * 100);
let nbOr = Math.floor(sols / 10);
let nbArgent = sols - (nbOr * 10);
let nbBronze = Math.floor(deniers / 10);
let nbEtain = deniers - (nbBronze * 10);
async optimizeArgent(sumDenier, monnaies) {
// console.log("ARGENT", nbOr, nbArgent, nbBronze, nbEtain);
let piece = this.data.items.find(item => item.type == 'monnaie' && item.data.valeur_deniers == 1000);
if (piece) {
let update = { _id: piece._id, 'data.quantite': nbOr };
const updated = await this.updateEmbeddedEntity("OwnedItem", update);
let parValeur = Misc.classifyFirst(monnaies, it => it.data.valeur_deniers);
let fortune = {
1000: Math.floor(sumDenier / 1000), // or
100: Math.floor(sumDenier / 100) % 10, // argent
10: Math.floor(sumDenier / 10) % 10, // bronze
1: sumDenier % 10 // étain
}
piece = this.data.items.find(item => item.type == 'monnaie' && item.data.valeur_deniers == 100);
if (piece) {
let update = { _id: piece._id, 'data.quantite': nbArgent };
const updated = await this.updateEmbeddedEntity("OwnedItem", update);
}
piece = this.data.items.find(item => item.type == 'monnaie' && item.data.valeur_deniers == 10);
if (piece) {
let update = { _id: piece._id, 'data.quantite': nbBronze };
const updated = await this.updateEmbeddedEntity("OwnedItem", update);
}
piece = this.data.items.find(item => item.type == 'monnaie' && item.data.valeur_deniers == 1);
if (piece) {
let update = { _id: piece._id, 'data.quantite': nbEtain };
const updated = await this.updateEmbeddedEntity("OwnedItem", update);
for (const [valeur, nombre] of Object.entries(fortune)) {
let piece = parValeur[valeur];
await this.updateEmbeddedEntity("OwnedItem", { _id: piece._id, 'data.quantite': nombre });
}
}
/* -------------------------------------------- */
async payerDenier(sumDenier, dataObj = undefined, quantite = 1) {
let monnaies = Monnaie.filtrerMonnaies(this.data.items);
if (monnaies.length < 4) {
ui.notifications.warn("Problème de monnaies manquantes, impossible de payer correctement!")
return;
}
sumDenier = Number(sumDenier);
let denierDisponible = 0;
@ -2912,19 +2823,18 @@ export class RdDActor extends Actor {
let isPayed = false;
if (denierDisponible >= sumDenier) {
denierDisponible -= sumDenier;
this.optimizeArgent(denierDisponible);
this.optimizeArgent(denierDisponible, monnaies);
msg = `Vous avez payé <strong>${sumDenier} Deniers</strong>, qui ont été soustraits de votre argent.`;
RdDAudio.PlayContextAudio("argent"); // Petit son
isPayed = true;
if (dataObj) {
dataObj.payload.data.cout = sumDenier / 100; // Mise à jour du prix en sols , avec le prix acheté
dataObj.payload.data.quantite = quantite;
await this.createOwnedItem(dataObj.payload);
msg += `<br>Et l'objet <strong>${dataObj.payload.name}</strong> a été ajouté à votre inventaire.`;
}
} else {
msg = "Vous n'avez pas assez d'argent pour paye cette somme !";
}
if (dataObj && isPayed) {
dataObj.payload.data.cout = sumDenier / 100; // Mise à jour du prix en sols , avec le prix acheté
dataObj.payload.data.quantite = quantite;
await this.createOwnedItem(dataObj.payload);
msg += `<br>Et l'objet <strong>${dataObj.payload.name}</strong> a été ajouté à votre inventaire.`;
msg = "Vous n'avez pas assez d'argent pour payer cette somme !";
}
let message = {
@ -2938,10 +2848,8 @@ export class RdDActor extends Actor {
async monnaieIncDec(id, value) {
let monnaie = this.data.items.find(item => item.type == 'monnaie' && item._id == id);
if (monnaie) {
monnaie.data.quantite += value;
if (monnaie.data.quantite < 0) monnaie.data.quantite = 0; // Sanity check
const update = { _id: monnaie._id, 'data.quantite': monnaie.data.quantite };
const updated = await this.updateEmbeddedEntity("OwnedItem", update);
const quantite = Math.max(0, monnaie.data.quantite + value);
await this.updateEmbeddedEntity("OwnedItem", { _id: monnaie._id, 'data.quantite': quantite });
}
}

View File

@ -31,6 +31,13 @@ const categorieCompetences = {
"lancer": { level: "-8", label: "Lancer" }
}
const compendiumCompetences = {
"personnage": "foundryvtt-reve-de-dragon.competences",
"creature": "foundryvtt-reve-de-dragon.competences-creatures",
"entite": "foundryvtt-reve-de-dragon.competences-entites"
};
function _buildCumulXP() {
let cumulXP = { "-11": 0 };
let cumul = 0;
@ -46,6 +53,10 @@ const competence_xp_cumul = _buildCumulXP();
export class RdDItemCompetence extends Item {
static actorCompendium(actorType) {
return compendiumCompetences[actorType];
}
static getCategorieCompetences() {
return categorieCompetences;
}

40
module/item-monnaie.js Normal file
View File

@ -0,0 +1,40 @@
const monnaiesData = [
{
_id: randomID(16), name: "Etain (1 denier)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
data: { quantite: 0, valeur_deniers: 1, encombrement: 0.001, description: "" }
},
{
_id: randomID(16), name: "Bronze (10 deniers)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp",
data: { quantite: 0, valeur_deniers: 10, encombrement: 0.002, description: "" }
},
{
_id: randomID(16), name: "Argent (1 sol)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp",
data: { quantite: 0, valeur_deniers: 100, encombrement: 0.003, description: "" }
},
{
_id: randomID(16), name: "Or (10 sols)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
data: { quantite: 0, valeur_deniers: 1000, encombrement: 0.004, description: "" }
}
]
export class Monnaie {
static monnaiesData() {
return monnaiesData;
}
static filtrerMonnaies(items) {
return items.filter(it => it.type == 'monnaie');
}
static monnaiesManquantes(items) {
const valeurs = Monnaie.filtrerMonnaies(items)
.map(it => it.data.valeur_deniers)
return duplicate(monnaiesData.filter(monnaie => !valeurs.find(v => v != monnaie.data.valeur_deniers)));
}
}

View File

@ -47,6 +47,17 @@ export class Misc {
return itemsBy;
}
static classifyFirst(items, classifier) {
let itemsBy = {};
for (const item of items) {
const classification = classifier(item);
if (!itemsBy[classification]) {
itemsBy[classification] = item;
}
}
return itemsBy;
}
static classifyInto(itemsBy, items, classifier = it => it.type, transform = it => it) {
for (const item of items) {
const classification = classifier(item);

44
module/poetique.txt Normal file
View File

@ -0,0 +1,44 @@
Le courant du Fleuve
Te domine et te Porte
Avant que tu te moeuves
Combat le, ou il t'emporte
A vous qui faites ripaille
sourds aux damnés de la faim
à vous qui livrez
une inégale bataille
à ceux qui vous tendent la main
Ils sont tout près ! - Tenons fermée
<br>Cette salle, où nous les narguons.
<br>Quel bruit dehors ! Hideuse armée
<br>De vampires et de dragons !
<br>La poutre du toit descellée
<br>Ploie ainsi qu'une herbe mouillée,
<br>Et la vieille porte rouillée
<br>Tremble, à déraciner ses gonds !`),
https://www.poetica.fr/poeme-1423/guy-de-maupassant-le-sommeil-du-mandarin/
Le monde est un rêve de Dragons. Nous
ne savons pas qui sont les Dragons ni à quoi
ils ressemblent, en dépit de lantique iconographie qui les dépeint comme de gigantesques créatures ailées capables de cracher
feu et flammes.
Car parmi les humains, autre nom lui est donné,
Nom sinistre parmi tous, nom funèbre, c'est la mort!
Un ami disparu... Thanatos est passé...
Messieurs, ne crachez pas de jurons ni d'ordure
Au visage fardé de cette pauvre impure
Que déesse Famine a par un soir d'hiver,
Contrainte à relever ses jupons en plein air.

View File

@ -147,6 +147,7 @@ export class RdDCalendrier extends Application {
}
}
}
this.listeNombreAstral = newList;
game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral);
}
/* -------------------------------------------- */

View File

@ -1,5 +1,4 @@
import { Grammar } from "./grammar.js";
import { RdDUtility } from "./rdd-utility.js";
const tableCaracDerivee = {
// xp: coût pour passer du niveau inférieur à ce niveau

View File

@ -72,11 +72,11 @@ export class RdDTMRDialog extends Dialog {
}
loadSortsReserve() {
this.sortsReserves = duplicate(this.actor.data.data.reve.reserve.list);
this.sortsReserves = this.actor.data.data.reve.reserve.list;
}
loadRencontres() {
this.rencontresExistantes = duplicate(this.actor.getTMRRencontres()).list;
this.rencontresExistantes = this.actor.getTMRRencontres();
}
/* -------------------------------------------- */
@ -389,6 +389,11 @@ export class RdDTMRDialog extends Dialog {
ChatMessage.create({ content: message, user: game.user._id, whisper: ChatMessage.getWhisperRecipients("GM") });
}
/* -------------------------------------------- */
_tellToUserAndGM(message) {
ChatMessage.create({ content: message, user: game.user._id, whisper: [game.user._id].concat(ChatMessage.getWhisperRecipients("GM")) });
}
/* -------------------------------------------- */
async manageRencontre(tmr, postRencontre) {
if (this.viewOnly) {
@ -669,8 +674,8 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async declencheSortEnReserve(coord) {
let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coord);
if (sortReserveList.length > 0) {
let sortsEnCoord = TMRUtility.getSortsReserve(this.sortsReserves, coord);
if (sortsEnCoord.length > 0) {
if (EffetsDraconiques.isSortReserveImpossible(this.actor)) {
ui.notifications.error("Une queue ou un souffle vous empèche de déclencher de sort!");
return;
@ -678,7 +683,7 @@ export class RdDTMRDialog extends Dialog {
if (!EffetsDraconiques.isUrgenceDraconique(this.actor) &&
(EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coord))) {
let msg = "Vous êtes sur une case avec un Sort en Réserve. Grâce à votre Tête <strong>Reserve en Sécurité</strong> ou <strong>Réserve Exensible</strong>, vous pouvez contrôler le déclenchement. Cliquez si vous souhaitez le déclencher : <ul>";
for (let sortReserve of sortReserveList) {
for (let sortReserve of sortsEnCoord) {
msg += "<li><a class='chat-card-button' id='sort-reserve' data-actor-id='" + this.actor._id + "' data-tmr-coord='" + coord + "' data-sort-id='" + sortReserve.sort._id + "'>" + sortReserve.sort.name + "</a></li>";
}
msg += "</ol>";
@ -688,15 +693,14 @@ export class RdDTMRDialog extends Dialog {
});
return;
}
await this.processSortReserve(sortReserveList[0]);
await this.processSortReserve(sortsEnCoord[0]);
}
}
/* -------------------------------------------- */
lancerSortEnReserve(coord, sortId) {
let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coord);
let sortReserve = sortReserveList.find(sortReserve => sortReserve.sort._id == sortId);
//console.log("SORT RESA", sortReserveList, coordTMR, sortId, sortReserve);
let sortEnCoord = TMRUtility.getSortsReserve(this.sortsReserves, coord);
let sortReserve = sortEnCoord.find(sortReserve => sortReserve.sort._id == sortId);
if (sortReserve) {
this.processSortReserve(sortReserve);
} else {
@ -712,7 +716,7 @@ export class RdDTMRDialog extends Dialog {
await this.actor.deleteSortReserve(sortReserve);
//this.updateSortReserve();
console.log("declencheSortEnReserve", sortReserve)
this._tellToGM(`Vous avez déclenché le sort en réserve <strong> ${sortReserve.sort.name}</strong>
this._tellToUserAndGM(`Vous avez déclenché le sort en réserve <strong> ${sortReserve.sort.name}</strong>
avec ${sortReserve.sort.data.ptreve_reel} points de Rêve
en ${sortReserve.coord} (${TMRUtility.getTMRLabel(sortReserve.coord)})
`);

View File

@ -485,8 +485,10 @@ export class RdDUtility {
/* -------------------------------------------- */
static async loadCompendium(compendium, filter = item => true) {
if (!compendium){
return [];
}
let compendiumItems = await RdDUtility.loadCompendiumNames(compendium);
const pack = game.packs.get(compendium);
let list = [];
for (let compendiumItem of compendiumItems) {

View File

@ -432,7 +432,7 @@ export class TMRUtility {
}
/* -------------------------------------------- */
static getSortReserveList(reserveList, coord) {
static getSortsReserve(reserveList, coord) {
// TODO : Gérer les têtes spéciales réserve!
let tmrDescr = this.getTMR(coord);
//console.log("Sort réserve : ", tmrDescr);

View File

@ -2,7 +2,7 @@
"name": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"description": "Rêve de Dragon RPG for FoundryVTT",
"version": "1.3.35",
"version": "1.3.36",
"manifestPlusVersion": "1.0.0",
"minimumCoreVersion": "0.7.5",
"compatibleCoreVersion": "0.7.9",

View File

@ -541,7 +541,6 @@
</div>
{{!-- hautreve Tab --}}
{{log 'Haut reve' hautreve}}
<div class="tab hautreve " data-group="primary" data-tab="hautreve" style="height:200px">
<div>
<h3>Haut rêve:</h3>

1
templates/logger.html Normal file
View File

@ -0,0 +1 @@
{{log 'HandleBars' this}}