From 44e212cd12b4a69c9983e208d46427874a22c685 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 14 Apr 2021 21:51:29 +0200 Subject: [PATCH 1/7] Fix drop conteneurs --- module/actor.js | 12 ++++++------ module/item.js | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/module/actor.js b/module/actor.js index c6c67f35..ce368bd6 100644 --- a/module/actor.js +++ b/module/actor.js @@ -826,15 +826,15 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - _isConteneurContenu(item, conteneurId) { - if (Misc.data(item)?.type == 'conteneur') { // Si c'est un conteneur, il faut vérifier qu'on ne le déplace pas vers un sous-conteneur lui appartenant + _isConteneurContenu(item, conteneur) { + if (item?.isConteneur()) { // Si c'est un conteneur, il faut vérifier qu'on ne le déplace pas vers un sous-conteneur lui appartenant for (let id of Misc.templateData(item).contenu) { let subObjet = this.getObjet(id); - if (subObjet?.id == conteneurId) { + if (subObjet?.id == conteneur.id) { return true; // Loop detected ! } - if (subObjet?.type == 'conteneur') { - return this._isConteneurContenu(subObjet, conteneurId); + if (subObjet?.isConteneur()) { + return this._isConteneurContenu(subObjet, conteneur); } } } @@ -969,7 +969,7 @@ export class RdDActor extends Actor { ui.notifications.warn(`Impossible de déplacer un objet (${item.name}) vers un ${destData.type} qui n'est pas un conteneur (${dest.name}) !`); return false; } - if (this._isConteneurContenu(item, conteneurId)) { + if (this._isConteneurContenu(item, dest)) { ui.notifications.warn(`Impossible de déplacer un conteneur parent (${item.name}) dans un de ses contenus ${destData.name} !`); return false; // Loop detected ! } diff --git a/module/item.js b/module/item.js index 39346eee..179088f2 100644 --- a/module/item.js +++ b/module/item.js @@ -104,9 +104,9 @@ export class RdDItem extends Item { async quantiteIncDec(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) { const itemData = Misc.data(this); - const quantite = itemData.data.quantite; - if (quantite != undefined) { - const reste = Math.max(quantite + nombre, 0); + const quantite = Number(itemData.data.quantite ??-1); + if (quantite >=0 ) { + const reste = Math.max(quantite + Number(nombre), 0); if (reste == 0) { if (options.supprimerSiZero){ From b37de0a420510d331a1038b51d0364055d0bb687 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 14 Apr 2021 22:28:49 +0200 Subject: [PATCH 2/7] Payer pour l'actor d'un token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comme ça le MJ peut acheter lui aussi --- module/rdd-utility.js | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/module/rdd-utility.js b/module/rdd-utility.js index db6ef01c..a2fb6c2c 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -204,9 +204,9 @@ export class RdDUtility { } /* -------------------------------------------- */ - static buildListOptions( min, max ) { + static buildListOptions(min, max) { let options = "" - for(let i=min; i<= max; i++) { + for (let i = min; i <= max; i++) { options += `` } return options; @@ -530,24 +530,38 @@ export class RdDUtility { // Gestion du bouton payer html.on("click", '.payer-button', event => { let sumdenier = event.currentTarget.attributes['data-somme-denier'].value; - let quantite = 1; - if (event.currentTarget.attributes['data-quantite']) { - quantite = event.currentTarget.attributes['data-quantite'].value; - } + let quantite = event.currentTarget.attributes['data-quantite']?.value ?? 1; let jsondata = event.currentTarget.attributes['data-jsondata'] let objData if (jsondata) { objData = JSON.parse(jsondata.value) } - if (game.user.character) { - game.user.character.payerDenier(sumdenier, objData, quantite); - } else { - let msgPayer = "Vous devez avoir un acteur relié pour effectuer le paiement"; - ChatMessage.create({ content: msgPayer, whisper: [game.user] }); + let actor = RdDUtility.getSelectedActor("Pour effectuer le paiement:"); + if (actor) { + actor.payerDenier(sumdenier, objData, quantite); } }); } + static getSelectedActor(msgPlayer = '') { + if (canvas.tokens.controlled.length == 1) { + let token = canvas.tokens.controlled[0]; + if (token.actor && token.data.actorLink) { + return token.actor; + } + msgPlayer += "
le token sélectionné doit être lié à un personnage"; + } + if (game.user.character) { + return game.user.character; + } + msgPlayer += "
vous pouvez sélectionner un seul token lié à un personnage"; + msgPlayer += "
vous devez être connecté comme joueur avec un personnage sélectionné"; + + ui.notifications.warn(msgPlayer); + ChatMessage.create({ content: msgPlayer, whisper: [game.user] }); + return undefined; + } + /* -------------------------------------------- */ static createMonnaie(name, valeur_deniers, img = "", enc = 0.01) { let piece = { From a282575422c78c20226ee86ce4ddad9ae91b784e Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 14 Apr 2021 22:29:20 +0200 Subject: [PATCH 3/7] On peut donner gratuitement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit en utilisant payer à un prix de 0 --- module/item.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/item.js b/module/item.js index 179088f2..35f205bc 100644 --- a/module/item.js +++ b/module/item.js @@ -205,7 +205,7 @@ export class RdDItem extends Item { if (chatData.hasPrice) { if (quantiteEnvoi > 0) chatData.postQuantity = Number(quantiteEnvoi); - if (prixTotal > 0) { + if (prixTotal >= 0) { chatData.postPrice = prixTotal; chatData.data.cout_deniers = Math.floor(prixTotal * 100); // Mise à jour cout en deniers } From 413893bc67bc4bb6714abc4090f6850de2c6ac0f Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 14 Apr 2021 22:40:12 +0200 Subject: [PATCH 4/7] Garder trace du vendeur --- module/item.js | 4 +++- templates/post-item.html | 12 ++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/module/item.js b/module/item.js index 35f205bc..9fbbb961 100644 --- a/module/item.js +++ b/module/item.js @@ -150,7 +150,9 @@ export class RdDItem extends Item { let chatData = duplicate(Misc.data(this)); const properties = this[`_${chatData.type}ChatData`](); chatData["properties"] = properties - + if (this.actor){ + chatData.actor = {id: this.actor.id }; + } //Check if the posted item should have availability/pay buttons chatData.hasPrice = "cout" in chatData.data; chatData.data.cout_deniers = 0; diff --git a/templates/post-item.html b/templates/post-item.html index a569f947..519b8725 100644 --- a/templates/post-item.html +++ b/templates/post-item.html @@ -15,21 +15,21 @@ Quantité: {{postQuantity}} {{/if}} {{#if postPrice}} - Prix: {{postPrice}} Sols
+ Prix: {{postPrice}} Sols {{/if}} - +
{{/if}} - {{#if finalPrice}} Prix Total: {{finalPrice}} Sols
- {{/if}}

{{#if hasPrice}} - Payer + Payer {{/if}} From c2f5229ca6951ddaf188d1ee6d0ba905aa7e2894 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Thu, 15 Apr 2021 00:13:50 +0200 Subject: [PATCH 5/7] =?UTF-8?q?Permettre=20de=20d=C3=A9l=C3=A9guer=20un=20?= =?UTF-8?q?appel=20au=20MJ?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit permettre de poster un message au MJ pour que du code soit exécuté par le MJ. Ceci permet par exemple à un joueur de payer un objet posté par un autre joueur, et que l'argent soit transféré à l'autre joueur --- module/actor.js | 33 +++++++++++++++++++++++++++++++++ module/misc.js | 7 +++++++ module/rdd-combat.js | 2 +- module/rdd-main.js | 9 +++++---- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/module/actor.js b/module/actor.js index ce368bd6..af6f9760 100644 --- a/module/actor.js +++ b/module/actor.js @@ -48,6 +48,39 @@ export class RdDActor extends Actor { Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId)); } + static onSocketMessage(sockmsg) { + switch (sockmsg.msg) { + case "msg_remote_actor_call": + return RdDActor.onRemoteActorCall(sockmsg.data); + } + } + + static remoteActorCall(actorId, method, ...args) { + game.socket.emit("system.foundryvtt-reve-de-dragon", { + msg: "msg_remote_actor_call", + data: { + gmId: Misc.connectedGM(), + toActorId: actorId, + method: method, + args: args + } + }); + } + + static onRemoteActorCall(data) { + if (game.user.id == data.gmId) { // Seul le GM connecté choisi effectue l'appel + const actor = game.actors.get(data?.toActorId); + if (!actor) { + console.info("RdDActor.onRemoteActorCall: Pas d'Actor disponible ", data); + } + else { + const args = data.args; + console.info(`RdDActor.onRemoteActorCall: pour l'Actor ${data.toActorId}, appel de RdDActor.${data.method}(`, ...args, ')'); + actor[data.method](...args); + } + } + } + static getParentActor(document) { return document?.parent instanceof Actor ? document.parent : undefined } diff --git a/module/misc.js b/module/misc.js index e0a07c61..1d71fab7 100644 --- a/module/misc.js +++ b/module/misc.js @@ -47,11 +47,13 @@ export class Misc { const parsed = parseInt(value); return isNaN(parsed) ? 0 : parsed; } + static keepDecimals(num, decimals) { if (decimals<=0 || decimals>6) return num; const decimal = Math.pow(10, parseInt(decimals)); return Math.round(num * decimal) / decimal; } + static getFractionHtml(diviseur) { if (!diviseur || diviseur <= 1) return undefined; switch (diviseur || 1) { @@ -111,4 +113,9 @@ export class Misc { static templateData(it) { return Misc.data(it)?.data ?? {} } + + static connectedGM() + { + return game.users.entities.find(u => u.isGM && u.active)?.id; + } } \ No newline at end of file diff --git a/module/rdd-combat.js b/module/rdd-combat.js index a8ae51e3..4b78d9c5 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -1211,7 +1211,7 @@ export class RdDCombat { attackerId: this.attackerId, defenderTokenId: defenderTokenId, attackerRoll: attackerRoll, - gmId: game.users.entities.find(u => u.isGM)?.id, + gmId: Misc.connectedGM(), } }); } diff --git a/module/rdd-main.js b/module/rdd-main.js index 822b9b4b..f76c177c 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -140,10 +140,11 @@ Hooks.once("init", async function () { }; /* -------------------------------------------- */ - game.socket.on("system.foundryvtt-reve-de-dragon", data => { - RdDUtility.onSocketMesssage(data); - RdDCombat.onSocketMessage(data); - ChatUtility.onSocketMessage(data); + game.socket.on("system.foundryvtt-reve-de-dragon", sockmsg => { + RdDUtility.onSocketMesssage(sockmsg); + RdDCombat.onSocketMessage(sockmsg); + ChatUtility.onSocketMessage(sockmsg); + RdDActor.onSocketMessage(sockmsg); }); /* -------------------------------------------- */ From 94bc70a2c9d2a7369bfda70501b5c0440ef6e59f Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Thu, 15 Apr 2021 00:25:40 +0200 Subject: [PATCH 6/7] Payer un autre personnage --- module/actor.js | 98 ++++++++++++++++++++++++++++--------------- module/rdd-utility.js | 9 +++- 2 files changed, 72 insertions(+), 35 deletions(-) diff --git a/module/actor.js b/module/actor.js index af6f9760..fc90154b 100644 --- a/module/actor.js +++ b/module/actor.js @@ -3110,54 +3110,68 @@ export class RdDActor extends Actor { return; } /* -------------------------------------------- */ - async optimizeArgent(sumDenier, monnaies) { + getFortune() { + let monnaies = Monnaie.filtrerMonnaies(this.data.items); + if (monnaies.length < 4) { + ui.notifications.error("Problème de monnaies manquantes, impossible de payer correctement!") + return 0; + } + return monnaies.map(m => Misc.templateData(m)) + .map(tpl => tpl.valeur_deniers * Number(tpl.quantite)) + .reduce(Misc.sum(), 0); + } + /* -------------------------------------------- */ + async optimizeArgent(fortuneTotale) { + let monnaies = Monnaie.filtrerMonnaies(this.data.items); let parValeur = Misc.classifyFirst(monnaies, it => Misc.templateData(it).valeur_deniers); - let fortune = { - 1000: Math.floor(sumDenier / 1000), // or - 100: Math.floor(sumDenier / 100) % 10, // argent - 10: Math.floor(sumDenier / 10) % 10, // bronze - 1: sumDenier % 10 // étain + let nouvelleFortune = { + 1000: Math.floor(fortuneTotale / 1000), // or + 100: Math.floor(fortuneTotale / 100) % 10, // argent + 10: Math.floor(fortuneTotale / 10) % 10, // bronze + 1: fortuneTotale % 10 // étain } let updates = [] - for (const [valeur, nombre] of Object.entries(fortune)) { + for (const [valeur, nombre] of Object.entries(nouvelleFortune)) { updates.push({ _id: parValeur[valeur]._id, 'data.quantite': nombre }); } await this.updateEmbeddedDocuments('Item', updates); } /* -------------------------------------------- */ - async payerDenier(sumDenier, dataObj = undefined, quantite = 1) { - let monnaies = Monnaie.filtrerMonnaies(this.data.items); - if (monnaies.length < 4) { - ui.notifications.warn("Problème de monnaies manquantes, impossible de payer correctement!") - return; - } - - sumDenier = Number(sumDenier); - let denierDisponible = 0; - - for (let pieceData of monnaies.map(m => Misc.data(m))) { - denierDisponible += pieceData.data.valeur_deniers * Number(pieceData.data.quantite); - } - console.log("DENIER", game.user.character, sumDenier, denierDisponible); - + async depenserDeniers(depense, dataObj = undefined, quantite = 1, toActorId) { + depense = Number(depense); + let fortune = this.getFortune(); + console.log("depenserDeniers", game.user.character, depense, fortune); let msg = ""; - let isPayed = false; - if (denierDisponible >= sumDenier) { - denierDisponible -= sumDenier; - this.optimizeArgent(denierDisponible, monnaies); - msg = `Vous avez payé ${sumDenier} Deniers, qui ont été soustraits de votre argent.`; - RdDAudio.PlayContextAudio("argent"); // Petit son - isPayed = true; + if (depense == 0) { if (dataObj) { - dataObj.payload.data.cout = sumDenier / 100; // Mise à jour du prix en sols , avec le prix acheté + dataObj.payload.data.cout = depense / 100; // Mise à jour du prix en sols , avec le prix acheté dataObj.payload.data.quantite = quantite; await this.createEmbeddedDocuments('Item', [dataObj.payload]); - msg += `
Et l'objet ${dataObj.payload.name} a été ajouté à votre inventaire.`; + msg += `
L'objet ${dataObj.payload.name} a été ajouté gratuitement à votre inventaire.`; + } + } + else { + if (fortune >= depense) { + fortune -= depense; + const toActor = game.actors.get(toActorId) + if (toActor) { + toActor.ajouterDeniers(depense, this.id); + } + await this.optimizeArgent(fortune); + msg = `Vous avez payé ${depense} Deniers${toActor ? " à " + toActor.name : ''}, qui ont été soustraits de votre argent.`; + RdDAudio.PlayContextAudio("argent"); // Petit son + + if (dataObj) { + dataObj.payload.data.cout = depense / 100; // Mise à jour du prix en sols , avec le prix acheté + dataObj.payload.data.quantite = quantite; + await this.createEmbeddedDocuments('Item', [dataObj.payload]); + msg += `
Et l'objet ${dataObj.payload.name} a été ajouté à votre inventaire.`; + } + } else { + msg = "Vous n'avez pas assez d'argent pour payer cette somme !"; } - } else { - msg = "Vous n'avez pas assez d'argent pour payer cette somme !"; } let message = { @@ -3167,6 +3181,24 @@ export class RdDActor extends Actor { ChatMessage.create(message); } + async ajouterDeniers(gain, fromActorId = undefined) { + if (fromActorId && !game.user.isGM) { + RdDActor.remoteActorCall(this.id, 'ajouterDeniers', gain, fromActorId); + } + else { + const fromActor = game.actors.get(fromActorId) + let fortune = this.getFortune(); + fortune += Number(gain); + await this.optimizeArgent(fortune); + + RdDAudio.PlayContextAudio("argent"); // Petit son + ChatMessage.create({ + whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), + content: `Vous avez reçu ${gain} Deniers ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés de votre argent.` + }); + } + } + /* -------------------------------------------- */ async monnaieIncDec(id, value) { let monnaie = this.getMonnaie(id); diff --git a/module/rdd-utility.js b/module/rdd-utility.js index a2fb6c2c..d1dd170a 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -529,8 +529,9 @@ export class RdDUtility { }); // Gestion du bouton payer html.on("click", '.payer-button', event => { - let sumdenier = event.currentTarget.attributes['data-somme-denier'].value; + let sumdenier = event.currentTarget.attributes['data-somme-denier']?.value ?? 0; let quantite = event.currentTarget.attributes['data-quantite']?.value ?? 1; + let fromActorId = event.currentTarget.attributes['data-actor-id']?.value; let jsondata = event.currentTarget.attributes['data-jsondata'] let objData if (jsondata) { @@ -538,7 +539,11 @@ export class RdDUtility { } let actor = RdDUtility.getSelectedActor("Pour effectuer le paiement:"); if (actor) { - actor.payerDenier(sumdenier, objData, quantite); + actor.depenserDeniers(sumdenier, objData, quantite, fromActorId); + // TODO: diminuer la quantité ou supprimer le message + // message: => document.querySelector("#chat-log > li:nth-child(61) > div > div > span > a") + // => ../../../..[@data-message-id] + } }); } From e0ce7d1e339678b3508844802982f29477c34009 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Thu, 15 Apr 2021 01:14:24 +0200 Subject: [PATCH 7/7] =?UTF-8?q?Suppression=20des=20messages=20pour=20les?= =?UTF-8?q?=20objets=20pay=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- module/chat-utility.js | 45 ++++++++++++++++++++++++++++-------------- module/misc.js | 5 ++--- module/rdd-utility.js | 20 ++++++++++++++++++- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/module/chat-utility.js b/module/chat-utility.js index 7e95b705..38cc2733 100644 --- a/module/chat-utility.js +++ b/module/chat-utility.js @@ -1,3 +1,4 @@ +import { Misc } from "./misc.js"; /** * Class providing helper methods to get the list of users, and @@ -7,31 +8,45 @@ export class ChatUtility { /* -------------------------------------------- */ static onSocketMessage(sockmsg) { switch (sockmsg.msg) { - case "msg_delete_chat_message": return ChatUtility.onRemoveMessages(sockmsg.part, sockmsg.gmId); + case "msg_delete_chat_message": return ChatUtility.onRemoveMessages(sockmsg.data); } } /* -------------------------------------------- */ - static onRemoveMessages(part, gmId) { - if (game.user.id == gmId) { - const toDelete = game.messages.filter(it => it.data.content.includes(part)); - toDelete.forEach(it => it.delete()); + static onRemoveMessages(data) { + if (game.user.isGM || game.user.id == data.gmId) { + if (data.part){ + const toDelete = game.messages.filter(it => it.data.content.includes(data.part)); + toDelete.forEach(it => it.delete()); + } + if (data.messageId){ + game.messages.get(data.messageId)?.delete(); + } } } - + /* -------------------------------------------- */ static removeChatMessageContaining(part) { - const gmId = game.user.isGM ? game.user.id : game.users.entities.find(u => u.isGM && u.active)?.id; + const removeMessageData = { + part: part, + gmId: Misc.connectedGM() + }; - if (!gmId || game.user.isGM) { - ChatUtility.onRemoveMessages(part, game.user.id); + if (game.user.isGM) { + ChatUtility.onRemoveMessages(removeMessageData); } else { - game.socket.emit("system.foundryvtt-reve-de-dragon", { - msg: "msg_delete_chat_message", data: { - part:part, - gmId: gmId, - }}); + game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_delete_chat_message", data: removeMessageData }); + } + } + + static removeChatMessageId(messageId) { + const removeMessageData = { messageId: messageId, gmId: Misc.connectedGM() }; + if (game.user.isGM) { + ChatUtility.onRemoveMessages(removeMessageData); + } + else { + game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_delete_chat_message", data: removeMessageData }); } } @@ -108,5 +123,5 @@ export class ChatUtility { ChatMessage.create(data); } } - + } diff --git a/module/misc.js b/module/misc.js index 1d71fab7..2faa6f8d 100644 --- a/module/misc.js +++ b/module/misc.js @@ -114,8 +114,7 @@ export class Misc { return Misc.data(it)?.data ?? {} } - static connectedGM() - { - return game.users.entities.find(u => u.isGM && u.active)?.id; + static connectedGM() { + return game.user.isGM ? game.user.id : game.users.entities.find(u => u.isGM && u.active)?.id; } } \ No newline at end of file diff --git a/module/rdd-utility.js b/module/rdd-utility.js index d1dd170a..bb5ed094 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -543,11 +543,29 @@ export class RdDUtility { // TODO: diminuer la quantité ou supprimer le message // message: => document.querySelector("#chat-log > li:nth-child(61) > div > div > span > a") // => ../../../..[@data-message-id] - + let chatMessageId = RdDUtility.findChatMessageId(event.currentTarget); + if (chatMessageId) { + ChatUtility.removeChatMessageId(chatMessageId); + } } }); } + static findChatMessageId(current) { + const isChatMessageWithId = it => it.classList.contains('chat-message') && it.attributes.getNamedItem('data-message-id'); + return RdDUtility.findNodeMatching(current, isChatMessageWithId)?.attributes.getNamedItem('data-message-id').value; + } + + static findNodeMatching(current, predicate) { + if (current) { + if (predicate(current)) { + return current; + } + return RdDUtility.findNodeMatching(current.parentElement, predicate); + } + return undefined; + } + static getSelectedActor(msgPlayer = '') { if (canvas.tokens.controlled.length == 1) { let token = canvas.tokens.controlled[0];