From c0b5bb3f356d7d7359ccbc79c67660f76106f1f7 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 29 Jan 2022 18:49:06 +0100 Subject: [PATCH 1/4] =?UTF-8?q?Fix=20jets=20encaissements=20faits=20par=20?= =?UTF-8?q?le=20d=C3=A9fenseur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit => Les dés sont ceux du défenseur => Le message d'encaissement est visible par le joueur --- module/actor.js | 32 ++++++++++++++++++-------------- module/misc.js | 8 ++++++++ module/rdd-combat.js | 13 ++++++------- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/module/actor.js b/module/actor.js index 0e076007..2c0a7ec7 100644 --- a/module/actor.js +++ b/module/actor.js @@ -62,26 +62,23 @@ export class RdDActor extends Actor { } } - static remoteActorCall(data) { - if (Misc.isUniqueConnectedGM()) { + static remoteActorCall(data, canExecuteLocally = () => Misc.isUniqueConnectedGM()) { + if (canExecuteLocally()) { RdDActor.onRemoteActorCall(data); + return false; } else { game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_remote_actor_call", data: data }); + return true; } } static onRemoteActorCall(data) { - if (Misc.isUniqueConnectedGM()) { // Seul le joueur choisi effectue l'appel - const actor = game.actors.get(data?.actorId); - if (!actor) { - console.info("RdDActor.onRemoteActorCall: Pas d'Actor disponible ", data); - } - else { - const args = data.args; - console.info(`RdDActor.onRemoteActorCall: pour l'Actor ${data.actorId}, appel de RdDActor.${data.method}(`, ...args, ')'); - actor[data.method](...args); - } + const actor = game.actors.get(data?.actorId); + if (Misc.isOwnerPlayerOrUniqueConnectedGM(actor)) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon + const args = data.args; + console.info(`RdDActor.onRemoteActorCall: pour l'Actor ${data.actorId}, appel de RdDActor.${data.method}(`, ...args, ')'); + actor[data.method](...args); } } @@ -3668,7 +3665,10 @@ export class RdDActor extends Actor { return; } if (fromActorId && !game.user.isGM) { - RdDActor.remoteActorCall({ userId: Misc.connectedGMOrUser(), actorId: this.id, method: 'ajouterDeniers', args: [gain, fromActorId] }); + RdDActor.remoteActorCall({ + userId: Misc.connectedGMOrUser(), + actorId: this.id, + method: 'ajouterDeniers', args: [gain, fromActorId] }); } else { const fromActor = game.actors.get(fromActorId) @@ -3700,7 +3700,11 @@ export class RdDActor extends Actor { return; } if (!Misc.isUniqueConnectedGM()) { - RdDActor.remoteActorCall({ actorId: achat.vendeurId ?? achat.acheteurId, method: 'achatVente', args: [achat] }); + RdDActor.remoteActorCall({ + actorId: achat.vendeurId ?? achat.acheteurId, + method: 'achatVente', + args: [achat] }, + ); return; } diff --git a/module/misc.js b/module/misc.js index 3f8fa2a9..59fc080c 100644 --- a/module/misc.js +++ b/module/misc.js @@ -147,6 +147,14 @@ export class Misc { } + static isOwnerPlayer(actor, user=undefined) { + return actor.testUserPermission(user ?? game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER) + } + + static isOwnerPlayerOrUniqueConnectedGM(actor, user =undefined){ + return Misc.isOwnerPlayer(actor, user) ?? Misc.isUniqueConnectedGM(); + } + /** * @returns true pour un seul utilisateur: le premier GM connecté par ordre d'id */ diff --git a/module/rdd-combat.js b/module/rdd-combat.js index 0c354d1a..b350c398 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -544,16 +544,15 @@ export class RdDCombat { /* -------------------------------------------- */ static onMsgEncaisser(data) { - if (Misc.isUniqueConnectedGM()) { + let defender = canvas.tokens.get(data.defenderTokenId).actor; + if (Misc.isOwnerPlayerOrUniqueConnectedGM()) { let attackerRoll = RdDCombat._getAttaque(data.attackerId); // Retrieve the rolldata from the store let attacker = data.attackerId ? game.actors.get(data.attackerId) : null; - let defender = canvas.tokens.get(data.defenderTokenId).actor; defender.encaisserDommages(attackerRoll, attacker); RdDCombat._deleteDefense(attackerRoll.passeArme); RdDCombat._deleteAttaque(data.attackerId); } - } /* -------------------------------------------- */ @@ -917,11 +916,11 @@ export class RdDCombat { dmg: attackerRoll.dmg, }; - if (!Misc.isUniqueConnectedGM()) { - this._socketSendMessageDefense(paramChatDefense, defenderRoll); + if (Misc.isUniqueConnectedGM()) { + await this._chatMessageDefense(paramChatDefense); } else { - await this._chatMessageDefense(paramChatDefense); + this._socketSendMessageDefense(paramChatDefense, defenderRoll); } } @@ -1295,7 +1294,7 @@ export class RdDCombat { this._onEchecTotal(defenderRoll); } - if (Misc.isUniqueConnectedGM()) { + if (Misc.isOwnerPlayerOrUniqueConnectedGM(this.defender)) { attackerRoll.attackerId = this.attackerId; attackerRoll.defenderTokenId = defenderTokenId; From 3ae3003be3bec75aa806215f1838238aeabdae85 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 29 Jan 2022 18:50:37 +0100 Subject: [PATCH 2/4] Ajout async sur displayRollData MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Préparation pour récupérer le message affiché et lui ajouter des flags --- module/actor.js | 26 +++++++++++++------------- module/chat-utility.js | 10 +++++----- module/rdd-possession.js | 14 +++++++------- module/rdd-resolution-table.js | 2 +- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/module/actor.js b/module/actor.js index 2c0a7ec7..d7f361df 100644 --- a/module/actor.js +++ b/module/actor.js @@ -2458,7 +2458,7 @@ export class RdDActor extends Actor { this.currentTMR.close(); // Close TMR ! } // Final chat message - RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-sort.html'); + await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-sort.html'); if (reveActuel == 0) { // 0 points de reve ChatMessage.create({ content: this.name + " est réduit à 0 Points de Rêve, et tombe endormi !" }); @@ -2488,7 +2488,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async _onRollCaracResult(rollData) { // Final chat message - RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-general.html'); + await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-general.html'); } async rollCaracCompetence(caracName, compName, diff, options = { title: "", apprecier: false }) { @@ -2516,7 +2516,7 @@ export class RdDActor extends Actor { RollDataAjustements.calcul(rollData, this); await RdDResolutionTable.rollData(rollData); this._appliquerExperienceRollData(rollData); - RdDResolutionTable.displayRollData(rollData, this) + await RdDResolutionTable.displayRollData(rollData, this) return rollData.rolled; } @@ -2562,7 +2562,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async _competenceResult(rollData) { - RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-competence.html') + await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-competence.html') } /* -------------------------------------------- */ @@ -2641,7 +2641,7 @@ export class RdDActor extends Actor { this.updateEmbeddedDocuments('Item', [rollData.tache]); this.santeIncDec("fatigue", rollData.tache.data.fatigue); - RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-tache.html'); + await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-tache.html'); } /* -------------------------------------------- */ @@ -2688,7 +2688,7 @@ export class RdDActor extends Actor { const baseQualite = (artData.rolled.isSuccess ? artData.oeuvre.data.niveau : artData.competence.data.niveau); artData.qualiteFinale = Math.min(baseQualite, artData.oeuvre.data.niveau) + artData.rolled.ptQualite; - RdDResolutionTable.displayRollData(artData, this.name, `chat-resultat-${artData.art}.html`); + await RdDResolutionTable.displayRollData(artData, this.name, `chat-resultat-${artData.art}.html`); } /* -------------------------------------------- */ @@ -2766,7 +2766,7 @@ export class RdDActor extends Actor { ui.notifications.info(`${platCuisine.data.quantite} rations de ${platCuisine.name} ont été ajoutés à votre équipement`); } artData.platCuisine = platCuisine; - RdDResolutionTable.displayRollData(artData, this.name, `chat-resultat-${artData.art}.html`); + await RdDResolutionTable.displayRollData(artData, this.name, `chat-resultat-${artData.art}.html`); } /* -------------------------------------------- */ @@ -2834,7 +2834,7 @@ export class RdDActor extends Actor { await this.createEmbeddedDocuments("Item", [signeData]); } - RdDResolutionTable.displayRollData(meditationData, this.name, 'chat-resultat-meditation.html'); + await RdDResolutionTable.displayRollData(meditationData, this.name, 'chat-resultat-meditation.html'); } /* -------------------------------------------- */ @@ -2914,7 +2914,7 @@ export class RdDActor extends Actor { await this.updateExperienceLog("XP Sort", rollData.xpSort, "Signe draconique en " + rollData.competence.name); } await this.deleteEmbeddedDocuments("Item", [rollData.signe._id]); - RdDResolutionTable.displayRollData(rollData, this.name, 'chat-resultat-lecture-signedraconique.html'); + await RdDResolutionTable.displayRollData(rollData, this.name, 'chat-resultat-lecture-signedraconique.html'); this.currentTMR.close(); } @@ -3339,7 +3339,7 @@ export class RdDActor extends Actor { show: defenderRoll?.show ?? {} }); - ChatUtility.createChatWithRollMode(this.name, { + await ChatUtility.createChatWithRollMode(this.name, { roll: encaissement.roll, content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html', encaissement) }); @@ -3821,7 +3821,7 @@ export class RdDActor extends Actor { callbacks: [ this.createCallbackExperience(), this.createCallbackAppelAuMoral(), - { action: r => this._alchimieResult(r, false) } + { action: async r => await this._alchimieResult(r, false) } ] } ); @@ -3834,8 +3834,8 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - _alchimieResult(rollData) { - RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-alchimie.html'); + async _alchimieResult(rollData) { + await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-alchimie.html'); } /* -------------------------------------------- */ diff --git a/module/chat-utility.js b/module/chat-utility.js index 65e0c557..6dd97b77 100644 --- a/module/chat-utility.js +++ b/module/chat-utility.js @@ -66,7 +66,7 @@ export class ChatUtility { /* -------------------------------------------- */ static removeMessages(data) { - if (Misc.isUniqueConnectedGM()){ + if (Misc.isUniqueConnectedGM()) { ChatUtility.onRemoveMessages(data); } else { @@ -86,12 +86,12 @@ export class ChatUtility { } /* -------------------------------------------- */ - static createChatWithRollMode(name, chatOptions) { - ChatUtility.createChatMessage(name, game.settings.get("core", "rollMode"), chatOptions); + static async createChatWithRollMode(name, chatOptions) { + return await ChatUtility.createChatMessage(name, game.settings.get("core", "rollMode"), chatOptions); } /* -------------------------------------------- */ - static createChatMessage(name, rollMode, chatOptions) { + static async createChatMessage(name, rollMode, chatOptions) { switch (rollMode) { case "blindroll": // GM only if (!game.user.isGM) { @@ -109,7 +109,7 @@ export class ChatUtility { break; } chatOptions.alias = chatOptions.alias || name; - ChatMessage.create(chatOptions); + return await ChatMessage.create(chatOptions); } /* -------------------------------------------- */ diff --git a/module/rdd-possession.js b/module/rdd-possession.js index 4d3b7b2c..4b9e0f36 100644 --- a/module/rdd-possession.js +++ b/module/rdd-possession.js @@ -50,13 +50,13 @@ export class RdDPossession { } /* -------------------------------------------- */ - static resultConjuration( rollData) { + static async resultConjuration( rollData) { console.log("RollData!!!", rollData); if ( !rollData.rolled.isSuccess ) { rollData.possession.data.compteur++; } this.updateEtatPossession(rollData.possession); - RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-possession.html'); + await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-possession.html'); } /* -------------------------------------------- */ @@ -86,7 +86,7 @@ export class RdDPossession { name: 'conjurer', label: 'Conjurer une Possession', callbacks: [ - { action: async r => this.resultConjuration(r) } + { action: async r => await this.resultConjuration(r) } ] } ); @@ -94,11 +94,11 @@ export class RdDPossession { } /* -------------------------------------------- */ - static _onRollPossession( rollData, isSuccess ) { + static async _onRollPossession( rollData, isSuccess ) { let possession = rollData.possession; possession.isSuccess = isSuccess; this.updateEtatPossession( possession); - RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-possession.html'); + await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-possession.html'); } /* -------------------------------------------- */ @@ -141,8 +141,8 @@ export class RdDPossession { name: 'jet-possession', label: 'Possession: ', callbacks: [ - { condition: r => (r.rolled.isSuccess), action: r => this._onRollPossession(r, true) }, - { condition: r => (r.rolled.isEchec), action: r => this._onRollPossession(r, false) }, + { condition: r => (r.rolled.isSuccess), action: async r => await this._onRollPossession(r, true) }, + { condition: r => (r.rolled.isEchec), action: async r => await this._onRollPossession(r, false) }, ] }); dialog.render(true); diff --git a/module/rdd-resolution-table.js b/module/rdd-resolution-table.js index 52d0bd6a..6db89650 100644 --- a/module/rdd-resolution-table.js +++ b/module/rdd-resolution-table.js @@ -64,7 +64,7 @@ export class RdDResolutionTable { /* -------------------------------------------- */ static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.html') { - ChatUtility.createChatWithRollMode(actor?.userName ?? game.user.name, { + return await ChatUtility.createChatWithRollMode(actor?.userName ?? game.user.name, { content: await RdDResolutionTable.buildRollDataHtml(rollData, actor, template) }); } From 3abaf4e944b7974b2fad598b0637dea0ec54d4e3 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 29 Jan 2022 22:49:34 +0100 Subject: [PATCH 3/4] Extract constants for SYSTEM / SOCKET --- module/actor.js | 24 ++++++++++++------------ module/chat-utility.js | 7 ++++--- module/constants.js | 3 ++- module/rdd-astrologie-joueur.js | 3 ++- module/rdd-calendrier.js | 12 ++++++------ module/rdd-combat.js | 9 +++++---- module/rdd-compendium-organiser.js | 3 ++- module/rdd-main.js | 4 ++-- module/rdd-tmr-dialog.js | 3 ++- 9 files changed, 37 insertions(+), 31 deletions(-) diff --git a/module/actor.js b/module/actor.js index d7f361df..717152c0 100644 --- a/module/actor.js +++ b/module/actor.js @@ -33,7 +33,7 @@ import { RollDataAjustements } from "./rolldata-ajustements.js"; import { DialogItemAchat } from "./dialog-item-achat.js"; import { RdDItem } from "./item.js"; import { RdDPossession } from "./rdd-possession.js"; -import { SYSTEM_RDD } from "./constants.js"; +import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; /* -------------------------------------------- */ /** @@ -68,7 +68,7 @@ export class RdDActor extends Actor { return false; } else { - game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_remote_actor_call", data: data }); + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_remote_actor_call", data: data }); return true; } } @@ -494,11 +494,11 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async _recupereChance() { // On ne récupère un point de chance que si aucun appel à la chance dans la journée - if (this.getChanceActuel() < this.getChance() && !this.getFlag('foundryvtt-reve-de-dragon', 'utilisationChance')) { + if (this.getChanceActuel() < this.getChance() && !this.getFlag(SYSTEM_RDD, 'utilisationChance')) { await this.chanceActuelleIncDec(1); } // Nouveau jour, suppression du flag - await this.unsetFlag('foundryvtt-reve-de-dragon', 'utilisationChance'); + await this.unsetFlag(SYSTEM_RDD, 'utilisationChance'); } async _jetDeMoralChateauDormant(message) { @@ -1469,7 +1469,7 @@ export class RdDActor extends Actor { async cacheTMRetMessage() { await this.reinsertionAleatoire("Action MJ"); await this.cacheTMR(); - game.socket.emit("system.foundryvtt-reve-de-dragon", { + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_tmr_move", data: { actorId: this.data._id, tmrPos: this.data.data.reve.tmrpos @@ -1480,7 +1480,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async afficheTMRetMessage() { await this.montreTMR(); - game.socket.emit("system.foundryvtt-reve-de-dragon", { + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_tmr_move", data: { actorId: this.data._id, tmrPos: this.data.data.reve.tmrpos @@ -2940,7 +2940,7 @@ export class RdDActor extends Actor { async _appelChanceResult(rollData, onSuccess = () => { }, onEchec = () => { }) { await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-appelchance.html') if (rollData.rolled.isSuccess) { - await this.setFlag('foundryvtt-reve-de-dragon', 'utilisationChance', true); + await this.setFlag(SYSTEM_RDD, 'utilisationChance', true); await this.chanceActuelleIncDec(-1); onSuccess(); } @@ -3493,21 +3493,21 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async resetItemUse() { - await this.unsetFlag('foundryvtt-reve-de-dragon', 'itemUse'); - await this.setFlag('foundryvtt-reve-de-dragon', 'itemUse', {}); + await this.unsetFlag(SYSTEM_RDD, 'itemUse'); + await this.setFlag(SYSTEM_RDD, 'itemUse', {}); } /* -------------------------------------------- */ async incDecItemUse(itemId, inc = 1) { - let itemUse = duplicate(this.getFlag('foundryvtt-reve-de-dragon', 'itemUse') ?? {}); + let itemUse = duplicate(this.getFlag(SYSTEM_RDD, 'itemUse') ?? {}); itemUse[itemId] = (itemUse[itemId] ?? 0) + inc; - await this.setFlag('foundryvtt-reve-de-dragon', 'itemUse', itemUse); + await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse); console.log("ITEM USE INC", inc, itemUse); } /* -------------------------------------------- */ getItemUse(itemId) { - let itemUse = this.getFlag('foundryvtt-reve-de-dragon', 'itemUse') ?? {}; + let itemUse = this.getFlag(SYSTEM_RDD, 'itemUse') ?? {}; console.log("ITEM USE GET", itemUse); return itemUse[itemId] ?? 0; } diff --git a/module/chat-utility.js b/module/chat-utility.js index 6dd97b77..ba8fdf4c 100644 --- a/module/chat-utility.js +++ b/module/chat-utility.js @@ -1,4 +1,5 @@ import { Misc } from "./misc.js"; +import { SYSTEM_SOCKET_ID } from "./constants.js"; /** * Class providing helper methods to get the list of users, and @@ -23,7 +24,7 @@ export class ChatUtility { ChatUtility.onNotifyUser(data); } else { - game.socket.emit("system.foundryvtt-reve-de-dragon", { + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_user_ui_notifications", data: data }); } @@ -70,7 +71,7 @@ export class ChatUtility { ChatUtility.onRemoveMessages(data); } else { - game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_delete_chat_message", data: data }); + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_delete_chat_message", data: data }); } } @@ -147,7 +148,7 @@ export class ChatUtility { chatGM.whisper = ChatUtility.getUsers(user => user.isGM); chatGM.content = "Message aveugle de " + game.user.name + "
" + chatOptions.content; console.log("blindMessageToGM", chatGM); - game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_gm_chat_message", data: chatGM }); + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_gm_chat_message", data: chatGM }); } /* -------------------------------------------- */ diff --git a/module/constants.js b/module/constants.js index be1d1c86..865a0559 100644 --- a/module/constants.js +++ b/module/constants.js @@ -1,4 +1,5 @@ -export const SYSTEM_RDD = "foundryvtt-reve-de-dragon"; +export const SYSTEM_RDD = 'foundryvtt-reve-de-dragon'; +export const SYSTEM_SOCKET_ID = 'system.foundryvtt-reve-de-dragon'; export const HIDE_DICE = 'hide'; export const SHOW_DICE = 'show'; diff --git a/module/rdd-astrologie-joueur.js b/module/rdd-astrologie-joueur.js index bf0c3692..7497a97a 100644 --- a/module/rdd-astrologie-joueur.js +++ b/module/rdd-astrologie-joueur.js @@ -1,5 +1,6 @@ import { RdDItemCompetence } from "./item-competence.js"; import { Misc } from "./misc.js"; +import { SYSTEM_SOCKET_ID } from "./constants.js"; /** @@ -74,7 +75,7 @@ export class RdDAstrologieJoueur extends Dialog { if (Misc.isUniqueConnectedGM()) { game.system.rdd.calendrier.requestNombreAstral(data); } else { - game.socket.emit("system.foundryvtt-reve-de-dragon", { + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_request_nombre_astral", data: data }); diff --git a/module/rdd-calendrier.js b/module/rdd-calendrier.js index 7cc351c5..73a97003 100644 --- a/module/rdd-calendrier.js +++ b/module/rdd-calendrier.js @@ -7,7 +7,7 @@ import { RdDUtility } from "./rdd-utility.js"; import { Grammar } from "./grammar.js"; import { RdDDice } from "./rdd-dice.js"; import { Misc } from "./misc.js"; -import { HIDE_DICE, SHOW_DICE, SYSTEM_RDD } from "./constants.js"; +import { HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; /* -------------------------------------------- */ const dossierIconesHeures = 'systems/foundryvtt-reve-de-dragon/icons/heures/' @@ -172,7 +172,7 @@ export class RdDCalendrier extends Application { this.listeNombreAstral = []; game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.listeNombreAstral); - game.socket.emit("system.foundryvtt-reve-de-dragon", { + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_reset_nombre_astral", data: {} }); @@ -254,8 +254,8 @@ export class RdDCalendrier extends Application { this.checkMaladie("jour"); } game.settings.set(SYSTEM_RDD, "calendrier", duplicate(this.calendrier)); - // Notification aux joueurs - game.socket.emit("system.foundryvtt-reve-de-dragon", { + // Notification aux joueurs // TODO: replace with Hook on game settings update + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_sync_time", data: duplicate(this.calendrier) }); @@ -343,7 +343,7 @@ export class RdDCalendrier extends Application { if (Misc.getActiveUser(request.userId)?.isGM) { RdDUtility.responseNombreAstral(request); } else { - game.socket.emit("system.foundryvtt-reve-de-dragon", { + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_response_nombre_astral", data: request }); @@ -474,7 +474,7 @@ export class RdDCalendrier extends Application { await this.rebuildListeNombreAstral(); - game.socket.emit("system.foundryvtt-reve-de-dragon", { + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_sync_time", data: duplicate(this.calendrier) }); diff --git a/module/rdd-combat.js b/module/rdd-combat.js index b350c398..d7a38e3f 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -1,5 +1,5 @@ import { ChatUtility } from "./chat-utility.js"; -import { HIDE_DICE, SYSTEM_RDD } from "./constants.js"; +import { HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; import { RdDItemArme } from "./item-arme.js"; import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; @@ -473,7 +473,8 @@ export class RdDCombat { /* -------------------------------------------- */ static messagePasseArme(data) { - game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_combat_passearme", data: data }); + // TODO: store required info for combat in the chat message presenting choices? + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_combat_passearme", data: data }); RdDCombat.onMsgPasseArme(data); } @@ -938,7 +939,7 @@ export class RdDCombat { /* -------------------------------------------- */ _socketSendMessageDefense(paramChatDefense, defenderRoll) { // envoyer le message au destinataire - game.socket.emit("system.foundryvtt-reve-de-dragon", { + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_defense", data: { attackerId: this.attacker?.data._id, defenderId: this.defender?.data._id, @@ -1302,7 +1303,7 @@ export class RdDCombat { this.defender.encaisserDommages(attackerRoll, this.attacker, defenderRoll); } else { // envoi à un GM: les joueurs n'ont pas le droit de modifier les personnages qu'ils ne possèdent pas - game.socket.emit("system.foundryvtt-reve-de-dragon", { + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_encaisser", data: { attackerId: this.attackerId, diff --git a/module/rdd-compendium-organiser.js b/module/rdd-compendium-organiser.js index 91611194..7f4a4665 100644 --- a/module/rdd-compendium-organiser.js +++ b/module/rdd-compendium-organiser.js @@ -1,3 +1,4 @@ +import { SYSTEM_RDD } from "./constants.js"; import { Misc } from "./misc.js"; export class RddCompendiumOrganiser { @@ -8,7 +9,7 @@ export class RddCompendiumOrganiser { static async onRenderCompendium(compendium, html, data) { console.log('onRenderCompendium', compendium, html, data); const pack = compendium.collection - if (pack.metadata.system === 'foundryvtt-reve-de-dragon') { + if (pack.metadata.system === SYSTEM_RDD) { html.find('.directory-item').each((i, element) => { RddCompendiumOrganiser.setEntityTypeName(pack, element); }); diff --git a/module/rdd-main.js b/module/rdd-main.js index 1c7321c9..90852f7d 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -8,7 +8,7 @@ /* -------------------------------------------- */ // Import Modules -import { SYSTEM_RDD } from "./constants.js"; +import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; import { RdDActor } from "./actor.js"; import { RdDItemSheet } from "./item-sheet.js"; import { RdDActorSheet } from "./actor-sheet.js"; @@ -147,7 +147,7 @@ Hooks.once("init", async function () { }; /* -------------------------------------------- */ - game.socket.on("system.foundryvtt-reve-de-dragon", sockmsg => { + game.socket.on(SYSTEM_SOCKET_ID, sockmsg => { console.log(">>>>> MSG RECV", sockmsg); RdDUtility.onSocketMessage(sockmsg); diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index ce522327..3d62ddac 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -1,3 +1,4 @@ +import { SYSTEM_SOCKET_ID } from "./constants.js"; import { RollDataAjustements } from "./rolldata-ajustements.js"; import { RdDUtility } from "./rdd-utility.js"; import { TMRUtility } from "./tmr-utility.js"; @@ -947,7 +948,7 @@ export class RdDTMRDialog extends Dialog { this.cumulFatigue += this.fatigueParCase; } this.updateValuesDisplay(); - game.socket.emit("system.foundryvtt-reve-de-dragon", { + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_tmr_move", data: { actorId: this.actor.data._id, tmrPos: Misc.data(this.actor).data.reve.tmrpos From c0442f607c71a78c809e8ee6f84e8729b9fb3e13 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 29 Jan 2022 23:33:31 +0100 Subject: [PATCH 4/4] Gestion des choix de combat par flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Utiliser des flags sur les ChatMessage de choix de combat permet: - de conserver les informations même après un refresh - de simplifier un peu (pas besoin de gérer un stockage custom) --- module/chat-utility.js | 20 +++++- module/rdd-combat.js | 141 +++++++---------------------------------- 2 files changed, 43 insertions(+), 118 deletions(-) diff --git a/module/chat-utility.js b/module/chat-utility.js index ba8fdf4c..976e1b0c 100644 --- a/module/chat-utility.js +++ b/module/chat-utility.js @@ -1,5 +1,7 @@ import { Misc } from "./misc.js"; -import { SYSTEM_SOCKET_ID } from "./constants.js"; +import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; + +export const MESSAGE_DATA = 'message-data'; /** * Class providing helper methods to get the list of users, and @@ -160,4 +162,20 @@ export class ChatUtility { } } + static async setMessageData(chatMessage, key, data) { + if (data) { + await chatMessage.setFlag(SYSTEM_RDD, key, JSON.stringify(data)); + } + } + + static getMessageData(chatMessage, key) { + const json = chatMessage.getFlag(SYSTEM_RDD, key); + return json ? JSON.parse(json) : undefined; + } + + static getChatMessage(event) { + const chatMessageId = $(event.currentTarget).closest('.chat-message').attr('data-message-id'); + return game.messages.get(chatMessageId); + } + } diff --git a/module/rdd-combat.js b/module/rdd-combat.js index d7a38e3f..e341ed42 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -371,19 +371,10 @@ export class RdDCombatManager extends Combat { export class RdDCombat { static init() { - this.initStorePasseArmes(); Hooks.on("updateCombat", (combat, change, options, userId) => { RdDCombat.onUpdateCombat(combat, change, options, userId) }); Hooks.on("preDeleteCombat", (combat, options, userId) => { RdDCombat.onPreDeleteCombat(combat, options, userId); }); } - /* -------------------------------------------- */ - static initStorePasseArmes() { - game.system.rdd.combatStore = { - attaques: {}, - defenses: {} - }; - } - /* -------------------------------------------- */ static onSocketMessage(sockmsg) { switch (sockmsg.msg) { @@ -391,8 +382,6 @@ export class RdDCombat { return RdDCombat.onMsgEncaisser(sockmsg.data); case "msg_defense": return RdDCombat.onMsgDefense(sockmsg.data); - case "msg_combat_passearme": - return RdDCombat.onMsgPasseArme(sockmsg.data); } } @@ -405,22 +394,11 @@ export class RdDCombat { /* -------------------------------------------- */ static onPreDeleteCombat(combat, options, userId) { - if (game.user.isGM) { + if (Misc.isUniqueConnectedGM()) { combat.cleanItemUse(); ChatUtility.removeChatMessageContaining(`
`) - /* - * TODO: support de plusieurs combats parallèles - * il faudrait avoir un id de combat en plus de celui de passe d'armes - */ - for (const key in game.system.rdd.combatStore.attaques) { - const attackerRoll = game.system.rdd.combatStore.attaques[key]; - ChatUtility.removeChatMessageContaining(`
`); - } - for (const key in game.system.rdd.combatStore.defenses) { - const defenderRoll = game.system.rdd.combatStore.defenses[key]; - ChatUtility.removeChatMessageContaining(`
`); - } - RdDCombat.initStorePasseArmes(); + game.messages.filter(m => ChatUtility.getMessageData(m, 'attacker-roll') != undefined && ChatUtility.getMessageData(m, 'defender-roll') != undefined) + .forEach(it => it.delete()); } } @@ -471,61 +449,6 @@ export class RdDCombat { return undefined; } - /* -------------------------------------------- */ - static messagePasseArme(data) { - // TODO: store required info for combat in the chat message presenting choices? - game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_combat_passearme", data: data }); - RdDCombat.onMsgPasseArme(data); - } - - /* -------------------------------------------- */ - static onMsgPasseArme(data) { - switch (data.actionPasseArme) { - case "store-attaque": - game.system.rdd.combatStore.attaques[data.id] = data.rollData; - break; - case "store-defense": - game.system.rdd.combatStore.defenses[data.id] = data.rollData; - break; - case "delete-attaque": - delete game.system.rdd.combatStore.attaques[data.id]; - break; - case "delete-defense": - delete game.system.rdd.combatStore.defenses[data.id]; - break; - } - } - - /* -------------------------------------------- */ - static _storeAttaque(attackerId, attackerRoll) { - RdDCombat.messagePasseArme({ actionPasseArme: "store-attaque", id: attackerId, rollData: attackerRoll }); - } - - /* -------------------------------------------- */ - static _getAttaque(attackerId) { - return game.system.rdd.combatStore.attaques[attackerId]; - } - - /* -------------------------------------------- */ - static _deleteAttaque(attackerId) { - RdDCombat.messagePasseArme({ actionPasseArme: "delete-attaque", id: attackerId }); - } - - /* -------------------------------------------- */ - static _storeDefense(passeArme, defenderRoll) { - RdDCombat.messagePasseArme({ actionPasseArme: "store-defense", id: passeArme, rollData: defenderRoll }); - } - - /* -------------------------------------------- */ - static _getDefense(passeArme) { - return game.system.rdd.combatStore.defenses[passeArme]; - } - - /* -------------------------------------------- */ - static _deleteDefense(passeArme) { - RdDCombat.messagePasseArme({ actionPasseArme: "delete-defense", id: passeArme }); - } - /* -------------------------------------------- */ static create(attacker, defender, defenderTokenId, target = undefined) { return new RdDCombat(attacker, defender, defenderTokenId, target) @@ -547,7 +470,7 @@ export class RdDCombat { static onMsgEncaisser(data) { let defender = canvas.tokens.get(data.defenderTokenId).actor; if (Misc.isOwnerPlayerOrUniqueConnectedGM()) { - let attackerRoll = RdDCombat._getAttaque(data.attackerId); // Retrieve the rolldata from the store + let attackerRoll = data.attackerRoll; let attacker = data.attackerId ? game.actors.get(data.attackerId) : null; defender.encaisserDommages(attackerRoll, attacker); @@ -563,10 +486,8 @@ export class RdDCombat { const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId); if (rddCombat) { const defenderRoll = msg.defenderRoll; - RdDCombat._storeAttaque(msg.attackerId, defenderRoll.attackerRoll); - RdDCombat._storeDefense(defenderRoll.passeArme, defenderRoll); rddCombat.removeChatMessageActionsPasseArme(defenderRoll.passeArme); - rddCombat._chatMessageDefense(msg.paramChatDefense); + rddCombat._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll); } } } @@ -621,12 +542,10 @@ export class RdDCombat { /* -------------------------------------------- */ async onEvent(button, event) { - const attackerRoll = RdDCombat._getAttaque(this.attackerId); - if (!attackerRoll) { - ui.notifications.warn("Action automatisée impossible, le jet de l'attaquant a été perdu (suite à un raffraichissement?)") - return; - } - const defenderRoll = game.system.rdd.combatStore.defenses[attackerRoll.passeArme]; + const chatMessage = ChatUtility.getChatMessage(event); + const defenderRoll = ChatUtility.getMessageData(chatMessage, 'defender-roll'); + const attackerRoll = defenderRoll?.attackerRoll ?? ChatUtility.getMessageData(chatMessage, 'attacker-roll') ; + console.log('RdDCombat', attackerRoll, defenderRoll); const defenderTokenId = event.currentTarget.attributes['data-defenderTokenId']?.value; const armeParadeId = event.currentTarget.attributes['data-armeid']?.value; @@ -637,7 +556,7 @@ export class RdDCombat { case '#particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value); case '#parer-button': return this.parade(attackerRoll, armeParadeId); case '#esquiver-button': return this.esquive(attackerRoll, compId, competence); - case '#encaisser-button': return this.encaisser(attackerRoll, defenderTokenId); + case '#encaisser-button': return this.encaisser(attackerRoll, defenderRoll, defenderTokenId); case '#echec-total-attaque': return this._onEchecTotal(attackerRoll); case '#appel-chance-attaque': return this.attacker.rollAppelChance( @@ -650,7 +569,7 @@ export class RdDCombat { () => this.attaqueSignificative(attackerRoll), () => { }); case '#appel-destinee-defense': return this.defender.appelDestinee( - () => this.defenseDestinee(attackerRoll), + () => this.defenseDestinee(defenderRoll), () => { }); } } @@ -680,8 +599,7 @@ export class RdDCombat { } /* -------------------------------------------- */ - defenseDestinee(attackerRoll) { - let defenderRoll = RdDCombat._getDefense(attackerRoll.passeArme); + defenseDestinee(defenderRoll) { if (defenderRoll) { ui.notifications.info('Défense significative grâce à la destinée') RdDResolutionTable.significativeRequise(defenderRoll.rolled); @@ -819,8 +737,7 @@ export class RdDCombat { /* -------------------------------------------- */ async _onAttaqueParticuliere(rollData) { - RdDCombat._storeAttaque(this.attackerId, rollData); - + const isMeleeDiffNegative = (rollData.competence.type == 'competencecreature' || rollData.selectedCarac.label == "Mêlée") && rollData.diffLibre < 0; // force toujours, sauf empoignade // finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum @@ -838,8 +755,8 @@ export class RdDCombat { else if (!isForce && !isFinesse && isRapide) { return await this.choixParticuliere(rollData, "rapidite"); } - - ChatMessage.create({ + + const choixParticuliere = await ChatMessage.create({ alias: this.attacker.name, whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name), content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html', { @@ -852,6 +769,7 @@ export class RdDCombat { passeArme: rollData.passeArme }) }); + ChatUtility.setMessageData(choixParticuliere, 'attacker-roll', rollData); } /* -------------------------------------------- */ @@ -860,10 +778,6 @@ export class RdDCombat { attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker.getBonusDegat(), this.defender.isEntiteCauchemar()); let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} } - // Save rollData for defender - RdDCombat._storeAttaque(this.attackerId, attackerRoll); - RdDCombat._storeDefense(defenderRoll.passeArme, defenderRoll); - attackerRoll.show = { cible: this.target ? this.defender.data.name : 'la cible', isRecul: (attackerRoll.particuliere == 'force' || attackerRoll.tactique == 'charge') @@ -918,7 +832,7 @@ export class RdDCombat { }; if (Misc.isUniqueConnectedGM()) { - await this._chatMessageDefense(paramChatDefense); + await this._chatMessageDefense(paramChatDefense, defenderRoll); } else { this._socketSendMessageDefense(paramChatDefense, defenderRoll); @@ -926,14 +840,16 @@ export class RdDCombat { } /* -------------------------------------------- */ - async _chatMessageDefense(paramDemandeDefense) { - ChatMessage.create({ + async _chatMessageDefense(paramDemandeDefense, defenderRoll) { + const choixDefense = await ChatMessage.create({ // message privé: du défenseur à lui même (et aux GMs) speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)), alias: this.attacker.name, whisper: ChatUtility.getWhisperRecipientsAndGMs(this.defender.name), content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.html', paramDemandeDefense), }); + // flag pour garder les jets d'attaque/defense + ChatUtility.setMessageData(choixDefense, 'defender-roll', defenderRoll); } /* -------------------------------------------- */ @@ -974,10 +890,7 @@ export class RdDCombat { /* -------------------------------------------- */ async _onAttaqueEchecTotal(attackerRoll) { - - RdDCombat._storeAttaque(this.attackerId, attackerRoll); - - ChatMessage.create({ + const choixEchecTotal = await ChatMessage.create({ whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name), content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', { attackerId: this.attackerId, @@ -986,6 +899,7 @@ export class RdDCombat { essais: attackerRoll.essais }) }); + ChatUtility.setMessageData(choixEchecTotal, 'attacker-roll', attackerRoll); } /* -------------------------------------------- */ @@ -1105,7 +1019,6 @@ export class RdDCombat { this.removeChatMessageActionsPasseArme(defenderRoll.passeArme); this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true }); - RdDCombat._storeDefense(defenderRoll.passeArme, defenderRoll); } /* -------------------------------------------- */ @@ -1177,7 +1090,6 @@ export class RdDCombat { this.removeChatMessageActionsPasseArme(defenderRoll.passeArme); this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true }) - RdDCombat._storeDefense(defenderRoll.passeArme, defenderRoll); } /* -------------------------------------------- */ @@ -1282,15 +1194,10 @@ export class RdDCombat { } /* -------------------------------------------- */ - async encaisser(attackerRoll, defenderTokenId) { + async encaisser(attackerRoll, defenderRoll, defenderTokenId) { defenderTokenId = defenderTokenId || this.defenderTokenId; console.log("RdDCombat.encaisser >>>", attackerRoll, defenderTokenId); - let defenderRoll = RdDCombat._getDefense(attackerRoll.passeArme); - if (!defenderRoll) { - ui.notifications.warn("Cette passe d'arme est déjà terminée!") - return; - } if (defenderRoll?.rolled && RdDCombat.isEchecTotal(defenderRoll)) { this._onEchecTotal(defenderRoll); }