diff --git a/module/rdd-commands.js b/module/rdd-commands.js
index 74dd1e61..b907c0ce 100644
--- a/module/rdd-commands.js
+++ b/module/rdd-commands.js
@@ -16,6 +16,7 @@ import { RdDRollTables } from "./rdd-rolltables.js";
import { RdDUtility } from "./rdd-utility.js";
import { FenetreRechercheTirage } from "./tirage/fenetre-recherche-tirage.js";
import { TMRUtility } from "./tmr-utility.js";
+import { DialogFatigueVoyage } from "./voyage/dialog-fatigue-voyage.js";
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
@@ -76,6 +77,7 @@ export class RdDCommands {
this.registerCommand({ path: ["/tirer", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant('chat'), descr: "Tire un Désir Lancinant" });
this.registerCommand({ path: ["/tirer", "rencontre"], func: (content, msg, params) => this.getRencontreTMR(params), descr: `Détermine une rencontre dans les TMR (synonyme de "/tmrr")` });
this.registerCommand({ path: ["/tirage"], func: (content, msg, params) => this.tirage(), descr: "Ouvre la fenêtre de recherche et tirage" });
+ this.registerCommand({ path: ["/voyage"], func: (content, msg, params) => this.voyage(msg, params), descr: "Gérer le voyage" });
this.registerCommand({ path: ["/sommeil"], func: (content, msg, params) => this.sommeil(msg, params), descr: "Prépare le passage de journée pour chateau dormant" });
this.registerCommand({ path: ["/meteo"], func: (content, msg, params) => this.getMeteo(msg, params), descr: "Propose une météo marine" });
@@ -485,10 +487,13 @@ export class RdDCommands {
}
async tirage() {
- FenetreRechercheTirage.create();
+ FenetreRechercheTirage.create()
+ }
+ async voyage() {
+ DialogFatigueVoyage.create()
}
async sommeil() {
- DialogChateauDormant.create();
+ DialogChateauDormant.create()
}
}
diff --git a/module/rdd-utility.js b/module/rdd-utility.js
index 5baefcfe..44068635 100644
--- a/module/rdd-utility.js
+++ b/module/rdd-utility.js
@@ -63,12 +63,6 @@ const cumulFatigueMatrix = _cumulSegmentsFatigue(fatigueMatrix);
const fatigueMalus = [0, 0, 0, -1, -1, -1, -2, -3, -4, -5, -6, -7]; // Provides the malus for each segment of fatigue
const fatigueLineSize = [3, 6, 7, 8, 9, 10, 11, 12];
const fatigueLineMalus = [0, -1, -2, -3, -4, -5, -6, -7];
-const fatigueMarche = {
- "aise": { "4": 1, "6": 2, "8": 3, "10": 4, "12": 6 },
- "malaise": { "4": 2, "6": 3, "8": 4, "10": 6 },
- "difficile": { "4": 3, "6": 4, "8": 6 },
- "tresdifficile": { "4": 4, "6": 6 }
-}
/* -------------------------------------------- */
const nomEthylisme = ["Emeché", "Gris", "Pinté", "Pas frais", "Ivre", "Bu", "Complètement fait", "Ivre mort"];
@@ -208,6 +202,8 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/coeur/afficher-coeur.hbs',
'systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs',
'systems/foundryvtt-reve-de-dragon/templates/time/horloge.hbs',
+ 'systems/foundryvtt-reve-de-dragon/templates/voyage/fatigue-actor.hbs',
+ 'systems/foundryvtt-reve-de-dragon/templates/voyage/option-vitesse-fatigue.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/timestamp.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs',
@@ -288,6 +284,7 @@ export class RdDUtility {
Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree());
Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode());
+ Handlebars.registerHelper('array-includes', (array, value) => array.includes(value));
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionnelles.isUsing(option));
Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name)));
diff --git a/module/voyage/dialog-fatigue-voyage.js b/module/voyage/dialog-fatigue-voyage.js
new file mode 100644
index 00000000..a874d1fc
--- /dev/null
+++ b/module/voyage/dialog-fatigue-voyage.js
@@ -0,0 +1,182 @@
+import { TYPES } from "../item.js"
+import { RdDItemCompetence } from "../item-competence.js"
+import { ChatUtility } from "../chat-utility.js"
+
+const CODES_COMPETENCES_VOYAGE = ['Extérieur', 'Forêt', 'Montagne', 'Marais', 'Glace', 'Equitation']
+const TABLEAU_FATIGUE_MARCHE = [
+ {
+ code: "aise", label: "Aisé", description: "Route ou chemin",
+ survies: ['Extérieur', 'Equitation'],
+ vitesses: [{ vitesse: 4, fatigue: 1 }, { vitesse: 6, fatigue: 2 }, { vitesse: 8, fatigue: 3 }, { vitesse: 10, fatigue: 4 }, { vitesse: 12, fatigue: 6 }],
+ },
+ {
+ code: "malaise", label: "Malaisé", description: "Hors piste (herbes et buissons)",
+ survies: ['Extérieur', 'Equitation'],
+ vitesses: [{ vitesse: 4, fatigue: 2 }, { vitesse: 6, fatigue: 3 }, { vitesse: 8, fatigue: 4 }, { vitesse: 10, fatigue: 6 }],
+ },
+ {
+ code: "difficile", label: "Difficile", description: "Hors piste (collines, forêt)",
+ survies: ['Extérieur', 'Forêt', 'Glace', 'Equitation'],
+ vitesses: [{ vitesse: 4, fatigue: 3 }, { vitesse: 6, fatigue: 4 }, { vitesse: 8, fatigue: 6 }],
+ },
+ {
+ code: "tresdifficile", label: "Très difficile", description: "Hors piste (montagne, jungle, marais)",
+ survies: ['Forêt', 'Montagne', 'Marais', 'Glace'],
+ vitesses: [{ vitesse: 4, fatigue: 4 }, { vitesse: 6, fatigue: 6 }],
+ },
+]
+
+export class DialogFatigueVoyage extends Dialog {
+ static dialog = undefined
+ static async create() {
+ if (!game.user.isGM) {
+ return
+ }
+ if (!DialogFatigueVoyage.dialog) {
+ const playerActors = game.actors.filter(actor => actor.hasPlayerOwner && actor.isPersonnage())
+ .map(actor => DialogFatigueVoyage.prepareActor(actor))
+ const parameters = {
+ tableauFatigueMarche: TABLEAU_FATIGUE_MARCHE,
+ playerActors: playerActors,
+ nombreHeures: 1,
+ }
+ DialogFatigueVoyage.setModeDeplacement(parameters, undefined, undefined)
+
+ const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/voyage/dialog-fatigue-voyage.hbs", parameters);
+ DialogFatigueVoyage.dialog = new DialogFatigueVoyage(html, parameters);
+ }
+ DialogFatigueVoyage.dialog.render(true);
+ }
+
+ static setModeDeplacement(parameters, code, vitesse) {
+ const ligneFatigueMarche = TABLEAU_FATIGUE_MARCHE.find(it => it.code == code) ?? TABLEAU_FATIGUE_MARCHE[0]
+ const rythme = ligneFatigueMarche.vitesses.find(it => it.vitesse == vitesse) ?? ligneFatigueMarche.vitesses[0]
+ parameters.typeTerrain = ligneFatigueMarche
+ parameters.vitesseDeplacement = rythme.vitesse
+ parameters.fatigueHoraire = rythme.fatigue
+ }
+
+ static prepareActor(actor) {
+ const competencesVoyage = {}
+ CODES_COMPETENCES_VOYAGE.forEach(codeSurvie =>
+ competencesVoyage[codeSurvie] = RdDItemCompetence.findCompetence(actor.itemTypes[TYPES.competence], codeSurvie, { onMessage: () => { } })
+ )
+ return {
+ actor: actor,
+ selected: true,
+ ajustementFatigue: 0,
+ competencesVoyage: competencesVoyage
+ }
+ }
+
+
+ constructor(html, parameters) {
+ const options = {
+ classes: ["dialog-fatigue-voyage"],
+ width: 600,
+ height: 'fit-content',
+ 'max-height': 900,
+ 'z-index': 99999
+ }
+ const conf = {
+ title: "Fatigue de voyage",
+ content: html,
+ buttons: {}
+ }
+ super(conf, options);
+ this.parameters = parameters
+ this.controls = {}
+ }
+
+ activateListeners(html) {
+ if (this.html == undefined) {
+ html.find('select[name="code-terrain"]').trigger("focus")
+ }
+ this.html = html;
+ super.activateListeners(html);
+
+ this.html.find('select[name="code-terrain"]').change(event => this.changeParameters())
+ this.html.find('select[name="vitesse-deplacement"]').change(event => this.changeParameters())
+ this.html.find('input[name="nombre-heures"]').change(event => this.changeParameters())
+ this.html.find('button[name="appliquer-fatigue"]').click(event => this.appliquerFatigue())
+ }
+
+ changeParameters() {
+ this.changeTerrain(this.html.find('select[name="code-terrain"]').val())
+ this.changeVitesse(this.html.find('select[name="vitesse-deplacement"]').val())
+ this.changeNombreHeures(this.html.find('input[name="nombre-heures"]').val())
+ this.setFatigue()
+ }
+
+ async changeTerrain(codeTerrain) {
+ if (this.parameters.typeTerrain.code != codeTerrain) {
+ const selectVitesseDeplacement = this.html.find('select[name="vitesse-deplacement"]')
+ const vitesse = selectVitesseDeplacement.val()
+ selectVitesseDeplacement.empty()
+
+ DialogFatigueVoyage.setModeDeplacement(this.parameters, codeTerrain, vitesse)
+ this.parameters.typeTerrain.vitesses.forEach(async rythme => {
+ selectVitesseDeplacement.append(await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/voyage/option-vitesse-fatigue.hbs', rythme))
+ })
+ selectVitesseDeplacement.val(this.parameters.vitesseDeplacement).change()
+ }
+ }
+
+ async changeVitesse(vitesse) {
+ if (this.parameters.vitesseDeplacement != vitesse) {
+ DialogFatigueVoyage.setModeDeplacement(this.parameters, this.parameters.typeTerrain.code, vitesse)
+ }
+ }
+
+ async changeNombreHeures(nombreHeures) {
+ this.parameters.nombreHeures = parseInt(nombreHeures)
+ }
+
+ async setFatigue() {
+ this.html.find('input[name="base-fatigue"]').val(this.parameters.nombreHeures * this.parameters.fatigueHoraire)
+ }
+
+ async appliquerFatigue() {
+ const fatigueBase = parseInt(this.html.find('input[name="base-fatigue"]').val() ?? 0)
+ const actors = jQuery.map(
+ this.html.find('div.fatigue-actors-list li.list-item'),
+ it => this.$extractActor(this.html.find(it))
+ )
+ actors.filter(it => it.selected)
+ .forEach(async it => {
+ const perteFatigue = fatigueBase + it.ajustement
+ ChatMessage.create({
+ whisper: ChatUtility.getWhisperRecipientsAndGMs(it.actor.name),
+ content: await renderTemplate(
+ 'systems/foundryvtt-reve-de-dragon/templates/voyage/chat-fatigue_voyage.hbs', mergeObject(it,
+ {
+ parameters: this.parameters,
+ fatigueBase: fatigueBase,
+ perteFatigue: perteFatigue,
+ isVoyage: fatigueBase == this.parameters.nombreHeures * this.parameters.fatigueHoraire
+ })
+ ),
+ })
+ await it.actor.santeIncDec("fatigue", perteFatigue)
+ })
+ }
+
+ $extractActor(actorRow) {
+ const actor = game.actors.get(actorRow.data('actor-id'))
+ if (!actor) {
+ ui.notifications.warn(`Acteur ${it.actorId} introuvable`)
+ }
+ return {
+ actor: actor,
+ ajustement: parseInt(actorRow.find('input[name="ajustement-fatigue"]').val() ?? 0),
+ selected: actor && actorRow.find('input[name="selectionner-acteur"]').is(':checked')
+ }
+ }
+
+ async close() {
+ DialogFatigueVoyage.dialog = undefined
+ await super.close()
+ }
+
+
+}
\ No newline at end of file
diff --git a/styles/simple.css b/styles/simple.css
index 619b839e..d13871b1 100644
--- a/styles/simple.css
+++ b/styles/simple.css
@@ -440,7 +440,13 @@ table {border: 1px solid #7a7971;}
.flex-grow-2 {
flex-grow: 2;
}
+.voyage-liste-survies {
+ max-width: 12rem;
+}
/* Styles limited to foundryvtt-reve-de-dragon sheets */
+.texte-dans-liste {
+ text-align: left;
+}
.equipement-nom {
flex-grow : 4;
margin: 0;
@@ -1168,7 +1174,7 @@ ul.chat-list li:nth-child(odd) {
border-radius: 0.25rem;
padding: 0.1rem;
flex: 1 1 1.5rem;
- display: flex !important;
+ display: flex;
align-items: center !important;
}
diff --git a/templates/voyage/chat-fatigue_voyage.hbs b/templates/voyage/chat-fatigue_voyage.hbs
new file mode 100644
index 00000000..14829e12
--- /dev/null
+++ b/templates/voyage/chat-fatigue_voyage.hbs
@@ -0,0 +1,10 @@
+
+
{{actor.name}} s'est fatigué de {{perteFatigue}} +{{#if (and isVoyage (gt parameters.nombreHeures 0))}} +après {{parameters.nombreHeures}} heure{{#if (gt parameters.nombreHeures 1)}}s{{/if}} +de voyage {{lowerFirst parameters.typeTerrain.label}} +à {{parameters.vitesseDeplacement}} km/hdr (Fatigue par heure: {{parameters.fatigueHoraire}}) +
+{{parameters.typeTerrain.description}} +{{/if}} +
diff --git a/templates/voyage/dialog-fatigue-voyage.hbs b/templates/voyage/dialog-fatigue-voyage.hbs new file mode 100644 index 00000000..4dbd1f9a --- /dev/null +++ b/templates/voyage/dialog-fatigue-voyage.hbs @@ -0,0 +1,58 @@ + \ No newline at end of file diff --git a/templates/voyage/fatigue-actor.hbs b/templates/voyage/fatigue-actor.hbs new file mode 100644 index 00000000..ce8ee826 --- /dev/null +++ b/templates/voyage/fatigue-actor.hbs @@ -0,0 +1,23 @@ +