From b80af454a2eb9b72f355d3da81958cf10be5a470 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Tue, 11 May 2021 00:52:25 +0200 Subject: [PATCH] Commandes pour les signes draconiques --- module/actor.js | 16 ++- .../dialog-create-signedraconique-actors.js | 114 ++++++++++++++++++ module/item-signedraconique-sheet.js | 39 ++---- module/item-signedraconique.js | 23 ++++ module/rdd-commands.js | 27 +++++ module/rdd-utility.js | 3 +- module/tmr-utility.js | 6 + templates/chat-signe-draconique-actor.html | 7 ++ .../dialog-create-signedraconique-actors.html | 57 +++++++++ templates/item-livre-sheet.html | 12 +- templates/item-signedraconique-sheet.html | 36 +++--- 11 files changed, 280 insertions(+), 60 deletions(-) create mode 100644 module/dialog-create-signedraconique-actors.js create mode 100644 templates/chat-signe-draconique-actor.html create mode 100644 templates/dialog-create-signedraconique-actors.html diff --git a/module/actor.js b/module/actor.js index a97b6bfe..e97805d8 100644 --- a/module/actor.js +++ b/module/actor.js @@ -194,7 +194,7 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ isHautRevant() { - return Misc.templateData(this).attributs.hautrevant.value != "" + return this.isPersonnage() && Misc.templateData(this).attributs.hautrevant.value != "" } /* -------------------------------------------- */ getFatigueActuelle() { @@ -1089,10 +1089,16 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ computeIsHautRevant() { - const tplData = Misc.templateData(this); - tplData.attributs.hautrevant.value = this.listItemsData('tete').find(it => Grammar.toLowerCaseNoAccent(it.name) == 'don de haut-reve') - ? "Haut rêvant" - : ""; + if (this.isPersonnage()){ + Misc.templateData(this).attributs.hautrevant.value = this.hasItemNamed('tete', 'don de haut-reve') + ? "Haut rêvant" + : ""; + } + } + + hasItemNamed(type, name) { + name = Grammar.toLowerCaseNoAccent(name); + return this.listItemsData(type).find(it => Grammar.toLowerCaseNoAccent(it.name) == name); } /* -------------------------------------------- */ diff --git a/module/dialog-create-signedraconique-actors.js b/module/dialog-create-signedraconique-actors.js new file mode 100644 index 00000000..7a475949 --- /dev/null +++ b/module/dialog-create-signedraconique-actors.js @@ -0,0 +1,114 @@ +import { ChatUtility } from "./chat-utility.js"; +import { HtmlUtility } from "./html-utility.js"; +import { RdDItemSigneDraconique } from "./item-signedraconique.js"; +import { Misc } from "./misc.js"; +import { TMRType, TMRUtility } from "./tmr-utility.js"; + +export class DialogCreateSigneDraconiqueForActors extends Dialog { + + static async createSigneForActors() { + let dialogData = { + signe: { + name: 'Un signe draconique', + type: "signedraconique", + img: 'systems/foundryvtt-reve-de-dragon/icons/tmr/gift.webp', + data: { + typesTMR: DialogCreateSigneDraconiqueForActors.selectRandomTmrs(), + ephemere: true, + duree: "1 round", + difficulte: -5, + valeur: { norm: 10, sign: 10, part: 15 }, + } + }, + actors: game.actors.filter(actor => actor.isHautRevant()).map(it => duplicate(Misc.data(it))) + }; + dialogData.tmrs = TMRUtility.listSelectedTMR(dialogData.signe.data.typesTMR ?? []); + dialogData.actors.forEach(it => it.selected = false); + + const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-create-signedraconique-actors.html", dialogData); + new DialogCreateSigneDraconiqueForActors(dialogData, html) + .render(true); + + } + + static selectRandomTmrs() { + let tmrs = Object.values(TMRType).map(value => Misc.upperFirst(value.name)); + const nbTmr = tmrs.length; + let remove = Math.floor(Math.random() * (nbTmr - 1)); + for (let i = nbTmr; i > remove; i--) { + tmrs.splice(Math.floor(Math.random() * i), 1); + } + return tmrs; + } + + constructor(dialogData, html, callback) { + let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 500, height: 650, 'z-index': 99999 }; + + let conf = { + title: "Créer un signe pour les personnages", + content: html, + default: "Créer le signe", + buttons: { "Créer le signe": { label: "Créer le signe", callback: it => { this._onCreerSigne(); } } } + }; + super(conf, options); + this.dialogData = dialogData; + } + + async _onCreerSigne() { + this.dialogData.actors.filter(it => it.selected).map(it => game.actors.get(it._id)) + .forEach(actor => this._createSigneForActor(actor, this.dialogData.signe)); + } + + async _createSigneForActor(actor, signe) { + actor.createEmbeddedDocuments("Item", [signe]); + ChatMessage.create({ + whisper: ChatUtility.getWhisperRecipientsAndGMs(Misc.data(actor).name), + content: await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.html", { + signe: signe, + alias: Misc.data(actor).name + }) + }); + } + + + /* -------------------------------------------- */ + activateListeners(html) { + super.activateListeners(html); + this.setEphemere(this.dialogData.signe.data.ephemere); + html.find(".signe-name").change((event) => this.dialogData.signe.name = event.currentTarget.value); + html.find(".signe-data-ephemere").change((event) => this.setEphemere(event.currentTarget.checked)); + html.find(".select-tmr").change((event) => this.onSelectTmr(event)); + html.find(".select-actor").change((event) => this.onSelectActor(event)); + html.find(".valeur-xp-sort").change((event) => this.onValeurXpSort(event)); + } + async setEphemere(ephemere){ + this.dialogData.signe.data.ephemere = ephemere; + HtmlUtility._showControlWhen($(".signe-data-duree"), ephemere); + } + + async onSelectTmr(event) { + event.preventDefault(); + this.dialogData.signe.data.typesTMR = $(".select-tmr").val(); + } + + async onSelectActor(event) { + event.preventDefault(); + let selectActor = $(".select-actor"); + const options = event.currentTarget.options; + for (var i = 0; i < options.length; i++) { // looping over the options + const actorId = options[i].attributes["data-actor-id"].value; + const actor = this.dialogData.actors.find(it => it._id == actorId); + if (actor) { + actor.selected = options[i].selected; + } + }; + } + + onValeurXpSort(event) { + const codeReussite = event.currentTarget.attributes['data-typereussite']?.value ?? 0; + const xp = Number(event.currentTarget.value); + const oldValeur = this.dialogData.signe.data.valeur; + this.dialogData.signe.data.valeur = RdDItemSigneDraconique.calculValeursXpSort(codeReussite, xp, oldValeur); + } + +} \ No newline at end of file diff --git a/module/item-signedraconique-sheet.js b/module/item-signedraconique-sheet.js index b597264d..703064be 100644 --- a/module/item-signedraconique-sheet.js +++ b/module/item-signedraconique-sheet.js @@ -1,5 +1,6 @@ +import { RdDItemSigneDraconique } from "./item-signedraconique.js"; import { Misc } from "./misc.js"; -import { TMRType } from "./tmr-utility.js"; +import { TMRType, TMRUtility } from "./tmr-utility.js"; /** * Item sheet pour signes draconiques @@ -48,16 +49,10 @@ export class RdDSigneDraconiqueItemSheet extends ItemSheet { editable: this.isEditable, cssClass: this.isEditable ? "editable" : "locked", }); - formData.tmrs = RdDSigneDraconiqueItemSheet.listTMRTypes(formData.data.typesTMR ?? []); + formData.tmrs = TMRUtility.listSelectedTMR(formData.data.typesTMR ?? []); return formData; } - static listTMRTypes(typesTMR) { - return Object.values(TMRType).map(value => Misc.upperFirst(value.name)) - .sort() - .map(name => { return { name: name, selected: typesTMR.includes(name) } }); - } - /* -------------------------------------------- */ /** @override */ activateListeners(html) { @@ -75,28 +70,12 @@ export class RdDSigneDraconiqueItemSheet extends ItemSheet { this.object.update({ 'data.typesTMR': selectedTMR }); } - async onValeurXpSort(qualite, valeur) { - let tplData = Misc.templateData(this.object); - if (valeur != tplData.valeur[qualite]) - { - await this.object.update({ [`data.valeur.${qualite}`]: valeur }); - - tplData = Misc.templateData(this.object); - switch (qualite) { - case "norm": - if (valeur > tplData.valeur.sign) await this.object.update({ 'data.valeur.sign': valeur }); - if (valeur > tplData.valeur.part) await this.object.update({ 'data.valeur.part': valeur }); - break; - case "sign": - if (valeur < tplData.valeur.norm) await this.object.update({ 'data.valeur.norm': valeur }); - if (valeur > tplData.valeur.part) await this.object.update({ 'data.valeur.part': valeur }); - break; - case "part": - if (valeur < tplData.valeur.norm) await this.object.update({ 'data.valeur.norm': valeur }); - if (valeur < tplData.valeur.sign) await this.object.update({ 'data.valeur.sign': valeur }); - break; - } - } + async onValeurXpSort(event) { + const codeReussite = event.currentTarget.attributes['data-typereussite']?.value ?? 0; + const xp = Number(event.currentTarget.value); + const oldValeur = Misc.templateData(this.object).valeur; + const newValeur = RdDItemSigneDraconique.calculValeursXpSort(codeReussite, xp, oldValeur); + await this.object.update({ 'data.valeur': newValeur }); } /* -------------------------------------------- */ diff --git a/module/item-signedraconique.js b/module/item-signedraconique.js index b2cad95c..e38e7b82 100644 --- a/module/item-signedraconique.js +++ b/module/item-signedraconique.js @@ -34,4 +34,27 @@ export class RdDItemSigneDraconique { return Misc.data(signe).data.valeur[code] ?? 0; } + static calculValeursXpSort(qualite, valeur, avant) { + switch (qualite) { + case "norm": + return { + norm: valeur, + sign: Math.max(valeur, avant.sign), + part: Math.max(valeur, avant.part) + } + case "sign": + return { + norm: Math.min(valeur, avant.norm), + sign: valeur, + part: Math.max(valeur, avant.part) + } + case "part": + return { + norm: Math.min(valeur, avant.norm), + sign: Math.min(valeur, avant.sign), + part: valeur + } + } + } + } \ No newline at end of file diff --git a/module/rdd-commands.js b/module/rdd-commands.js index f8b44405..16bb4e7d 100644 --- a/module/rdd-commands.js +++ b/module/rdd-commands.js @@ -1,5 +1,6 @@ /* -------------------------------------------- */ +import { DialogCreateSigneDraconiqueForActors } from "./dialog-create-signedraconique-actors.js"; import { RdDItemCompetence } from "./item-competence.js"; import { Misc } from "./misc.js"; import { RdDCarac } from "./rdd-carac.js"; @@ -82,6 +83,17 @@ export class RdDCommands { descr: `Affiche les heures de chance et de malchance selon l'heure de naissance donnée en argument. Exemples:
/astro Lyre` }); + + rddCommands.registerCommand({ + path: ["/signe", "+"], func: (content, msg, params) => rddCommands.creerSignesDraconiques(), + descr: "Crée un signe draconique et l'ajoute aux haut-rêvants choisis." + }); + + rddCommands.registerCommand({ + path: ["/signe", "-"], func: (content, msg, params) => rddCommands.supprimerSignesDraconiquesEphemeres(), + descr: "Supprime les signes draconiques éphémères" + }); + game.system.rdd.commands = rddCommands; } } @@ -312,5 +324,20 @@ export class RdDCommands { } } + async creerSignesDraconiques() { + DialogCreateSigneDraconiqueForActors.createSigneForActors(); + return true; + } + + async supprimerSignesDraconiquesEphemeres() { + game.actors.forEach(actor => { + const ephemeres = actor.filterItems(item => Misc.data(item).type = 'signedraconique' && Misc.data(item).data.ephemere) + .map(item => item.id); + if (ephemeres.length > 0) { + actor.deleteEmbeddedDocuments("Item", ephemeres); + } + }); + return true; + } } diff --git a/module/rdd-utility.js b/module/rdd-utility.js index a39c7135..ba46ca35 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -205,7 +205,8 @@ export class RdDUtility { 'systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-potionenchantee-chateaudormant.html', - 'systems/foundryvtt-reve-de-dragon/templates/chat-fabriquer-potion-base.html' + 'systems/foundryvtt-reve-de-dragon/templates/chat-fabriquer-potion-base.html', + 'systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.html' ]; Handlebars.registerHelper('upperFirst', str => Misc.upperFirst(str ?? 'Null')); diff --git a/module/tmr-utility.js b/module/tmr-utility.js index 566d45a7..6d418776 100644 --- a/module/tmr-utility.js +++ b/module/tmr-utility.js @@ -346,6 +346,12 @@ export class TMRUtility { return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label; } + static listSelectedTMR(typesTMR) { + return Object.values(TMRType).map(value => Misc.upperFirst(value.name)) + .sort() + .map(name => { return { name: name, selected: typesTMR.includes(name) } }); + } + static isCaseHumide(tmr) { return tmr.type == 'fleuve' || tmr.type == 'lac' || tmr.type == 'marais'; } diff --git a/templates/chat-signe-draconique-actor.html b/templates/chat-signe-draconique-actor.html new file mode 100644 index 00000000..f05b43fb --- /dev/null +++ b/templates/chat-signe-draconique-actor.html @@ -0,0 +1,7 @@ +

{{signe.name}} + {{alias}} perçoit {{signe.name}} +

+

Pour le lire ce signe draconique, rendez-vous dans les + Terres Médianes du Rêve et trouvez une case de résonnance. + {{#if signe.data.ephemere}}C'est un signe éphémère, qui ne restera présent que pour {{signe.data.duree}}{{/if}} +

diff --git a/templates/dialog-create-signedraconique-actors.html b/templates/dialog-create-signedraconique-actors.html new file mode 100644 index 00000000..9d4a6945 --- /dev/null +++ b/templates/dialog-create-signedraconique-actors.html @@ -0,0 +1,57 @@ +
+
+

Un signe draconique éphémère se manifeste: +
+

+
+
+ + +
+ + +
+ + +
+ +
+ +
+ + Sign. + + Part. + +
+
+ +
+ + + + + + + +
+
+ + +
+ +
\ No newline at end of file diff --git a/templates/item-livre-sheet.html b/templates/item-livre-sheet.html index 8230103c..23f6345c 100644 --- a/templates/item-livre-sheet.html +++ b/templates/item-livre-sheet.html @@ -29,15 +29,15 @@
- +
- +
- +
@@ -49,15 +49,15 @@
- +
- +
- +
diff --git a/templates/item-signedraconique-sheet.html b/templates/item-signedraconique-sheet.html index dbcf1050..e7bb228a 100644 --- a/templates/item-signedraconique-sheet.html +++ b/templates/item-signedraconique-sheet.html @@ -8,6 +8,24 @@ {{!-- Sheet Body --}}
+
+ + +
+
+ +
+ + Sign. + + Part. + +
+
@@ -18,24 +36,6 @@
{{/if}} -
- - -
-
- -
- - Sign. - - Part. - -
-