diff --git a/module/actor.js b/module/actor.js
index c6c67f35..fc90154b 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
}
@@ -826,15 +859,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 +1002,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 !
}
@@ -3077,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 = {
@@ -3134,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/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/item.js b/module/item.js
index 39346eee..9fbbb961 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){
@@ -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;
@@ -205,7 +207,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
}
diff --git a/module/misc.js b/module/misc.js
index e0a07c61..2faa6f8d 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,8 @@ export class Misc {
static templateData(it) {
return Misc.data(it)?.data ?? {}
}
+
+ 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-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);
});
/* -------------------------------------------- */
diff --git a/module/rdd-utility.js b/module/rdd-utility.js
index db6ef01c..bb5ed094 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;
@@ -529,25 +529,62 @@ 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 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) {
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.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]
+ 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];
+ 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 = {
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}}