From edf920b34055406a76d50e11c84eea4b644f313a Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Tue, 7 Oct 2025 01:49:53 +0200 Subject: [PATCH] Roll V2: cuisine --- changelog.md | 2 + css/foundryvtt-reve-de-dragon.css | 66 ++++++----- icons/cuisine/gibier.svg | 1 + icons/cuisine/herbe.svg | 1 + icons/cuisine/mortadelle.svg | 1 + icons/cuisine/plante.svg | 1 + icons/cuisine/ragout.svg | 1 + icons/cuisine/saucisson.svg | 1 + icons/cuisine/volaille.svg | 1 + less/foundryvtt-reve-de-dragon.less | 48 ++++---- less/roll-dialog.less | 22 ++-- less/sheets.less | 6 +- module/actor.js | 38 +++++- module/chat-utility.js | 2 +- module/roll/chat-roll-result.mjs | 13 ++- module/roll/roll-basic-parts.mjs | 20 ++-- module/roll/roll-dialog.mjs | 28 ++++- module/roll/roll-part-cuisine.mjs | 136 +++++++++++++++++++--- module/roll/roll-type-cuisine.mjs | 66 ++++++++++- module/roll/roll-type-oeuvre.mjs | 5 +- module/roll/roll-type.mjs | 11 +- module/technical/actor-impacts.mjs | 128 ++++++++++++++++++++ module/{ => technical}/actor-token.mjs | 10 +- templates/common/date-heure.hbs | 2 +- templates/roll/result/chat-attaque.hbs | 2 +- templates/roll/result/chat-comp.hbs | 2 +- templates/roll/result/chat-cuisine.hbs | 38 ++++-- templates/roll/result/chat-defense.hbs | 2 +- templates/roll/result/chat-jeu.hbs | 3 +- templates/roll/result/chat-meditation.hbs | 2 +- templates/roll/result/chat-oeuvre.hbs | 2 +- templates/roll/roll-part-comp.hbs | 2 +- templates/roll/roll-part-cuisine.hbs | 47 +++++++- templates/roll/roll-part-sort.hbs | 7 +- 34 files changed, 574 insertions(+), 143 deletions(-) create mode 100644 icons/cuisine/gibier.svg create mode 100644 icons/cuisine/herbe.svg create mode 100644 icons/cuisine/mortadelle.svg create mode 100644 icons/cuisine/plante.svg create mode 100644 icons/cuisine/ragout.svg create mode 100644 icons/cuisine/saucisson.svg create mode 100644 icons/cuisine/volaille.svg create mode 100644 module/technical/actor-impacts.mjs rename module/{ => technical}/actor-token.mjs (84%) diff --git a/changelog.md b/changelog.md index 650154a5..008982a7 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,8 @@ - Nouvelle fenêtre de jets de dés - jeux + - cuisine et préparation de nourriture + ## 13.0.10 - Les papilles d'Illysis - Ajout d'un statut "saignement" en cas de blessure grave ou critique sans premiers soins diff --git a/css/foundryvtt-reve-de-dragon.css b/css/foundryvtt-reve-de-dragon.css index c598a718..f2231fad 100644 --- a/css/foundryvtt-reve-de-dragon.css +++ b/css/foundryvtt-reve-de-dragon.css @@ -160,7 +160,7 @@ select, min-height: 100px; background: var(--rdd-bg-input-alt); padding: 5px; - border-radius: 3px; + border-radius: 0.2rem; color: var(--rdd-color-text-primary); } .system-foundryvtt-reve-de-dragon .monnaie-content .window-content { @@ -177,7 +177,7 @@ select, background: var(--fieldset-background); color: var(--rdd-color-text-primary); margin-bottom: 4px; - border-radius: 6px; + border-radius: 0.5rem; border-color: var(--rdd-color-text-primary); border-width: 2px; } @@ -207,7 +207,7 @@ select, border: 1px solid var(--rdd-color-border-input); color: var(--rdd-color-text-input); padding: 2px 2px; - border-radius: 3px; + border-radius: 0.2rem; } .system-foundryvtt-reve-de-dragon .monnaie-content .form-group input[type="checkbox"] { flex: 0 0 20px; @@ -251,7 +251,7 @@ select, min-height: 100px; background: var(--rdd-bg-input-alt); padding: 5px; - border-radius: 3px; + border-radius: 0.2rem; color: var(--rdd-color-text-primary); } .system-foundryvtt-reve-de-dragon .munition-content .window-content { @@ -268,7 +268,7 @@ select, background: var(--fieldset-background); color: var(--rdd-color-text-primary); margin-bottom: 4px; - border-radius: 6px; + border-radius: 0.5rem; border-color: var(--rdd-color-text-primary); border-width: 2px; } @@ -298,7 +298,7 @@ select, border: 1px solid var(--rdd-color-border-input); color: var(--rdd-color-text-input); padding: 2px 2px; - border-radius: 3px; + border-radius: 0.2rem; } .system-foundryvtt-reve-de-dragon .munition-content .form-group input[type="checkbox"] { flex: 0 0 20px; @@ -342,7 +342,7 @@ select, min-height: 100px; background: var(--rdd-bg-input-alt); padding: 5px; - border-radius: 3px; + border-radius: 0.2rem; color: var(--rdd-color-text-primary); } .system-foundryvtt-reve-de-dragon .tarot-content .window-content { @@ -359,7 +359,7 @@ select, background: var(--fieldset-background); color: var(--rdd-color-text-primary); margin-bottom: 4px; - border-radius: 6px; + border-radius: 0.5rem; border-color: var(--rdd-color-text-primary); border-width: 2px; } @@ -389,7 +389,7 @@ select, border: 1px solid var(--rdd-color-border-input); color: var(--rdd-color-text-input); padding: 2px 2px; - border-radius: 3px; + border-radius: 0.2rem; } .system-foundryvtt-reve-de-dragon .tarot-content .form-group input[type="checkbox"] { flex: 0 0 20px; @@ -530,7 +530,7 @@ select, margin: 0.1rem 0; } .system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section subline .warning { - border-radius: 6px; + border-radius: 0.5rem; background: var(--gradient-warning); } .system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-img { @@ -560,6 +560,7 @@ select, .system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-detail subline div.poesie-extrait { display: flex; flex-direction: column; + align-items: normal; } .system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-detail subline span.status-surprise { display: flex; @@ -576,8 +577,12 @@ select, display: flow; width: 2.5rem; text-align: right; - margin: 0 0.2rem 0 0.5rem; + margin: 0 0.2rem; padding: 0 0.2rem; + border: 1px solid ; + border-radius: 0.2rem; + height: 1.5rem; + background: hsla(0, 0%, 0%, 0.2); } .system-foundryvtt-reve-de-dragon .roll-dialog roll-action { flex-basis: content; @@ -632,12 +637,13 @@ select, margin: 0 0.1rem; } .system-foundryvtt-reve-de-dragon .roll-dialog roll-carac select[name="select-carac"] { - max-width: 6rem; + min-width: 6.5rem; + max-width: 8rem; } .system-foundryvtt-reve-de-dragon .roll-dialog roll-comp select[name="select-comp"] { min-width: 8rem; - max-width: 11rem; - margin-left: 1rem; + max-width: 10rem; + margin-left: 1.5rem; } .system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="coeur"] select[name="coeur"] { max-width: 4rem; @@ -1463,38 +1469,38 @@ select, } .system-foundryvtt-reve-de-dragon .rdd-roll-part { align-items: center; - border-radius: 6px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-gold); } .system-foundryvtt-reve-de-dragon .rdd-roll-sign { - border-radius: 6px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-silver); } .system-foundryvtt-reve-de-dragon .rdd-roll-norm { - border-radius: 6px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-green); } .system-foundryvtt-reve-de-dragon .rdd-roll-notSign, .system-foundryvtt-reve-de-dragon .rdd-roll-echec { - border-radius: 6px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-red); } .system-foundryvtt-reve-de-dragon .rdd-roll-epart { - border-radius: 6px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-violet); } .system-foundryvtt-reve-de-dragon .rdd-roll-etotal { - border-radius: 6px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-purple-black); } .system-foundryvtt-reve-de-dragon .rdd-diviseur { - border-radius: 6px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-red); } @@ -1522,6 +1528,7 @@ select, font-style: italic; color: rgba(82, 17, 131, 0.9); overflow-y: scroll; + width: 100%; } .system-foundryvtt-reve-de-dragon .poesie-reference { font-size: 0.7rem; @@ -1587,7 +1594,7 @@ select, height: var(--form-field-height); margin: 0; color: var(--color-text-dark-primary); - border-radius: 3px; + border-radius: 0.2rem; } .system-foundryvtt-reve-de-dragon .app-calendar-astrologie div.theme-astral { width: 14rem; @@ -1638,7 +1645,7 @@ select, background: hsla(280, 50%, 50%, 0.1); padding: 1px 4px; border: 1px solid var(--color-border-dark-tertiary); - border-radius: 2px; + border-radius: 0.2rem; white-space: nowrap; word-break: break-all; } @@ -1648,7 +1655,7 @@ select, font-weight: 560; padding: 0.1rem 0.3rem; border: 1px solid var(--color-border-dark-tertiary); - border-radius: 0.25rem; + border-radius: 0.2rem; white-space: nowrap; word-break: break-all; display: ruby; @@ -1768,7 +1775,7 @@ select, .system-foundryvtt-reve-de-dragon .xp-level-up { margin: 0.1rem; box-shadow: inset 0px 0px 1px #00000096; - border-radius: 0.25rem; + border-radius: 0.2rem; padding: 0.1rem; flex: 1 1 5rem; background: var(--gradient-gold) !important; @@ -1799,7 +1806,7 @@ select, .system-foundryvtt-reve-de-dragon .list-item { margin: 0.1rem; box-shadow: inset 0px 0px 1px #00000096; - border-radius: 0.25rem; + border-radius: 0.2rem; padding: 0.1rem; flex: 1 1 1.5rem; display: flex; @@ -2112,6 +2119,9 @@ select, font-size: 0.7rem; flex-grow: 3; } +.system-foundryvtt-reve-de-dragon .chat-message header.message-header .message-metadata { + flex-grow: 3.5; +} .system-foundryvtt-reve-de-dragon .chat-message hr { margin: 0.2rem 0; } @@ -2332,7 +2342,7 @@ select, font-size: 0.8rem; text-align: center; vertical-align: middle; - border-radius: 0.3rem; + border-radius: 0.2rem; } .system-foundryvtt-reve-de-dragon div.horloge-roue div img { border: none; @@ -2659,7 +2669,7 @@ select, .system-foundryvtt-reve-de-dragon :is(.tooltip, .tooltip-overflow) .ttt-ajustements { width: 10rem; background: var(--background-tooltip); - border-radius: 6px; + border-radius: 0.5rem; font-size: 0.9rem; padding: 3px 0; } diff --git a/icons/cuisine/gibier.svg b/icons/cuisine/gibier.svg new file mode 100644 index 00000000..1a0fb9d3 --- /dev/null +++ b/icons/cuisine/gibier.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/cuisine/herbe.svg b/icons/cuisine/herbe.svg new file mode 100644 index 00000000..f992dfe1 --- /dev/null +++ b/icons/cuisine/herbe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/cuisine/mortadelle.svg b/icons/cuisine/mortadelle.svg new file mode 100644 index 00000000..d30c66d5 --- /dev/null +++ b/icons/cuisine/mortadelle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/cuisine/plante.svg b/icons/cuisine/plante.svg new file mode 100644 index 00000000..527bb7bb --- /dev/null +++ b/icons/cuisine/plante.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/cuisine/ragout.svg b/icons/cuisine/ragout.svg new file mode 100644 index 00000000..92772579 --- /dev/null +++ b/icons/cuisine/ragout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/cuisine/saucisson.svg b/icons/cuisine/saucisson.svg new file mode 100644 index 00000000..4f432858 --- /dev/null +++ b/icons/cuisine/saucisson.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/cuisine/volaille.svg b/icons/cuisine/volaille.svg new file mode 100644 index 00000000..4ba904f3 --- /dev/null +++ b/icons/cuisine/volaille.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/less/foundryvtt-reve-de-dragon.less b/less/foundryvtt-reve-de-dragon.less index 1c19104b..fd300b3e 100644 --- a/less/foundryvtt-reve-de-dragon.less +++ b/less/foundryvtt-reve-de-dragon.less @@ -777,31 +777,31 @@ } .rdd-roll-part { align-items: center; - border-radius: 6px; padding: 3px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-gold); } .rdd-roll-sign{ - border-radius: 6px; padding: 3px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-silver); } .rdd-roll-norm{ - border-radius: 6px; padding: 3px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-green); } .rdd-roll-notSign, .rdd-roll-echec{ - border-radius: 6px; padding: 3px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-red); } .rdd-roll-epart{ - border-radius: 6px; padding: 3px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-violet); } .rdd-roll-etotal{ - border-radius: 6px; padding: 3px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-purple-black); } .rdd-diviseur{ - border-radius: 6px; padding: 3px; + border-radius: 0.5rem; padding: 3px; background: var(--gradient-red); } @@ -833,14 +833,9 @@ font-style: italic; color: rgba(82, 17, 131, 0.9); overflow-y: scroll; - // overflow: hidden; + width: 100%; } - // .poesie-extrait:hover { - // overflow-y: scroll; - // opacity: 1; - // } - .poesie-reference { font-size: 0.7rem; text-align: right; @@ -913,7 +908,7 @@ height: var(--form-field-height); margin: 0; color: var(--color-text-dark-primary); - border-radius: 3px; + border-radius: 0.2rem; } .app-calendar-astrologie{ div.theme-astral{ @@ -970,7 +965,7 @@ background: hsla(280, 50%, 50%, 0.1); padding: 1px 4px; border: 1px solid var(--color-border-dark-tertiary); - border-radius: 2px; + border-radius: 0.2rem; white-space: nowrap; word-break: break-all; } @@ -981,7 +976,7 @@ font-weight: 560; padding: 0.1rem 0.3rem; border: 1px solid var(--color-border-dark-tertiary); - border-radius: 0.25rem; + border-radius: 0.2rem; white-space: nowrap; word-break: break-all; display: ruby; @@ -1111,7 +1106,7 @@ .xp-level-up { margin: 0.1rem; box-shadow: inset 0px 0px 1px #00000096; - border-radius: 0.25rem; + border-radius: 0.2rem; padding: 0.1rem; flex: 1 1 5rem; background: var(--gradient-gold) !important; @@ -1142,7 +1137,7 @@ .list-item { margin: 0.1rem; box-shadow: inset 0px 0px 1px #00000096; - border-radius: 0.25rem; + border-radius: 0.2rem; padding: 0.1rem; flex: 1 1 1.5rem; display: flex; @@ -1483,10 +1478,15 @@ .message-content { text-align: justify; } - header.message-header .heure-rdd { - font-size: 0.7rem; - flex-grow: 3; - } + header.message-header{ + .heure-rdd { + font-size: 0.7rem; + flex-grow: 3; + } + .message-metadata { + flex-grow: 3.5; + } + } hr { margin: 0.2rem 0; } @@ -1685,7 +1685,7 @@ font-size: 0.8rem; text-align: center; vertical-align: middle; - border-radius: 0.3rem; + border-radius: 0.2rem; } div.horloge-roue div img { @@ -1921,7 +1921,7 @@ .ttt-ajustements { width: 10rem; background: var(--background-tooltip); - border-radius: 6px; + border-radius: 0.5rem; font-size: 0.9rem; padding: 3px 0; div:nth-child(odd) { diff --git a/less/roll-dialog.less b/less/roll-dialog.less index ba05a596..567c0f33 100644 --- a/less/roll-dialog.less +++ b/less/roll-dialog.less @@ -90,7 +90,7 @@ flex-direction: row; margin: 0.1rem 0; .warning { - border-radius: 6px; + border-radius: 0.5rem; background: var(--gradient-warning); } } @@ -121,6 +121,7 @@ div.poesie-extrait{ display: flex; flex-direction: column; + align-items: normal; } span.status-surprise{ display: flex; @@ -141,8 +142,13 @@ display: flow; width: 2.5rem; text-align: right; - margin: 0 0.2rem 0 0.5rem; + margin: 0 0.2rem; padding: 0 0.2rem; + border: 1px solid ; + border-radius: 0.2rem ; + background: hsla(0, 0%, 0%, 0.2); + height: 1.5rem; + background: hsla(0, 0%, 0%, 0.2); } roll-action { @@ -205,14 +211,14 @@ } roll-carac select[name="select-carac"] { - max-width: 6rem; - - } + min-width: 6.5rem; + max-width: 8rem; + } roll-comp select[name="select-comp"] { min-width: 8rem; - max-width: 11rem; - margin-left: 1rem; - } + max-width: 10rem; + margin-left: 1.5rem; + } roll-conditions roll-section[name="coeur"] select[name="coeur"] { max-width: 4rem; diff --git a/less/sheets.less b/less/sheets.less index 2919d5d8..91bf89f6 100644 --- a/less/sheets.less +++ b/less/sheets.less @@ -8,7 +8,7 @@ min-height: 100px; // Hauteur minimale pour la description background: var(--rdd-bg-input-alt); // Une couleur de fond alternative padding: 5px; - border-radius: 3px; + border-radius: 0.2rem; color: var(--rdd-color-text-primary); } @@ -28,7 +28,7 @@ background: var(--fieldset-background); color: var(--rdd-color-text-primary); margin-bottom: 4px; - border-radius: 6px; + border-radius: 0.5rem; border-color: var(--rdd-color-text-primary); border-width: 2px; } @@ -64,7 +64,7 @@ --rdd-color-text-input ); // Assurez-vous que cette variable existe padding: 2px 2px; // Augmentation du padding vertical - border-radius: 3px; + border-radius: 0.2rem; } input[type="checkbox"] { diff --git a/module/actor.js b/module/actor.js index dadeadfa..8374e42c 100644 --- a/module/actor.js +++ b/module/actor.js @@ -51,6 +51,7 @@ import { ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION } from "./roll/roll-constants.mjs"; import { PART_TACHE } from "./roll/roll-part-tache.mjs"; import { PART_COMP } from "./roll/roll-part-comp.mjs"; import { PART_OEUVRE } from "./roll/roll-part-oeuvre.mjs"; +import { PART_CUISINE } from "./roll/roll-part-cuisine.mjs"; export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre'] @@ -1937,10 +1938,11 @@ export class RdDActor extends RdDBaseActorSang { type: { allowed: [PART_COMP], current: PART_COMP }, selected: { carac: { key: caracName }, - comp: { key: compName, forced: options.forced } + comp: { key: compName, forced: options.forced }, + diff: { value: diff ?? 0 } } } - RollDialog.create(rollData, options) + RollDialog.create(rollData, foundry.utils.mergeObject(options, { onRollDone: RollDialog.onRollDoneClose })) return } @@ -2064,7 +2066,7 @@ export class RdDActor extends RdDBaseActorSang { selected: { meditation: { key: id } }, type: { allowed: [ROLL_TYPE_MEDITATION], current: ROLL_TYPE_MEDITATION } } - await RollDialog.create(rollData) + await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose }) return } @@ -3210,14 +3212,26 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async rollRecetteCuisine(id) { - const oeuvre = this.getRecetteCuisine(id); + const recette = this.getRecetteCuisine(id); + if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { + const rollData = { + ids: { actorId: this.id }, + type: { allowed: [PART_CUISINE], current: PART_CUISINE }, + selected: { + cuisine: { key: recette.id } + } + } + RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose }) + return + } + const artData = { verbe: 'Cuisiner', compName: 'cuisine', proportions: 1, ajouterEquipement: false }; - await this._rollArtV1(artData, 'odoratgout', oeuvre, r => this._resultRecetteCuisine(r)); + await this._rollArtV1(artData, 'odoratgout', recette, r => this._resultRecetteCuisine(r)); } /* -------------------------------------------- */ @@ -3250,6 +3264,18 @@ export class RdDActor extends RdDBaseActorSang { } async preparerNourriture(item) { + if (item.getUtilisationCuisine() == 'brut' && OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { + const rollData = { + ids: { actorId: this.id }, + type: { allowed: [PART_CUISINE], current: PART_CUISINE }, + selected: { + cuisine: { key: item.id } + } + } + RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose }) + return + } + if (item.getUtilisationCuisine() == 'brut') { const nourriture = { name: 'Plat de ' + item.name, @@ -3260,7 +3286,7 @@ export class RdDActor extends RdDBaseActorSang { exotisme: item.system.exotisme, ingredients: item.name } - }; + } const artData = { verbe: 'Préparer', compName: 'cuisine', diff --git a/module/chat-utility.js b/module/chat-utility.js index a1c9e1d9..68f88d4f 100644 --- a/module/chat-utility.js +++ b/module/chat-utility.js @@ -191,7 +191,7 @@ export class ChatUtility { const timestamp = new RdDTimestamp(rddTimestamp); const timestampData = timestamp.toCalendrier(); const dateHeure = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs', timestampData); - $(html).find('header.message-header .message-sender').after(dateHeure) + $(html).find('header.message-header .message-timestamp').after(dateHeure) } } diff --git a/module/roll/chat-roll-result.mjs b/module/roll/chat-roll-result.mjs index 0d24bbf6..0371c911 100644 --- a/module/roll/chat-roll-result.mjs +++ b/module/roll/chat-roll-result.mjs @@ -7,6 +7,7 @@ import { RdDResolutionTable } from "../rdd-resolution-table.js" import { RDD_CONFIG, renderTemplate } from "../constants.js" import { EMPOIGNADE } from "../item/arme.js" import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js" +import { RollTypeCuisine } from "./roll-type-cuisine.mjs" export default class ChatRollResult { static init() { @@ -25,7 +26,7 @@ export default class ChatRollResult { }) } - async display(roll) { + async display(roll, impacts) { this.prepareDisplay(roll) const chatMessage = await ChatUtility.createChatWithRollMode( @@ -35,7 +36,8 @@ export default class ChatRollResult { roll.active.actor, roll.current?.rollmode?.key ) - const save = RollDialog.saveParts(roll) + const save = RollDialog.saveParts(roll, impacts) + ChatUtility.setMessageData(chatMessage, 'rollData', save) return chatMessage } @@ -109,6 +111,7 @@ export default class ChatRollResult { $(html).on("click", '.encaissement', event => this.onClickEncaissement(event)) $(html).on("click", '.resister-recul', event => this.onClickRecul(event)) $(html).on("click", '.choix-particuliere', event => this.onClickChoixParticuliere(event)) + $(html).on("click", '.faire-gouter', event => this.onClickFaireGouter(event)) } @@ -143,6 +146,7 @@ export default class ChatRollResult { onAppelChanceSuccess(savedRoll, chatMessage) { const reRoll = foundry.utils.duplicate(savedRoll) + console.log('onAppelChanceSuccess savedRoll', savedRoll) reRoll.type.retry = true const callbacks = [r => ChatUtility.removeChatMessageId(chatMessage.id)] // TODO: annuler les effets @@ -211,4 +215,9 @@ export default class ChatRollResult { await this.updateChatMessage(chatMessage, savedRoll) await this.getCombat(savedRoll)?.onAttaqueV2(savedRoll, callbacks) } + async onClickFaireGouter(event) { + const chatMessage = ChatUtility.getChatMessage(event) + const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData') + await new RollTypeCuisine().onFaireGouter(savedRoll) + } } \ No newline at end of file diff --git a/module/roll/roll-basic-parts.mjs b/module/roll/roll-basic-parts.mjs index e1b0b3f0..513470a0 100644 --- a/module/roll/roll-basic-parts.mjs +++ b/module/roll/roll-basic-parts.mjs @@ -1,4 +1,4 @@ -import { ActorToken } from "../actor-token.mjs" +import { TokenActor } from "../technical/actor-token.mjs" import { StatusEffects } from "../settings/status-effects.js" import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs" import { PART_ATTAQUE } from "./roll-part-attaque.mjs" @@ -9,8 +9,8 @@ export class RollBasicParts { static restore(rollData) { rollData.ids.sceneId = rollData.ids.sceneId ?? canvas.scene.id - rollData.active = RollBasicParts.$getActor(rollData) - rollData.opponent = RollBasicParts.$getOpponent(rollData) + rollData.active = RollBasicParts.getTokenActor(rollData) + rollData.opponent = RollBasicParts.getTokenActorOpponent(rollData) if (rollData.type.opposed == undefined) { rollData.type.opposed = rollData.opponent != null } @@ -64,30 +64,30 @@ export class RollBasicParts { } } - static $getActor(rollData) { + static getTokenActor(rollData) { if (rollData.ids.actorTokenId) { - return ActorToken.fromTokenId(rollData.ids.actorTokenId, rollData.ids.sceneId) + return TokenActor.fromTokenId(rollData.ids.actorTokenId, rollData.ids.sceneId) } else { const actorId = rollData.ids.actorId ?? (canvas.tokens.controlled.length == 1 /** TODO: jets de plusieurs personnages??? */ ? canvas.tokens.controlled[0] : undefined) - return ActorToken.fromActorId(actorId, () => { throw new Error("Pas d'acteur sélectionné") }) + return TokenActor.fromActorId(actorId, () => { throw new Error("Pas d'acteur sélectionné") }) } } - static $getOpponent(rollData) { + static getTokenActorOpponent(rollData) { if (rollData.ids.opponentTokenId) { - return ActorToken.fromTokenId(rollData.ids.opponentTokenId, rollData.ids.sceneId) + return TokenActor.fromTokenId(rollData.ids.opponentTokenId, rollData.ids.sceneId) } else if (rollData.ids.opponentId) { - return ActorToken.fromActorId(rollData.ids.opponentId) + return TokenActor.fromActorId(rollData.ids.opponentId) } else { const targets = Array.from(game.user.targets) if (targets.length == 1) { - return ActorToken.fromToken(targets[0]) + return TokenActor.fromToken(targets[0]) } else { return undefined diff --git a/module/roll/roll-dialog.mjs b/module/roll/roll-dialog.mjs index 89468c4e..03c6a1e5 100644 --- a/module/roll/roll-dialog.mjs +++ b/module/roll/roll-dialog.mjs @@ -43,6 +43,7 @@ import { renderTemplate } from "../constants.js"; import { RollTypeCuisine } from "./roll-type-cuisine.mjs"; import { RollPartCuisine } from "./roll-part-cuisine.mjs"; import { OptionsAvancees, ROLL_DIALOG_V2_TEST } from "../settings/options-avancees.js"; +import { ActorImpacts } from "../technical/actor-impacts.mjs"; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api @@ -292,7 +293,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 return rollData } - static saveParts(rollData) { + static saveParts(rollData, impacts) { const target = RollBasicParts.initFrom(rollData) ROLL_PARTS.filter(p => p.isActive(rollData)) .forEach(p => p.storeClean(rollData, target)) @@ -301,6 +302,12 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 target.result = rollData.result target.done = rollData.done ?? {} target.dmg = rollData.dmg + if (impacts) { + target.reverse = { + active: impacts.active?.reverseImpacts(), + opponent: impacts.opponent?.reverseImpacts() + } + } return target } @@ -442,18 +449,29 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 roll.current.resultat = this.rollData.current[PART_TRICHER]?.resultat ?? -1 roll.choix = {} roll.rolled = await RollDialogAdapter.rollDice(roll, this.rollTitle(roll)) - roll.result = selectedRollType.getResult(roll) - + + const impacts = { + active: new ActorImpacts(roll.active), + opponent: roll.opponent ? new ActorImpacts(roll.opponent) : undefined + } + + roll.result = selectedRollType.getResult(roll, impacts) + console.info('RollDialog.roll:', roll) const callbacks = [ ...this.rollOptions.callbacks, ...selectedRollType.callbacks(this.rollOptions), ] + await Promise.all(callbacks.map(async callback => await callback(roll))) - await this.chatRollResult.display(roll) + + await impacts.active?.applyImpacts() + await impacts.opponent?.applyImpacts() + selectedRollType.onApplyImpacts(roll, impacts) + await this.chatRollResult.display(roll, impacts) this.rollOptions.onRollDone(this) } - + loadRollData(roll) { RollDialog.$prepareRollData(roll) RollDialog.calculAjustements(roll) diff --git a/module/roll/roll-part-cuisine.mjs b/module/roll/roll-part-cuisine.mjs index fa60128d..cedfaef9 100644 --- a/module/roll/roll-part-cuisine.mjs +++ b/module/roll/roll-part-cuisine.mjs @@ -19,55 +19,153 @@ export class RollPartCuisine extends RollPartSelect { isValid(rollData) { return rollData.active.actor.isPersonnage() } visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_CUISINE) } + restore(rollData) { + super.restore(rollData) + this.$restoreSavedOptions(rollData) + } + + store(rollData, targetData) { + const current = this.getCurrent(rollData) + this.setSaved(targetData, { + key: current.key, + fabriquer: current.fabriquer, + proportions: current.proportions, + value: current.value, + }) + } + loadRefs(rollData) { const refs = this.getRefs(rollData) - refs.recettes = rollData.active.actor.items + const actor = rollData.active.actor + refs.cuisine = actor.getCompetence('Cuisine') + + const recettes = actor.items .filter(it => it.type == ITEM_TYPES.recettecuisine) - .map(it => RollPartCuisine.$extractRecette(it, rollData.active.actor)) - if (refs.recettes.length > 0) { - this.$selectRecette(rollData) + .map(RollPartCuisine.$extractPreparationRecette) + + const ingredientsBruts = actor.items + .filter(it => it.getUtilisationCuisine() == 'brut') + .map(RollPartCuisine.$extractPreparationBrut) + + refs.preparations = [RollPartCuisine.$preparationBasique(), ...recettes, ...ingredientsBruts] + refs.preparations.forEach(p => p.comp = refs.cuisine) + if (refs.preparations.length > 0) { + this.$selectPreparation(rollData) + this.$restoreSavedOptions(rollData) } } - choices(refs) { return refs.recettes } + $restoreSavedOptions(rollData) { + const saved = this.getSaved(rollData) + const current = this.getCurrent(rollData) + if (saved.fabriquer != undefined) { + current.fabriquer = saved.fabriquer + } + if (saved.proportions != undefined) { + current.proportions = saved.proportions + } + if (saved.value != undefined) { + current.value = saved.value + } + } - static $extractRecette(recette, actor) { + choices(refs) { return refs.preparations } + + static $preparationBasique() { + return { + key: '', + label: "Improvisation du moment", + img: RollPartCuisine.$getImgIngredient(), + sust: 1, + exotisme: 0, + ingredients: "Ce qu'il y a sous la main", + proportions: 8, + proportionsMax: 50, + value: 0, + fabriquer: false, + } + } + + static $extractPreparationRecette(recette) { + const proportions = recette.system.sust ?? 1 return { key: recette.id, label: recette.name, - caracs: RollPartCuisine.getCaracs(recette), - qualite: recette.system.niveau, + img: 'systems/foundryvtt-reve-de-dragon/icons/cuisine/ragout.svg', + sust: 1, + exotisme: recette.system.exotisme, + ingredients: recette.system.ingredients, + proportions: proportions, + proportionsMax: proportions * 10, value: -recette.system.niveau, recette: recette, - comp: actor.getCompetence('Cuisine') + fabriquer: true, } } - static getCaracs(recette){ - // TODO: permettre différentes caractéristiques pour la cuisine? - return [CARACS.ODORATGOUT, CARACS.EMPATHIE, CARACS.DEXTERITE] + + static $extractPreparationBrut(ingredient) { + return { + key: ingredient.id, + label: ingredient.name + ' cuisiné', + img: RollPartCuisine.$getImgIngredient(ingredient.type), + sust: ingredient.system.sust ?? 1, + exotisme: ingredient.system.exotisme, + ingredients: ingredient.name, + proportions: Math.min(10, ingredient.system.quantite), + proportionsMax: Math.min(50, ingredient.system.quantite), + value: 0, + ingredient: ingredient, + fabriquer: true, + } } - $selectRecette(rollData, key) { + static $getImgIngredient(type = ITEM_TYPES.ingredient) { + switch (type) { + case ITEM_TYPES.herbe: + case ITEM_TYPES.plante: + return `systems/foundryvtt-reve-de-dragon/icons/cuisine/${type}.svg` + case ITEM_TYPES.faune: + return 'systems/foundryvtt-reve-de-dragon/icons/cuisine/gibier.svg' + } + return 'systems/foundryvtt-reve-de-dragon/icons/cuisine/ragout.svg' + } + + $selectPreparation(rollData, key) { this.selectByKey(rollData, key, 0) } async _onRender(rollDialog, context, options) { - const selectRecette = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-recette"]`) + const current = this.getCurrent(rollDialog.rollData) - selectRecette.addEventListener("change", e => { + const selectPreparation = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-preparation"]`) + const inputDiff = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="diff-var"]`) + const checkboxFabriquer = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="fabriquer"]`) + const inputProportions = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="proportions"]`) + + selectPreparation.addEventListener("change", e => { const selectOptions = e.currentTarget.options const index = selectOptions.selectedIndex - this.$selectRecette(rollDialog.rollData, selectOptions[index]?.value) + this.$selectPreparation(rollDialog.rollData, selectOptions[index]?.value) rollDialog.render() }) + + checkboxFabriquer?.addEventListener("change", e => { + current.fabriquer = e.currentTarget.checked + }) + inputDiff?.addEventListener("change", e => { + current.value = parseInt(e.currentTarget.value) + }) + inputProportions?.addEventListener("change", e => { + current.proportions = parseInt(e.currentTarget.value) + }) + } impactOtherPart(part, rollData) { if (this.visible(rollData)) { - const current = this.getCurrent(rollData) switch (part.code) { - case PART_CARAC: return part.filterCaracs(rollData, current.caracs) - case PART_COMP: return part.filterComps(rollData, [current.comp?.name]) + case PART_CARAC: return part.filterCaracs(rollData, [CARACS.ODORATGOUT]) + case PART_COMP: return part.filterComps(rollData, [this.getRefs(rollData).cuisine.name]) } } return undefined diff --git a/module/roll/roll-type-cuisine.mjs b/module/roll/roll-type-cuisine.mjs index 7ab82f6b..bcb84ae6 100644 --- a/module/roll/roll-type-cuisine.mjs +++ b/module/roll/roll-type-cuisine.mjs @@ -1,3 +1,5 @@ +import { ITEM_TYPES } from "../constants.js" +import { RollBasicParts } from "./roll-basic-parts.mjs" import { DIFF, ROLL_TYPE_CUISINE } from "./roll-constants.mjs" import { PART_CUISINE } from "./roll-part-cuisine.mjs" import { RollType } from "./roll-type.mjs" @@ -9,19 +11,73 @@ export class RollTypeCuisine extends RollType { visible(rollData) { return rollData.active.actor.isPersonnage() } title(rollData) { const current = rollData.current[PART_CUISINE] - return `prépare une recette: ${current.label}` + return current.recette ? `prépare une recette: ${current.label}` : `prépare: ${current.label}` } onSelect(rollData) { this.setDiffType(rollData, DIFF.AUCUN) } - getResult(rollData){ + getResult(rollData, impacts) { const current = rollData.current[PART_CUISINE] - const qualite = rollData.rolled.isSuccess ? current.qualite : Math.min(current.qualite, current.comp.system.niveau) - return { - qualite: qualite + rollData.rolled.ptQualite + const diff = -current.value + const cuisine = rollData.refs[PART_CUISINE].cuisine + const qualite = rollData.rolled.ptQualite + (rollData.rolled.isSuccess ? diff : Math.min(diff, cuisine.system.niveau)) + + const result = { + qualite: qualite, + exotisme: Math.min(Math.min(qualite, current.exotisme ?? 0), 0), + messages: [] } + if (current.fabriquer) { + const plat = this.$prepareNourriture(rollData.active.name, current, result) + result.messages.push(`${plat.system.quantite} ${plat.name} ont été préparés dans l'équipement`) + impacts.active.addCreatedItem(plat) + result.plat = { id: plat.id } + } + if (current.ingredient) { + const quantite = Math.min(current.proportions, current.ingredient.system.quantite) + if (quantite == current.ingredient.system.quantite) { + impacts.active.addDeletedItem(current.ingredient) + result.messages.push(`Il n'y a plus de ${ingredient.name}`) + } + else { + impacts.active.addItemDelta(current.ingredient, 'system.quantite', -current.proportions) + result.messages.push(`${current.proportions} ${current.ingredient.name} ont été utilisés`) + } + } + return result + } + onApplyImpacts(roll, impacts) { + if (roll.result.plat) { + // le plat n'est pas créé immédiatement, il faut donc retrouver l'id + roll.result.plat.id = impacts.active.itemCreates.find(it => it.id = roll.result.plat.id)?.createdId + } + } + + $prepareNourriture(cuisinier, current, result) { + return { + id: foundry.utils.randomID(16), + name: current.label, + img: current.img, + type: ITEM_TYPES.nourritureboisson, + system: { + sust: current.sust, + cuisinier: cuisinier, + exotisme: result.exotisme, + encombrement: 0.1, + quantite: current.proportions, + qualite: result.qualite, + cout: result.qualite > 0 ? (result.qualite * 0.01) : 0.01, + } + } + } + + async onFaireGouter(savedRoll) { + const actor = RollBasicParts.getTokenActor(savedRoll).actor + const platId = savedRoll.result.plat.id + const plat = actor.items.get(platId) + await plat?.proposerVente() } } diff --git a/module/roll/roll-type-oeuvre.mjs b/module/roll/roll-type-oeuvre.mjs index 1cfbc90d..5033f246 100644 --- a/module/roll/roll-type-oeuvre.mjs +++ b/module/roll/roll-type-oeuvre.mjs @@ -16,11 +16,12 @@ export class RollTypeOeuvre extends RollType { this.setDiffType(rollData, DIFF.AUCUN) } - getResult(rollData){ + getResult(rollData, impacts) { const current = rollData.current[PART_OEUVRE] const qualite = rollData.rolled.isSuccess ? current.qualite : Math.min(current.qualite, current.comp.system.niveau) return { - qualite: qualite + rollData.rolled.ptQualite + qualite: qualite + rollData.rolled.ptQualite, + messages: [] } } diff --git a/module/roll/roll-type.mjs b/module/roll/roll-type.mjs index 124f503d..4f7ed51e 100644 --- a/module/roll/roll-type.mjs +++ b/module/roll/roll-type.mjs @@ -53,5 +53,14 @@ export class RollType { callbacks(rollOptions) { return [] } - getResult(rollData) { return undefined } + /** + * Préparation des résultats d'un jet pour ce type de jet + * + * @param {*} rollData les données du jet, incluans la partie rolled + * @param {*} impacts une structure composée de deux ActorImpacts {active, opponent} + * pour stocker les effets sur ces deux participants au jey + * @returns undefined ou une structure contenant les informations requise pour afficher + */ + getResult(rollData, impacts) { return { messages: [] } } + onApplyImpacts(roll, impacts) { } } diff --git a/module/technical/actor-impacts.mjs b/module/technical/actor-impacts.mjs new file mode 100644 index 00000000..43420384 --- /dev/null +++ b/module/technical/actor-impacts.mjs @@ -0,0 +1,128 @@ + +/** + * class designed to store actor modification instructions, to apply them in a single operation, and have the ability to revert these + */ +export class ActorImpacts { + constructor(actorToken) { + this.actorToken = actorToken + this.updates = [] + this.deltas = [] + this.itemCreates = [] + this.itemUpdates = [] + this.itemDeletes = [] + } + + addActorUpdate(path, value) { + this.updates.push([path, value]) + } + + addActorDelta(path, value) { + const intValue = Number.parseInt(value) + if (Number.isInteger(intValue) && intValue != 0) { + const delta = [path, intValue] + this.deltas.push(delta) + } + else { + console.error('Cannot use non integer value {} for delta update', value) + } + } + + addDeletedItem(item) { + this.itemDeletes.push(item) + } + addCreatedItem(item) { + this.itemCreates.push(item) + } + + addItemUpdate(item, path, value) { + const existing = this.itemUpdates.find(it => it.id == item.id) + const update = [path, value] + if (existing) { + existing.updates.push(update) + } + else { + this.itemUpdates.push({ id: item.id, updates: [update], deltas: [] }) + } + } + + addItemDelta(item, path, value) { + const intValue = Number.parseInt(value) + if (Number.isInteger(intValue) && intValue != 0) { + const delta = [path, intValue] + const existing = this.itemUpdates.find(it => it.id == item.id) + if (existing) { + existing.deltas.push(delta) + } + else { + this.itemUpdates.push({ id: item.id, updates: [], deltas: [delta] }) + } + } + else { + console.error('Cannot use non integer value {} for delta update', value) + } + } + + reverseImpacts() { + const reverse = ActorImpacts.$computeReverts(new ActorImpacts(this.actorToken), this, __ => this.actorToken.actor) + reverse.itemCreates = this.itemDeletes.map(it => foundry.utils.duplicate(it)) + reverse.itemDeletes = this.itemCreates.map(it => { return { id: it.id } }) + reverse.itemUpdates = this.itemUpdates.map(it => ActorImpacts.$computeReverts({ id: it.id }, it, id => this.$getActorItem(id))) + return reverse + } + + toStorable() { + delete this.actorToken + return this + } + + async applyImpacts() { + const actor = this.actorToken.actor + const isItemsDelete = this.itemDeletes.length > 0 + const isItemsCreate = this.itemCreates.length > 0 + const isItemsUpdate = this.itemUpdates.length > 0 + const isActorUpdate = this.updates.length > 0 || this.deltas.length > 0 + + if (isItemsDelete) { + const deletes = this.itemDeletes.map(it => it.id) + await actor.deleteEmbeddedDocuments('Item', deletes, { render: !(isItemsCreate || isItemsUpdate || isActorUpdate) }) + } + + if (isItemsCreate) { + const creates = this.itemCreates + const created = await actor.createEmbeddedDocuments('Item', creates, { render: !(isItemsUpdate || isActorUpdate)}) + for (let i=0; i ActorImpacts.$computeUpdates(u, id => this.$getActorItem(id))) + await actor.updateEmbeddedDocuments('Item', updates, { render: !isActorUpdate }) + } + + if (isActorUpdate) { + const updates = ActorImpacts.$computeUpdates(this, id => actor) + await actor.update(updates, { render: true }) + } + } + + $getActorItem(id) { + return this.actorToken.actor.items.get(id) + } + + static $computeUpdates(u, getSource) { + const source = getSource(u.id) + const instruction = { _id: u.id } + u.updates.forEach(u => instruction[u[0]] = u[1]) + u.deltas.forEach(u => instruction[u[0]] = foundry.utils.getProperty(source, u[0]) + u[1]) + return instruction + } + + static $computeReverts(target, u, getSource) { + const source = getSource(u.id) + target.updates = u.updates.map(u => [u[0], foundry.utils.getProperty(source, u[0])]) + target.deltas = u.deltas.map(d => [d[0], -d[1]]) + return target + } + +} diff --git a/module/actor-token.mjs b/module/technical/actor-token.mjs similarity index 84% rename from module/actor-token.mjs rename to module/technical/actor-token.mjs index 8a05ee30..c657eef9 100644 --- a/module/actor-token.mjs +++ b/module/technical/actor-token.mjs @@ -1,9 +1,9 @@ /** * class providing the actor and token, and choosing the name and image from the token if available. */ -export class ActorToken { +export class TokenActor { static fromTokenActor(token, actor){ - return token ? ActorToken.fromToken(token) : ActorToken.fromActor(actor) + return token ? TokenActor.fromToken(token) : TokenActor.fromActor(actor) } static fromActorId(actorId, onError = () => undefined) { @@ -19,17 +19,17 @@ export class ActorToken { static fromActor(actor) { const token = actor.isToken ? actor.token : actor.prototypeToken - return ActorToken.fromToken(token) + return TokenActor.fromToken(token) } static fromTokenId(tokenId, sceneId = undefined) { const tokensList = sceneId ? game.scenes.get(sceneId).tokens : canvas.tokens.placeables const token = tokensList.get(tokenId) - return ActorToken.fromToken(token) + return TokenActor.fromToken(token) } static fromToken(token) { - return new ActorToken(token) + return new TokenActor(token) } constructor(token) { diff --git a/templates/common/date-heure.hbs b/templates/common/date-heure.hbs index a0f209fa..f5eb6cb2 100644 --- a/templates/common/date-heure.hbs +++ b/templates/common/date-heure.hbs @@ -1,3 +1,3 @@ \ No newline at end of file diff --git a/templates/roll/result/chat-attaque.hbs b/templates/roll/result/chat-attaque.hbs index ba173d6c..26c7f82f 100644 --- a/templates/roll/result/chat-attaque.hbs +++ b/templates/roll/result/chat-attaque.hbs @@ -1,7 +1,7 @@
- +
diff --git a/templates/roll/result/chat-comp.hbs b/templates/roll/result/chat-comp.hbs index 91d7323a..7a0f084d 100644 --- a/templates/roll/result/chat-comp.hbs +++ b/templates/roll/result/chat-comp.hbs @@ -1,7 +1,7 @@
- +
{{active.name}} fait un jet de {{current.comp.label}} diff --git a/templates/roll/result/chat-cuisine.hbs b/templates/roll/result/chat-cuisine.hbs index 3cc6126a..d3c707a3 100644 --- a/templates/roll/result/chat-cuisine.hbs +++ b/templates/roll/result/chat-cuisine.hbs @@ -1,10 +1,15 @@
- +
- {{active.name}} prépare une recette de niveau {{current.cuisine.recette.system.niveau}}: : {{current.cuisine.label}} ( + {{active.name}} + {{#if current.recette}} + prépare une recette de niveau {{current.cuisine.recette.system.niveau}}: {{current.cuisine.label}} + {{else}} + prépare {{current.label}}: {{current.cuisine.label}} + {{/if}}
@@ -14,16 +19,35 @@

- {{active.name}} - {{#if rolled.isSuccess}}réussit la recette avec - {{else}}manque d'inspiration, le plat a - {{/if}} - une qualité de {{result.qualite}}. + {{active.name}} + {{#if rolled.isSuccess}} + réussit la recette, pour un plat de qualité {{result.qualite~}} + {{#if (lt result.exotisme 0)}}et d'exotisme {{result.exotisme}}{{/if~}} + {{else}} + fait un piètre cuisinier, et obtient un plat de qualité {{result.qualite~}} + {{#if (lt result.exotisme 0)}}à l'exotisme certain ({{result.exotisme}}){{/if~}} + {{/if~}}. + {{#if (lt result.exotisme 0)}} +
Au vu de l'exotisme du plat, les convives devront réussir un jet de @roll[Volonté/Cuisine/{{result.exotisme}}]. + En cas d'échec, ils peuvent se forcer à faire plaisir à {{active.name}}, mais devront faire un jet de moral Malheureux. + {{/if}} + {{#each result.messages as |message|}} +
{{message}} + {{/each}}

{{> 'partial-info-appel-moral'}} {{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.hbs" current.cuisine.recette.system}}
+
+ {{#if current.cuisine.fabriquer}} + +   faire goûter à ses compagnons + + {{/if}} +
+
{{> 'partial-appel-chance'}}
diff --git a/templates/roll/result/chat-defense.hbs b/templates/roll/result/chat-defense.hbs index 975134a9..a16bee1e 100644 --- a/templates/roll/result/chat-defense.hbs +++ b/templates/roll/result/chat-defense.hbs @@ -1,7 +1,7 @@
- +
diff --git a/templates/roll/result/chat-jeu.hbs b/templates/roll/result/chat-jeu.hbs index 2d53be57..ddfa604c 100644 --- a/templates/roll/result/chat-jeu.hbs +++ b/templates/roll/result/chat-jeu.hbs @@ -1,8 +1,7 @@ - {{log 'jeu' this}}
- +
{{active.name}} Joue : {{current.jeu.label}} (niveau de base {{current.jeu.jeu.system.base}}) diff --git a/templates/roll/result/chat-meditation.hbs b/templates/roll/result/chat-meditation.hbs index 362bc806..7826a90f 100644 --- a/templates/roll/result/chat-meditation.hbs +++ b/templates/roll/result/chat-meditation.hbs @@ -1,7 +1,7 @@
- +
{{active.name}} a médité : {{current.meditation.label}} diff --git a/templates/roll/result/chat-oeuvre.hbs b/templates/roll/result/chat-oeuvre.hbs index da18ab17..cbd39ad9 100644 --- a/templates/roll/result/chat-oeuvre.hbs +++ b/templates/roll/result/chat-oeuvre.hbs @@ -1,7 +1,7 @@
- +
{{active.name}} {{current.oeuvre.art.action}}: {{current.oeuvre.label}} (de niveau {{current.oeuvre.oeuvre.system.niveau}}) diff --git a/templates/roll/roll-part-comp.hbs b/templates/roll/roll-part-comp.hbs index 82e1fddd..1a35b86a 100644 --- a/templates/roll/roll-part-comp.hbs +++ b/templates/roll/roll-part-comp.hbs @@ -2,4 +2,4 @@ {{selectOptions refs.comps selected=current.key valueAttr="key" labelAttr="label"}} {{plusMoins current.value}} - + diff --git a/templates/roll/roll-part-cuisine.hbs b/templates/roll/roll-part-cuisine.hbs index 0f88df9a..f8a3ef02 100644 --- a/templates/roll/roll-part-cuisine.hbs +++ b/templates/roll/roll-part-cuisine.hbs @@ -1,16 +1,53 @@ - + - + {{selectOptions refs.preparations selected=current.key valueAttr="key" labelAttr="label"}} {{#if current.recette}} {{plusMoins current.value}} + {{else if current.ingredient}} + {{numberInput current.value + name='diff-var' + step=1 + min=-10 + max=0 + disabled=rollData.type.retry + }} {{/if}} - {{#if current.recette}} - {{> 'roll-oeuvre-recettecuisine'}} + + + {{numberInput current.proportions + name='proportions' + step=1 + min=1 + max=(either current.proportionsMax 10) + disabled=rollData.type.retry + }} + {{#if (and current.sust (ne current.sust 1))}}(× {{current.sust}}){{/if}} + + + + + + {{#if current.ingredients}} + Ingrédients: + +
+ {{{current.ingredients}}} +
+
{{/if}} + {{#if current.recette}} + {{#if current.ingredients}} +
+ + {{/if}} + {{> "systems/foundryvtt-reve-de-dragon/templates/partial-description.hbs" current.recette.system}} + + {{/if}} +
\ No newline at end of file diff --git a/templates/roll/roll-part-sort.hbs b/templates/roll/roll-part-sort.hbs index 8279ce0f..6891c215 100644 --- a/templates/roll/roll-part-sort.hbs +++ b/templates/roll/roll-part-sort.hbs @@ -39,10 +39,11 @@ {{else}} + {{!-- TODO: proposer de mettre une HN/Taille de zone --}} {{/if}} Case TMR: {{current.caseTMR}} -{{#if current.bonusCase}} - Bonus case: {{plusMoins current.bonusCase}}% -{{/if}} + {{#if current.bonusCase}} + Bonus case: {{plusMoins current.bonusCase}}% + {{/if}}