From 3f098cab315e938a3de28b99944690df264b727f Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Tue, 26 Dec 2023 19:05:41 +0100 Subject: [PATCH] Commande /voyage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajout de la commande /voyage pour gérer la fatigue en voyage --- module/rdd-commands.js | 9 +- module/rdd-utility.js | 9 +- module/voyage/dialog-fatigue-voyage.js | 182 ++++++++++++++++++++ styles/simple.css | 8 +- templates/voyage/chat-fatigue_voyage.hbs | 10 ++ templates/voyage/dialog-fatigue-voyage.hbs | 58 +++++++ templates/voyage/fatigue-actor.hbs | 23 +++ templates/voyage/option-vitesse-fatigue.hbs | 1 + 8 files changed, 291 insertions(+), 9 deletions(-) create mode 100644 module/voyage/dialog-fatigue-voyage.js create mode 100644 templates/voyage/chat-fatigue_voyage.hbs create mode 100644 templates/voyage/dialog-fatigue-voyage.hbs create mode 100644 templates/voyage/fatigue-actor.hbs create mode 100644 templates/voyage/option-vitesse-fatigue.hbs 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 @@ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ heures +
+
+
+ +
+ +
+
+

+
+
    +
  • + Personnage + Survies + Ajustements +
  • + {{#each playerActors as |selected|}} + {{>'systems/foundryvtt-reve-de-dragon/templates/voyage/fatigue-actor.hbs' voyageur=selected survies=@root.typeTerrain.survies}} + {{/each}} +
+
+
+
+ + +
+
+
\ 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 @@ +
  • + + + + + +
    + +
    +
    + + + +
  • diff --git a/templates/voyage/option-vitesse-fatigue.hbs b/templates/voyage/option-vitesse-fatigue.hbs new file mode 100644 index 00000000..16d51e87 --- /dev/null +++ b/templates/voyage/option-vitesse-fatigue.hbs @@ -0,0 +1 @@ + \ No newline at end of file