diff --git a/changelog.md b/changelog.md
index 12c5d0fd..a585d0dd 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,4 +1,7 @@
# 11.2
+## 11.2.13 - Les cent pas d'Akarlikarlikar
+- Ajout de la commande /voyage pour gérer la fatigue de marche des voyageurs
+
## 11.2.12 - Le somnifère d'Akarlikarlikar
- Fix: les potions enchantées n'empêchent plus de finir correctement Château Dormant
diff --git a/module/rdd-combat.js b/module/rdd-combat.js
index fbdfa154..32887eed 100644
--- a/module/rdd-combat.js
+++ b/module/rdd-combat.js
@@ -1307,6 +1307,7 @@ export class RdDCombat {
blessuresStatus: actor.computeResumeBlessure(),
SConst: actor.getSConst(),
actorId: actor.id,
+ actor: actor,
tokenId: tokenId,
isGrave: actor.countBlessures(it => it.isGrave()) > 0,
isCritique: actor.countBlessures(it => it.isCritique()) > 0
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/sommeil/app-astrologie.js b/module/sommeil/app-astrologie.js
index 8f7e1e20..d993eaf7 100644
--- a/module/sommeil/app-astrologie.js
+++ b/module/sommeil/app-astrologie.js
@@ -116,10 +116,10 @@ export class AppAstrologie extends Application {
super.activateListeners(html);
this.html = html;
this.html.find('select[name="signe-astral"]').change(event => {
- this.selectNombreAstral(this.html.find('select[name="signe-astral"]').val());
+ this.selectNombreAstral(event.currentTarget.value);
})
this.html.find('select[name="signe-naissance"]').change(event => {
- this.selectHeureNaissance(this.html.find('select[name="signe-naissance"]').val());
+ this.selectHeureNaissance(event.currentTarget.value);
})
this.html.find('td.nombre-astral').click(event => {
this.selectNombreAstral(Number.parseInt(event.currentTarget.attributes['data-nombre-astral'].value) - 1);
diff --git a/module/sommeil/dialog-repos.js b/module/sommeil/dialog-repos.js
index d895c8ee..406914c8 100644
--- a/module/sommeil/dialog-repos.js
+++ b/module/sommeil/dialog-repos.js
@@ -21,7 +21,7 @@ export class DialogRepos extends Dialog {
}
constructor(html, actor) {
- let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 400, height: 'fit-content', 'z-index': 99999 };
+ let options = { classes: ["dialog-repos"], width: 400, height: 'fit-content', 'z-index': 99999 };
let conf = {
title: "Se reposer",
content: html,
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/system.json b/system.json
index bd83e1cf..8998132b 100644
--- a/system.json
+++ b/system.json
@@ -1,8 +1,8 @@
{
"id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
- "version": "11.2.12",
- "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.2.12.zip",
+ "version": "11.2.13",
+ "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.2.13.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json",
"changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
"compatibility": {
diff --git a/templates/chat-actor-turn-acteur.hbs b/templates/chat-actor-turn-acteur.hbs
index ad174c7f..665f5473 100644
--- a/templates/chat-actor-turn-acteur.hbs
+++ b/templates/chat-actor-turn-acteur.hbs
@@ -1 +1,2 @@
+
{{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 @@ +