From b4a725ff1232159c9367e482c0469dda9ece0a33 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 23 Oct 2024 23:42:38 +0200 Subject: [PATCH 01/20] Fix: Message uniquement MJ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit L'utilisation de firstConnectedGM renvoie le GM, pas true si un GM est connecté. --- changelog.md | 3 +++ module/actor.js | 8 ++++---- module/actor/base-actor.js | 4 ++-- module/chat-utility.js | 6 +++--- module/misc.js | 8 ++++---- module/rdd-combat.js | 10 +++++----- module/rdd-main.js | 2 +- module/sommeil/app-astrologie.js | 2 +- module/time/rdd-calendrier.js | 6 +++--- 9 files changed, 26 insertions(+), 23 deletions(-) diff --git a/changelog.md b/changelog.md index ad50c309..583aa09a 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,7 @@ # 12.0 +## 12.0.16 - Le secret d'Astrobazzarh +- Fix: les jets envoyés messages uniquement au MJ ne sont plus envoyés à tous les autres joueurs (et dupliqués) + ## 12.0.15 - Le messager d'Astrobazzarh - Correction des faces de dés personalisés dice-so-nice - Les messages de maladies ne sont plus publics diff --git a/module/actor.js b/module/actor.js index 73c21990..b8e6cd10 100644 --- a/module/actor.js +++ b/module/actor.js @@ -1548,7 +1548,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { - if (!Misc.firstConnectedGM()){ + if (!Misc.isFirstConnectedGM()){ return } hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM) @@ -3011,7 +3011,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async onCreateOwnedDraconique(item, options, id) { - if (Misc.isUniqueConnectedGM()) { + if (Misc.isFirstConnectedGM()) { let draconique = Draconique.all().find(it => it.match(item)); if (draconique) { await draconique.onActorCreateOwned(this, item) @@ -3023,7 +3023,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async onDeleteOwnedDraconique(item, options, id) { - if (Misc.isUniqueConnectedGM()) { + if (Misc.isFirstConnectedGM()) { let draconique = Draconique.all().find(it => it.match(item)); if (draconique) { await draconique.onActorDeleteOwned(this, item) @@ -3033,7 +3033,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async onDeleteOwnedCaseTmr(item, options, id) { - if (Misc.isUniqueConnectedGM()) { + if (Misc.isFirstConnectedGM()) { let draconique = Draconique.all().find(it => it.isCase(item)); if (draconique) { await draconique.onActorDeleteCaseTmr(this, item) diff --git a/module/actor/base-actor.js b/module/actor/base-actor.js index 57fbcb07..c92b8318 100644 --- a/module/actor/base-actor.js +++ b/module/actor/base-actor.js @@ -218,7 +218,7 @@ export class RdDBaseActor extends Actor { } async creerObjetParMJ(object) { - if (!Misc.isUniqueConnectedGM()) { + if (!Misc.isFirstConnectedGM()) { RdDBaseActor.remoteActorCall({ tokenId: this.token?.id, actorId: this.id, @@ -335,7 +335,7 @@ export class RdDBaseActor extends Actor { ui.notifications.info("Inutile de se vendre à soi-même"); return; } - if (!Misc.isUniqueConnectedGM()) { + if (!Misc.isFirstConnectedGM()) { RdDBaseActor.remoteActorCall({ actorId: achat.vendeurId ?? achat.acheteurId, method: 'achatVente', diff --git a/module/chat-utility.js b/module/chat-utility.js index 76792c86..5f515ce8 100644 --- a/module/chat-utility.js +++ b/module/chat-utility.js @@ -49,7 +49,7 @@ export class ChatUtility { /* -------------------------------------------- */ static onRemoveMessages(socketData) { - if (Misc.isUniqueConnectedGM()) { + if (Misc.isFirstConnectedGM()) { if (socketData.part) { const toDelete = game.messages.filter(it => it.content.includes(socketData.part)); toDelete.forEach(it => it.delete()); @@ -63,7 +63,7 @@ export class ChatUtility { /* -------------------------------------------- */ static removeMessages(socketData) { - if (Misc.isUniqueConnectedGM()) { + if (Misc.isFirstConnectedGM()) { ChatUtility.onRemoveMessages(socketData); } else { @@ -161,7 +161,7 @@ export class ChatUtility { /* -------------------------------------------- */ static handleGMChatMessage(socketData) { console.log("blindMessageToGM", socketData); - if (Misc.firstConnectedGM()) { + if (Misc.isFirstConnectedGM()) { ChatMessage.create({ user: game.user.id, whisper: ChatUtility.getGMs(), diff --git a/module/misc.js b/module/misc.js index c22fe21e..a3f5f43d 100644 --- a/module/misc.js +++ b/module/misc.js @@ -195,7 +195,7 @@ export class Misc { return document } } - else if (Misc.isUniqueConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) { + else if (Misc.isFirstConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) { return document } return undefined @@ -206,14 +206,14 @@ export class Misc { } static isOwnerPlayerOrUniqueConnectedGM(actor) { - return Misc.isOwnerPlayer(actor) ?? Misc.isUniqueConnectedGM(); + return Misc.isOwnerPlayer(actor) ?? Misc.isFirstConnectedGM(); } /** * @returns true pour un seul utilisateur: le premier GM connecté par ordre d'id */ - static isUniqueConnectedGM() { - return game.user.id == Misc.firstConnectedGMId(); + static isFirstConnectedGM() { + return game.user == Misc.firstConnectedGM(); } static firstConnectedGMId() { diff --git a/module/rdd-combat.js b/module/rdd-combat.js index 68947438..f31f3554 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -53,7 +53,7 @@ export class RdDCombatManager extends Combat { /* -------------------------------------------- */ async onPreDeleteCombat() { - if (Misc.isUniqueConnectedGM()) { + if (Misc.isFirstConnectedGM()) { await this.finDeRound({ terminer: true }) ChatUtility.removeChatMessageContaining(`
`) game.messages.filter(m => ChatUtility.getMessageData(m, 'attacker-roll') != undefined && ChatUtility.getMessageData(m, 'defender-roll') != undefined) @@ -291,7 +291,7 @@ export class RdDCombatManager extends Combat { /* -------------------------------------------- */ static processPremierRoundInit() { // Check if we have the whole init ! - if (Misc.isUniqueConnectedGM() && game.combat.current.round == 1) { + if (Misc.isFirstConnectedGM() && game.combat.current.round == 1) { let initMissing = game.combat.combatants.find(it => !it.initiative); if (!initMissing) { // Premier round ! for (let combatant of game.combat.combatants) { @@ -454,7 +454,7 @@ export class RdDCombat { /* -------------------------------------------- */ static combatNouveauTour(combat) { - if (Misc.isUniqueConnectedGM()) { + if (Misc.isFirstConnectedGM()) { let turn = combat.turns.find(t => t.token?.id == combat.current.tokenId); if (turn?.actor) { RdDCombat.displayActorCombatStatus(combat, turn.actor, turn.token.id); @@ -511,7 +511,7 @@ export class RdDCombat { /* -------------------------------------------- */ static onMsgDefense(msg) { let defenderToken = canvas.tokens.get(msg.defenderTokenId); - if (defenderToken && Misc.isUniqueConnectedGM()) { + if (defenderToken && Misc.isFirstConnectedGM()) { const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.defenderTokenId); rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme); rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll); @@ -919,7 +919,7 @@ export class RdDCombat { dmg: attackerRoll.dmg, }; - if (Misc.isUniqueConnectedGM()) { + if (Misc.isFirstConnectedGM()) { await this._chatMessageDefense(paramChatDefense, defenderRoll); } else { diff --git a/module/rdd-main.js b/module/rdd-main.js index 85331625..497fd5f3 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -280,7 +280,7 @@ export class SystemReveDeDragon { /* Foundry VTT Initialization */ /* -------------------------------------------- */ game.system.rdd.calendrier = new RdDCalendrier() - if (Misc.isUniqueConnectedGM()) { + if (Misc.isFirstConnectedGM()) { new Migrations().migrate() this.messageDeBienvenue() import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter => { diff --git a/module/sommeil/app-astrologie.js b/module/sommeil/app-astrologie.js index 0e33a748..e8727294 100644 --- a/module/sommeil/app-astrologie.js +++ b/module/sommeil/app-astrologie.js @@ -186,7 +186,7 @@ export class AppAstrologie extends Application { date: this.html.find('[name="joursAstrologie"]').val(), userId: game.user.id } - if (Misc.isUniqueConnectedGM()) { + if (Misc.isFirstConnectedGM()) { game.system.rdd.calendrier.requestNombreAstral(socketData); } else { game.socket.emit(SYSTEM_SOCKET_ID, { diff --git a/module/time/rdd-calendrier.js b/module/time/rdd-calendrier.js index b2a4129d..727599c2 100644 --- a/module/time/rdd-calendrier.js +++ b/module/time/rdd-calendrier.js @@ -48,7 +48,7 @@ export class RdDCalendrier extends Application { constructor() { super(); this.timestamp = RdDTimestamp.getWorldTime(); - if (Misc.isUniqueConnectedGM()) { // Uniquement si GM + if (Misc.isFirstConnectedGM()) { // Uniquement si GM RdDTimestamp.setWorldTime(this.timestamp); this.rebuildNombresAstraux(); // Ensure always up-to-date } @@ -258,7 +258,7 @@ export class RdDCalendrier extends Application { /* -------------------------------------------- */ async rebuildNombresAstraux() { - if (Misc.isUniqueConnectedGM()) { + if (Misc.isFirstConnectedGM()) { const nombresAstraux = this.getNombresAstraux() let newNombresAstraux = []; for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) { @@ -337,7 +337,7 @@ export class RdDCalendrier extends Application { /* -------------------------------------------- */ async requestNombreAstral(request) { const actor = game.actors.get(request.id); - if (Misc.isUniqueConnectedGM()) { // Only once + if (Misc.isFirstConnectedGM()) { // Only once console.log(request); let jourDiff = this.getLectureAstrologieDifficulte(request.date); let niveau = Number(request.astrologie.system.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat); From 3b06bd382be6d3da2bbc92db9270ea2edd9d062e Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Fri, 25 Oct 2024 23:28:09 +0200 Subject: [PATCH 02/20] Afficher le nom du token au lieu du nom d'Acteur MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dans les messages d'automatisation de combat, le nom des tokens est utilisé au lieu d'utiliser le nom de l'acteur. Ceci permet de ne pas dévoiler un nom générique (Villageois) si le token a un nom personnalisé. --- changelog.md | 1 + module/actor-sheet.js | 10 +-- module/actor/base-actor-reve.js | 12 ++-- module/rdd-combat.js | 79 +++++++++++++++------- module/rdd-token-hud.js | 8 +-- module/rdd-utility.js | 9 +++ module/targets.js | 17 +++-- templates/chat-demande-attaque-etotal.html | 14 ++-- templates/chat-demande-defense.html | 38 ++++++----- 9 files changed, 121 insertions(+), 67 deletions(-) diff --git a/changelog.md b/changelog.md index 583aa09a..c5ac1466 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,7 @@ # 12.0 ## 12.0.16 - Le secret d'Astrobazzarh - Fix: les jets envoyés messages uniquement au MJ ne sont plus envoyés à tous les autres joueurs (et dupliqués) +- Les noms affichés dans les automatisations de combat sont maintenant ceux des tokens plutôt que ceux des acteurs ## 12.0.15 - Le messager d'Astrobazzarh - Correction des faces de dés personalisés dice-so-nice diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 5e2ff8b6..8e5ab07c 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -220,18 +220,18 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { // Points de reve actuel this.html.find('.roll-reve-actuel').click(async event => this.actor.rollCarac('reve-actuel', true)) this.html.find('.empoignade-label a').click(async event => RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor))) - this.html.find('.roll-arme').click(async event => this.actor.rollArme(foundry.utils.duplicate(this._getEventArmeCombat(event)))) + + this.html.find('.roll-arme').click(async event => this.actor.rollArme(foundry.utils.duplicate(this._getEventArmeCombat(event)), 'competence')) // Initiative pour l'arme this.html.find('.arme-initiative a').click(async event => { - let combatant = game.combat.combatants.find(c => c.actor.id == this.actor.id); + let combatant = game.combat.combatants.find(c => c.actor.id == this.actor.id) if (combatant) { - let action = this._getEventArmeCombat(event); - RdDCombatManager.rollInitiativeAction(combatant._id, action); + RdDCombatManager.rollInitiativeAction(combatant._id, this._getEventArmeCombat(event)); } else { ui.notifications.info("Impossible de lancer l'initiative sans être dans un combat."); } - }); + }) // Display TMR this.html.find('.button-tmr').click(async event => this.actor.displayTMR("normal")) diff --git a/module/actor/base-actor-reve.js b/module/actor/base-actor-reve.js index 06b560f5..4610fe82 100644 --- a/module/actor/base-actor-reve.js +++ b/module/actor/base-actor-reve.js @@ -327,14 +327,15 @@ export class RdDBaseActorReve extends RdDBaseActor { const competence = this.getCompetence(idOrName); let rollData = { carac: this.system.carac, competence: competence, arme: options.arme } if (competence.type == ITEM_TYPES.competencecreature) { + const token = RdDUtility.getSelectedToken(this) const arme = RdDItemCompetenceCreature.armeCreature(competence) if (arme && options.tryTarget && Targets.hasTargets()) { - Targets.selectOneToken(target => { + Targets.selectOneTargetToken(target => { if (arme.action == "possession") { RdDPossession.onAttaquePossession(target, this, competence) } else { - RdDCombat.rddCombatTarget(target, this).attaque(competence, arme) + RdDCombat.rddCombatTarget(target, this, token).attaque(competence, arme) } }); return; @@ -364,7 +365,8 @@ export class RdDBaseActorReve extends RdDBaseActor { * @param {*} categorieArme catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession * @returns */ - rollArme(arme, categorieArme = "competence") { + rollArme(arme, categorieArme, token) { + token = token ?? RdDUtility.getSelectedToken(this) const compToUse = this.$getCompetenceArme(arme, categorieArme) if (!RdDItemArme.isArmeUtilisable(arme)) { ui.notifications.warn(`Arme inutilisable: ${arme.name} a une résistance de 0 ou moins`) @@ -385,7 +387,7 @@ export class RdDBaseActorReve extends RdDBaseActor { return } - Targets.selectOneToken(target => { + Targets.selectOneTargetToken(target => { if (Targets.isTargetEntite(target)) { ui.notifications.warn(`Vous ne pouvez pas attaquer une entité non incarnée avec votre ${arme.name}!!!!`); return @@ -395,7 +397,7 @@ export class RdDBaseActorReve extends RdDBaseActor { if (competence.isCompetencePossession()) { return RdDPossession.onAttaquePossession(target, this, competence); } - RdDCombat.rddCombatTarget(target, this).attaque(competence, arme); + RdDCombat.rddCombatTarget(target, this, token).attaque(competence, arme); }) } diff --git a/module/rdd-combat.js b/module/rdd-combat.js index f31f3554..e3e404c0 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -457,7 +457,7 @@ export class RdDCombat { if (Misc.isFirstConnectedGM()) { let turn = combat.turns.find(t => t.token?.id == combat.current.tokenId); if (turn?.actor) { - RdDCombat.displayActorCombatStatus(combat, turn.actor, turn.token.id); + RdDCombat.displayActorCombatStatus(combat, turn.actor, turn.token); // TODO Playaudio for player?? } } @@ -469,30 +469,29 @@ export class RdDCombat { } /* -------------------------------------------- */ - static rddCombatTarget(target, attacker) { - const defender = target?.actor; - const defenderTokenId = target?.id; - return new RdDCombat(attacker, defender, defenderTokenId, target) + static rddCombatTarget(target, attacker, attackerToken) { + return new RdDCombat(attacker, attackerToken?.id, target?.actor, target?.id, target) } /* -------------------------------------------- */ - static rddCombatForAttackerAndDefender(attackerId, defenderTokenId) { - const attacker = game.actors.get(attackerId); - let defender = defenderTokenId ? canvas.tokens.get(defenderTokenId)?.actor : undefined; + static rddCombatForAttackerAndDefender(attackerId, attackerTokenId, defenderTokenId) { + const attacker = game.actors.get(attackerId) + const defenderToken = defenderTokenId ? canvas.tokens.get(defenderTokenId) : undefined + let defender = defenderToken?.actor; let target = undefined if (!defenderTokenId || !defender) { console.warn(`RdDCombat.rddCombatForAttackerAndDefender: appel avec defenderTokenId ${defenderTokenId} incorrect, ou pas de defender correspondant`); target = Targets.getTarget() if (!target) { - return; + return } defenderTokenId = target.id; defender = target.actor; if (!defenderTokenId || !defender) { - return; + return } } - return new RdDCombat(attacker, defender, defenderTokenId, target) + return new RdDCombat(attacker, attackerTokenId, defender, defenderTokenId, target) } /* -------------------------------------------- */ @@ -503,7 +502,7 @@ export class RdDCombat { let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined; defender.encaisserDommages(attackerRoll, attacker); - const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.defenderTokenId); + const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerTokenId, msg.defenderTokenId); rddCombat?.removeChatMessageActionsPasseArme(attackerRoll.passeArme); } } @@ -512,7 +511,7 @@ export class RdDCombat { static onMsgDefense(msg) { let defenderToken = canvas.tokens.get(msg.defenderTokenId); if (defenderToken && Misc.isFirstConnectedGM()) { - const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.defenderTokenId); + const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerTokenId, msg.defenderTokenId); rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme); rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll); } @@ -545,6 +544,7 @@ export class RdDCombat { html.on("click", button, event => { const rddCombat = RdDCombat.rddCombatForAttackerAndDefender( event.currentTarget.attributes['data-attackerId']?.value, + event.currentTarget.attributes['data-attackerTokenId']?.value, event.currentTarget.attributes['data-defenderTokenId']?.value); if (rddCombat) { rddCombat.onEvent(button, event); @@ -560,15 +560,30 @@ export class RdDCombat { } /* -------------------------------------------- */ - constructor(attacker, defender, defenderTokenId, target) { + constructor(attacker, attackerTokenId, defender, defenderTokenId, target) { this.attacker = attacker this.defender = defender this.target = target this.attackerId = this.attacker.id this.defenderId = this.defender.id + this.attackerTokenId = attackerTokenId this.defenderTokenId = defenderTokenId } + _extractDefenderTokenData() { + if (this.target) { + return Targets.extractTokenData(this.target) + } + const token = canvas.tokens.get(this.defenderTokenId); + return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(this.defenderTokenId, this.defender) + } + + _extractAttackerTokenData(){ + const token = canvas.tokens.get(this.attackerTokenId); + return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(this.attackerTokenId, this.attacker) + } + + /* -------------------------------------------- */ async onEvent(button, event) { const chatMessage = ChatUtility.getChatMessage(event); @@ -769,7 +784,7 @@ export class RdDCombat { } RdDEmpoignade.checkEmpoignadeEnCours(this.attacker) - let rollData = this._prepareAttaque(competence, arme); + let rollData = this._prepareAttaque(competence, arme) console.log("RdDCombat.attaque >>>", rollData); if (arme) { this.attacker.verifierForceMin(arme); @@ -795,18 +810,22 @@ export class RdDCombat { dialog.render(true); } + /* -------------------------------------------- */ _prepareAttaque(competence, arme) { + const sourceToken = this._extractAttackerTokenData(); let rollData = { + alias: sourceToken.name, passeArme: foundry.utils.randomID(16), mortalite: arme?.system.mortalite, competence: competence, surprise: this.attacker.getSurprise(true), surpriseDefenseur: this.defender.getSurprise(true), - targetToken: Targets.extractTokenData(this.target), + sourceToken: sourceToken, + targetToken: this._extractDefenderTokenData(), essais: {} }; - + if (this.attacker.isCreatureEntite()) { RdDItemCompetenceCreature.setRollDataCreature(rollData); } @@ -850,7 +869,8 @@ export class RdDCombat { content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html', { alias: this.attacker.name, attackerId: this.attackerId, - defenderTokenId: this.defenderTokenId, + attackerToken: this._extractAttackerTokenData(), + defenderToken: this._extractDefenderTokenData(), isForce: isForce, isFinesse: isFinesse, isRapide: isRapide, @@ -900,6 +920,7 @@ export class RdDCombat { const esquives = foundry.utils.duplicate(this.defender.getCompetencesEsquive()) esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0); + const paramChatDefense = { passeArme: attackerRoll.passeArme, essais: attackerRoll.essais, @@ -908,7 +929,8 @@ export class RdDCombat { attacker: this.attacker, attackerId: this.attackerId, esquives: esquives, - defenderTokenId: this.defenderTokenId, + attackerToken: this._extractAttackerTokenData(), + defenderToken: this._extractDefenderTokenData(), mainsNues: attackerRoll.dmg.mortalite != 'mortel' && corpsACorps, armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme), diffLibre: attackerRoll.ajustements?.diffLibre?.value ?? 0, @@ -946,6 +968,7 @@ export class RdDCombat { game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_defense", data: { attackerId: this.attacker?.id, + attackerTokenId: this.attackerTokenId, defenderId: this.defender?.id, defenderTokenId: this.defenderTokenId, defenderRoll: defenderRoll, @@ -980,7 +1003,8 @@ export class RdDCombat { content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', { attackerId: this.attackerId, attacker: this.attacker, - defenderTokenId: this.defenderTokenId, + attackerToken: this._extractAttackerTokenData(), + defenderToken: this._extractDefenderTokenData(), essais: attackerRoll.essais }) }); @@ -1051,9 +1075,13 @@ export class RdDCombat { /* -------------------------------------------- */ _prepareParade(attackerRoll, armeParade, competenceParade) { + const defenderToken = this._extractDefenderTokenData() let defenderRoll = { + alias: defenderToken?.name, passeArme: attackerRoll.passeArme, diffLibre: attackerRoll.diffLibre, + attackerToken: this._extractAttackerTokenData(), + defenderToken: defenderToken, attackerRoll: attackerRoll, competence: this.defender.getCompetence(competenceParade), arme: armeParade, @@ -1132,9 +1160,13 @@ export class RdDCombat { /* -------------------------------------------- */ _prepareEsquive(attackerRoll, competence) { + const defenderToken= this._extractDefenderTokenData() let rollData = { + alias: defenderToken?.name, passeArme: attackerRoll.passeArme, diffLibre: attackerRoll.diffLibre, + attackerToken: this._extractAttackerTokenData(), + defenderToken: defenderToken, attackerRoll: attackerRoll, competence: competence, surprise: this.defender.getSurprise(true), @@ -1296,6 +1328,7 @@ export class RdDCombat { msg: "msg_encaisser", data: { attackerId: this.attackerId, + attackerTokenId: this.attackerTokenId, defenderTokenId: defenderTokenId, attackerRoll: attackerRoll } @@ -1305,17 +1338,17 @@ export class RdDCombat { } /* -------------------------------------------- */ - static async displayActorCombatStatus(combat, actor, tokenId) { + static async displayActorCombatStatus(combat, actor, token) { let formData = { combatId: combat._id, - alias: actor.name, + alias: token.name ?? actor.name, etatGeneral: actor.getEtatGeneral(), isSonne: actor.getSonne(), blessuresStatus: actor.computeResumeBlessure(), SConst: actor.getSConst(), actorId: actor.id, actor: actor, - tokenId: tokenId, + tokenId: token.id, isGrave: actor.countBlessures(it => it.isGrave()) > 0, isCritique: actor.countBlessures(it => it.isCritique()) > 0 } diff --git a/module/rdd-token-hud.js b/module/rdd-token-hud.js index 0cdf7adf..a230f8ee 100644 --- a/module/rdd-token-hud.js +++ b/module/rdd-token-hud.js @@ -37,7 +37,7 @@ export class RdDTokenHud { // initiative await RdDTokenHud.addExtensionHudInit(html, combatant, actions); // combat - await RdDTokenHud.addExtensionHudCombat(html, combatant, actions); + await RdDTokenHud.addExtensionHudCombat(html, combatant, token, actions); } @@ -68,8 +68,8 @@ export class RdDTokenHud { }); } - static async addExtensionHudCombat(html, combatant, actions) { - const hudData = { combatant, actions, commandes: [] }; + static async addExtensionHudCombat(html, combatant, token, actions) { + const hudData = { combatant, token, actions, commandes: [] }; const controlIconTarget = html.find('.control-icon[data-action=target]'); await RdDTokenHud._configureSubMenu(controlIconTarget, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData, (event) => { @@ -80,7 +80,7 @@ export class RdDTokenHud { combatant.actor.conjurerPossession(possession); } else { - combatant.actor.rollArme(action); + combatant.actor.rollArme(action, 'competence', token) } }); } diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 20b10526..2153bfa7 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -741,6 +741,15 @@ export class RdDUtility { return undefined; } + static getSelectedToken(actor) { + if (canvas.tokens.controlled.length > 0) { + const tokens = canvas.tokens.controlled + .filter(it => it.actor.id == actor.id) + return tokens[0] + } + return undefined + } + static getSelectedActor(msgPlayer = undefined) { if (canvas.tokens.controlled.length == 1) { let token = canvas.tokens.controlled[0]; diff --git a/module/targets.js b/module/targets.js index 09d83e5d..98f76f2a 100644 --- a/module/targets.js +++ b/module/targets.js @@ -13,18 +13,21 @@ export class Targets { static extractTokenData(target) { return { id: target?.id, name: target?.document.name, img: target?.document.texture.src ?? target?.actor.img ?? 'icons/svg/mystery-man.svg' }; } - + static buildActorTokenData(tokenId, actor) { + return { id: tokenId, name: actor.name, img: actor.img ?? 'icons/svg/mystery-man.svg' }; + } static isTargetEntite(target) { return target?.actor.type == 'entite' && target?.actor.system.definition.typeentite == ENTITE_NONINCARNE; } - static async selectOneToken(onSelectTarget = target => { }) { - const targets = Targets.listTargets(); + static async selectOneTargetToken(onSelectTarget = target => { }) { + const targets = Targets.listTargets() switch (targets.length) { - case 0: return; + case 0: + return case 1: - onSelectTarget(targets[0]); - return; + onSelectTarget(targets[0]) + return default: { const selectData = { @@ -32,7 +35,7 @@ export class Targets { label: "Choisir une seule des cibles", list: targets.map(it => Targets.extractTokenData(it)) }; - DialogSelect.select(selectData, onSelectTarget); + DialogSelect.select(selectData, onSelectTarget) } } } diff --git a/templates/chat-demande-attaque-etotal.html b/templates/chat-demande-attaque-etotal.html index 6c88fc0f..c72007d7 100644 --- a/templates/chat-demande-attaque-etotal.html +++ b/templates/chat-demande-attaque-etotal.html @@ -3,20 +3,22 @@
{{#if (eq attacker.type 'personnage')}} {{#unless essais.attaqueChance}} - Faire appel à la chance + + Faire appel à la chance
{{/unless}} {{#if (gt attacker.system.compteurs.destinee.value 0)}} - Utiliser la destinée + + Utiliser la destinée
{{/if}} {{/if}} - + Tirer la maladresse !
\ No newline at end of file diff --git a/templates/chat-demande-defense.html b/templates/chat-demande-defense.html index 5d58505b..1260e009 100644 --- a/templates/chat-demande-defense.html +++ b/templates/chat-demande-defense.html @@ -1,17 +1,17 @@
{{#if (eq surprise 'totale')}} - {{defender.name}} est totalement surpris + {{defenderToken.name}} est totalement surpris {{else if essais.defense}} - {{defender.name}} doit : + {{defenderToken.name}} doit : {{else}} - {{defender.name}} doit se défendre + {{defenderToken.name}} doit se défendre {{~#if (eq surprise 'demi')}} avec une significative {{/if}} d'une attaque {{~#if attaqueParticuliere}} particulière en {{~#if (eq attaqueParticuliere 'finesse')}} finesse {{else if (eq attaqueParticuliere 'force')}} force {{else if (eq attaqueParticuliere 'rapidite')}} rapidité {{/if~}} - {{/if}} de {{attacker.name}} ({{attaqueArme.name}}): + {{/if}} de {{attackerToken.name}} ({{attaqueArme.name}}): {{/if}} @@ -20,15 +20,17 @@ {{#if essais.defense}} {{#unless essais.defenseChance}} {{#if (eq defender.type 'personnage')}} - Faire appel à la chance + + Faire appel à la chance
{{/if}} {{#if (eq defender.type 'personnage')}} {{#if (gt defender.system.compteurs.destinee.value 0)}} - Utiliser la destinée + + Utiliser la destinée
{{/if}} @@ -36,24 +38,26 @@ {{/unless}} {{else}} {{#each armes as |arme key|}} - + Parer avec {{arme.name}} à {{../diffLibre }}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}}
{{/each}} {{#if mainsNues}} - + Parer à mains nues à {{diffLibre}}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}}
{{/if}} {{#if (ne attaqueCategorie 'tir')}} {{#each esquives as |esquive key|}} - - {{log 'esquive' esquive}} + {{esquive.name}} à {{../diffLibre}} {{#if esquive.system.nbUsage}} (Utilisations : {{esquive.system.nbUsage}}){{/if}}
@@ -61,8 +65,8 @@ {{/if}} {{/if}} {{/unless}} - + Encaisser à {{plusMoins dmg.total}} {{#if (eq dmg.mortalite 'non-mortel')~}} (non-mortel) ! From 5c58932a0d47714bbb075a13030991ce7384160f Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 26 Oct 2024 01:20:03 +0200 Subject: [PATCH 03/20] =?UTF-8?q?Am=C3=A9lioration=20message=20encaissemen?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- styles/simple.css | 5 +++++ templates/chat-resultat-encaissement.html | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/styles/simple.css b/styles/simple.css index 491e0f7b..f9eb048f 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -1561,6 +1561,11 @@ div.control-icon.token-hud-icon { height: 100%; object-fit: contain; } +.chat-inline-icon { + border: 0; + padding: 1px; + vertical-align: text-top; +} #sidebar-tabs { flex: 0 0 28px; diff --git a/templates/chat-resultat-encaissement.html b/templates/chat-resultat-encaissement.html index 737eef53..d2c7ce22 100644 --- a/templates/chat-resultat-encaissement.html +++ b/templates/chat-resultat-encaissement.html @@ -18,18 +18,18 @@
Jet d'encaissement de {{roll.total}} - {{#unless (eq armure 0)}}, l'armure a protègé de {{armure}} + {{~#unless (eq armure 0)}}, l'armure a protègé de {{armure}} {{~#unless (eq penetration 0)}} (pénétration de {{penetration}}){{/unless}} - {{~/unless}}, total: {{total}} + {{~/unless~}}, total: {{total}}
{{alias}} {{#if (eq dmg.mortalite 'entiteincarnee')}}subit le coup {{else if mort}}vient de mourir {{else if blessure}} {{#if (gt blessure.system.gravite 0)}}subit une blessure {{blessure.system.label}} - {{else}}subit une contusion + {{~else~}}subit une contusion {{~/if~}} - {{else}}s'en sort sans une égratignure + {{~else~}}s'en sort sans une égratignure {{~/if~}} {{~#unless (eq dmg.mortalite 'entiteincarnee')}} @@ -39,11 +39,11 @@ {{/unless~}} {{~#if (gt endurance 0)}} {{~#if hasPlayerOwner}}, a perdu {{endurance}} points d'endurance - {{#if (ne vie 0)}}, {{vie}} points de vie{{/if}} + {{~#if (ne vie 0)}}, {{vie}} points de vie{{/if~}} {{/if}} {{#if (ne dmg.mortalite 'entiteincarnee')}} {{#if (gt endurance 1)}}et - {{#if sonne}}est sonné jusqu'à la fin du prochain round{{else}}n'est pas sonné{{/if}}! + {{#if sonne}}est sonné jusqu'à la fin du prochain round{{else}}n'est pas sonné{{/if}}! {{#if hasPlayerOwner}}Jet d'endurance : {{jetEndurance}} / {{resteEndurance}}{{/if}} {{/if}} {{/if}} From 3906cb0a7b7cdee386c11f13a03dd4503d906f1b Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 26 Oct 2024 01:33:20 +0200 Subject: [PATCH 04/20] Localisation des blessures en regle optionnelle --- changelog.md | 1 + module/actor/base-actor-reve.js | 23 +++-- module/actor/base-actor-sang.js | 8 +- module/actor/entite.js | 2 +- module/dialog-validation-encaissement.js | 9 +- module/rdd-combat.js | 102 +++++++++++------------ module/rdd-roll-encaisser.js | 2 +- module/rdd-utility.js | 17 ++-- module/settings/regles-optionnelles.js | 1 + 9 files changed, 83 insertions(+), 82 deletions(-) diff --git a/changelog.md b/changelog.md index c5ac1466..baf5946a 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,7 @@ ## 12.0.16 - Le secret d'Astrobazzarh - Fix: les jets envoyés messages uniquement au MJ ne sont plus envoyés à tous les autres joueurs (et dupliqués) - Les noms affichés dans les automatisations de combat sont maintenant ceux des tokens plutôt que ceux des acteurs +- Ajout d'une option pour la localisation des blessures ## 12.0.15 - Le messager d'Astrobazzarh - Correction des faces de dés personalisés dice-so-nice diff --git a/module/actor/base-actor-reve.js b/module/actor/base-actor-reve.js index 4610fe82..02e549d5 100644 --- a/module/actor/base-actor-reve.js +++ b/module/actor/base-actor-reve.js @@ -415,41 +415,40 @@ export class RdDBaseActorReve extends RdDBaseActor { /* -------------------------------------------- */ async encaisser() { await RdDEncaisser.encaisser(this) } - async encaisserDommages(rollData, attacker = undefined, show = undefined) { + async encaisserDommages(rollData, attacker = undefined, attackerToken = undefined, show = undefined) { if (attacker && !await attacker.accorder(this, 'avant-encaissement')) { return; } const armure = await this.computeArmure(rollData); if (ReglesOptionnelles.isUsing('validation-encaissement-gr')) { - await this.encaisserDommagesValidationGR(rollData, armure, attacker?.id, show); + await this.encaisserDommagesValidationGR(rollData, armure, attackerToken, show); } else { - const jet = await RdDUtility.jetEncaissement(rollData, armure, { showDice: SHOW_DICE }); - await this.$onEncaissement(jet, show, attacker); + const jet = await RdDUtility.jetEncaissement(this, rollData, armure, { showDice: SHOW_DICE }); + await this.$onEncaissement(jet, show, attackerToken) } } - async encaisserDommagesValidationGR(rollData, armure, attackerId, show) { + async encaisserDommagesValidationGR(rollData, armure, attackerToken, show) { if (!game.user.isGM) { RdDBaseActor.remoteActorCall({ tokenId: this.token?.id, actorId: this.id, method: 'encaisserDommagesValidationGR', - args: [rollData, armure, attackerId, show] - }); + args: [rollData, armure, attackerToken, show] + }) } else { - const attacker = game.actors.get(attackerId); DialogValidationEncaissement.validerEncaissement(this, rollData, armure, - jet => this.$onEncaissement(jet, show, attacker)); + jet => this.$onEncaissement(jet, show, attackerToken)); } } - async $onEncaissement(jet, show, attacker) { - await this.onAppliquerJetEncaissement(jet, attacker); + async $onEncaissement(jet, show, attackerToken) { + await this.onAppliquerJetEncaissement(jet, attackerToken); await this.$afficherEncaissement(jet, show); } - async onAppliquerJetEncaissement(encaissement, attacker) { } + async onAppliquerJetEncaissement(encaissement, attackerToken) { } async $afficherEncaissement(encaissement, show) { foundry.utils.mergeObject(encaissement, { diff --git a/module/actor/base-actor-sang.js b/module/actor/base-actor-sang.js index 978c27c2..48e5299a 100644 --- a/module/actor/base-actor-sang.js +++ b/module/actor/base-actor-sang.js @@ -89,9 +89,9 @@ export class RdDBaseActorSang extends RdDBaseActorReve { /* -------------------------------------------- */ - async onAppliquerJetEncaissement(encaissement, attacker) { + async onAppliquerJetEncaissement(encaissement, attackerToken) { const santeOrig = foundry.utils.duplicate(this.system.sante); - const blessure = await this.ajouterBlessure(encaissement, attacker); // Will update the result table + const blessure = await this.ajouterBlessure(encaissement, attackerToken); // Will update the result table const perteVie = await this.santeIncDec("vie", -encaissement.vie); const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, blessure?.isCritique()); @@ -169,7 +169,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve { /* -------------------------------------------- */ - async ajouterBlessure(encaissement, attacker = undefined) { + async ajouterBlessure(encaissement, attackerToken = undefined) { if (encaissement.gravite < 0) return; if (encaissement.gravite > 0) { while (this.countBlessures(it => it.system.gravite == encaissement.gravite) >= RdDItemBlessure.maxBlessures(encaissement.gravite) && encaissement.gravite <= 6) { @@ -181,7 +181,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve { } } const endActuelle = this.getEnduranceActuelle(); - const blessure = await RdDItemBlessure.createBlessure(this, encaissement.gravite, encaissement.dmg?.loc.label ?? '', attacker); + const blessure = await RdDItemBlessure.createBlessure(this, encaissement.gravite, encaissement.dmg?.loc.label ?? '', attackerToken); if (blessure.isCritique()) { encaissement.endurance = endActuelle; } diff --git a/module/actor/entite.js b/module/actor/entite.js index 70bc0577..ff0ad06a 100644 --- a/module/actor/entite.js +++ b/module/actor/entite.js @@ -74,7 +74,7 @@ export class RdDEntite extends RdDBaseActorReve { return [STATUSES.StatusComma].includes(effectId); } - async onAppliquerJetEncaissement(encaissement, attacker) { + async onAppliquerJetEncaissement(encaissement, attackerToken) { const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance); foundry.utils.mergeObject(encaissement, { resteEndurance: perteEndurance.newValue, diff --git a/module/dialog-validation-encaissement.js b/module/dialog-validation-encaissement.js index d4c41f61..c0a74d85 100644 --- a/module/dialog-validation-encaissement.js +++ b/module/dialog-validation-encaissement.js @@ -8,14 +8,13 @@ import { RdDUtility } from "./rdd-utility.js"; export class DialogValidationEncaissement extends Dialog { static async validerEncaissement(actor, rollData, armure, onEncaisser) { - let encaissement = await RdDUtility.jetEncaissement(rollData, armure, { showDice: HIDE_DICE }); + const encaissement = await RdDUtility.jetEncaissement(actor, rollData, armure, { showDice: HIDE_DICE }); const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html', { actor: actor, rollData: rollData, encaissement: encaissement }); - const dialog = new DialogValidationEncaissement(html, actor, rollData, armure, encaissement, onEncaisser); - dialog.render(true); + new DialogValidationEncaissement(html, actor, rollData, armure, encaissement, onEncaisser).render(true); } /* -------------------------------------------- */ @@ -56,14 +55,14 @@ export class DialogValidationEncaissement extends Dialog { this.html = html; this.html.find('input.encaissement-roll-result').keyup(async event => { this.forceDiceResult.total = event.currentTarget.value; - this.encaissement = await RdDUtility.jetEncaissement(this.rollData, this.armure, { showDice: HIDE_DICE, forceDiceResult: this.forceDiceResult}); + this.encaissement = await RdDUtility.jetEncaissement(this.actor, this.rollData, this.armure, { showDice: HIDE_DICE, forceDiceResult: this.forceDiceResult}); this.html.find('label.encaissement-total').text(this.encaissement.total); this.html.find('label.encaissement-blessure').text(this.encaissement.blessures) }); } async onValider() { - this.encaissement = await RdDUtility.jetEncaissement(this.rollData, this.armure, { showDice: SHOW_DICE, forceDiceResult: this.forceDiceResult}); + this.encaissement = await RdDUtility.jetEncaissement(this.actor, this.rollData, this.armure, { showDice: SHOW_DICE, forceDiceResult: this.forceDiceResult}); this.onEncaisser(this.encaissement) } } diff --git a/module/rdd-combat.js b/module/rdd-combat.js index e3e404c0..4de3fb5b 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -496,24 +496,24 @@ export class RdDCombat { /* -------------------------------------------- */ static onMsgEncaisser(msg) { - let defender = canvas.tokens.get(msg.defenderTokenId).actor; if (Misc.isOwnerPlayerOrUniqueConnectedGM()) { let attackerRoll = msg.attackerRoll; let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined; + let defender = canvas.tokens.get(msg.defenderToken.id).actor; - defender.encaisserDommages(attackerRoll, attacker); - const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerTokenId, msg.defenderTokenId); + defender.encaisserDommages(attackerRoll, attacker, msg.attackerToken); + const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerToken.id, msg.defenderToken.id); rddCombat?.removeChatMessageActionsPasseArme(attackerRoll.passeArme); } } /* -------------------------------------------- */ static onMsgDefense(msg) { - let defenderToken = canvas.tokens.get(msg.defenderTokenId); + let defenderToken = canvas.tokens.get(msg.defenderToken.id) if (defenderToken && Misc.isFirstConnectedGM()) { - const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerTokenId, msg.defenderTokenId); - rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme); - rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll); + const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerToken.id, msg.defenderToken.id) + rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme) + rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll) } } @@ -568,19 +568,21 @@ export class RdDCombat { this.defenderId = this.defender.id this.attackerTokenId = attackerTokenId this.defenderTokenId = defenderTokenId + this.attackerToken = RdDCombat.$extractAttackerTokenData(attacker, attackerTokenId) + this.defenderToken = RdDCombat.$extractDefenderTokenData(defender, defenderTokenId, target) } - _extractDefenderTokenData() { - if (this.target) { - return Targets.extractTokenData(this.target) + static $extractAttackerTokenData(attacker, attackerTokenId) { + const token = canvas.tokens.get(attackerTokenId); + return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(attackerTokenId, attacker) + } + + static $extractDefenderTokenData(defender, defenderTokenId, target) { + if (target) { + return Targets.extractTokenData(target) } - const token = canvas.tokens.get(this.defenderTokenId); - return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(this.defenderTokenId, this.defender) - } - - _extractAttackerTokenData(){ - const token = canvas.tokens.get(this.attackerTokenId); - return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(this.attackerTokenId, this.attacker) + const token = canvas.tokens.get(defenderTokenId); + return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(defenderTokenId, defender) } @@ -590,7 +592,6 @@ export class RdDCombat { 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; const competence = event.currentTarget.attributes['data-competence']?.value; @@ -600,7 +601,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, defenderRoll, defenderTokenId); + case '#encaisser-button': return this.encaisser(attackerRoll, defenderRoll); case '#echec-total-attaque': return this._onEchecTotal(attackerRoll); case '#appel-chance-attaque': return this.attacker.rollAppelChance( @@ -717,7 +718,7 @@ export class RdDCombat { }) } else { - const defenderToken = canvas.tokens.get(this.defenderTokenId); + const defenderToken = canvas.tokens.get(this.defenderTokenId) const dist = this.distance(_token, defenderToken) const isVisible = this.isVisible(_token, defenderToken) const portee = this._ajustementPortee(dist, rollData.arme) @@ -813,16 +814,15 @@ export class RdDCombat { /* -------------------------------------------- */ _prepareAttaque(competence, arme) { - const sourceToken = this._extractAttackerTokenData(); let rollData = { - alias: sourceToken.name, + alias: this.attackerToken.name, passeArme: foundry.utils.randomID(16), mortalite: arme?.system.mortalite, competence: competence, surprise: this.attacker.getSurprise(true), surpriseDefenseur: this.defender.getSurprise(true), - sourceToken: sourceToken, - targetToken: this._extractDefenderTokenData(), + sourceToken: this.attackerToken, + targetToken: this.defenderToken, essais: {} }; @@ -867,10 +867,10 @@ export class RdDCombat { alias: this.attacker.name, whisper: ChatUtility.getOwners(this.attacker), content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html', { - alias: this.attacker.name, + alias: this.attackerToken.name, attackerId: this.attackerId, - attackerToken: this._extractAttackerTokenData(), - defenderToken: this._extractDefenderTokenData(), + attackerToken: this.attackerToken, + defenderToken: this.defenderToken, isForce: isForce, isFinesse: isFinesse, isRapide: isRapide, @@ -920,7 +920,6 @@ export class RdDCombat { const esquives = foundry.utils.duplicate(this.defender.getCompetencesEsquive()) esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0); - const paramChatDefense = { passeArme: attackerRoll.passeArme, essais: attackerRoll.essais, @@ -929,8 +928,8 @@ export class RdDCombat { attacker: this.attacker, attackerId: this.attackerId, esquives: esquives, - attackerToken: this._extractAttackerTokenData(), - defenderToken: this._extractDefenderTokenData(), + attackerToken: this.attackerToken, + defenderToken: this.defenderToken, mainsNues: attackerRoll.dmg.mortalite != 'mortel' && corpsACorps, armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme), diffLibre: attackerRoll.ajustements?.diffLibre?.value ?? 0, @@ -954,7 +953,7 @@ export class RdDCombat { 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, + alias: this.attackerToken.name, whisper: ChatUtility.getOwners(this.defender), content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.html', paramDemandeDefense), }); @@ -968,9 +967,9 @@ export class RdDCombat { game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_defense", data: { attackerId: this.attacker?.id, - attackerTokenId: this.attackerTokenId, + attackerToken: this.attackerToken, defenderId: this.defender?.id, - defenderTokenId: this.defenderTokenId, + defenderToken: this.defenderToken, defenderRoll: defenderRoll, paramChatDefense: paramChatDefense, rollMode: true @@ -1003,8 +1002,8 @@ export class RdDCombat { content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', { attackerId: this.attackerId, attacker: this.attacker, - attackerToken: this._extractAttackerTokenData(), - defenderToken: this._extractDefenderTokenData(), + attackerToken: this.attackerToken, + defenderToken: this.defenderToken, essais: attackerRoll.essais }) }); @@ -1075,13 +1074,12 @@ export class RdDCombat { /* -------------------------------------------- */ _prepareParade(attackerRoll, armeParade, competenceParade) { - const defenderToken = this._extractDefenderTokenData() let defenderRoll = { - alias: defenderToken?.name, + alias: this.defenderToken?.name, passeArme: attackerRoll.passeArme, diffLibre: attackerRoll.diffLibre, - attackerToken: this._extractAttackerTokenData(), - defenderToken: defenderToken, + attackerToken: this.attackerToken, + defenderToken: this.defenderToken, attackerRoll: attackerRoll, competence: this.defender.getCompetence(competenceParade), arme: armeParade, @@ -1160,13 +1158,12 @@ export class RdDCombat { /* -------------------------------------------- */ _prepareEsquive(attackerRoll, competence) { - const defenderToken= this._extractDefenderTokenData() let rollData = { - alias: defenderToken?.name, + alias: this.defenderToken?.name, passeArme: attackerRoll.passeArme, diffLibre: attackerRoll.diffLibre, - attackerToken: this._extractAttackerTokenData(), - defenderToken: defenderToken, + attackerToken: this.attackerToken, + defenderToken: this.defenderToken, attackerRoll: attackerRoll, competence: competence, surprise: this.defender.getSurprise(true), @@ -1308,9 +1305,8 @@ export class RdDCombat { } /* -------------------------------------------- */ - async encaisser(attackerRoll, defenderRoll, defenderTokenId) { - defenderTokenId = defenderTokenId || this.defenderTokenId; - console.log("RdDCombat.encaisser >>>", attackerRoll, defenderTokenId); + async encaisser(attackerRoll, defenderRoll) { + console.log("RdDCombat.encaisser >>>", attackerRoll, defenderRoll); if (defenderRoll?.rolled && RdDCombat.isEchecTotal(defenderRoll)) { this._onEchecTotal(defenderRoll); @@ -1318,19 +1314,19 @@ export class RdDCombat { if (Misc.isOwnerPlayerOrUniqueConnectedGM(this.defender)) { attackerRoll.attackerId = this.attackerId; - attackerRoll.defenderTokenId = defenderTokenId; + attackerRoll.defenderTokenId = this.defenderToken.id; await this.computeRecul(defenderRoll); - await this.defender.encaisserDommages(attackerRoll, this.attacker, defenderRoll?.show); + await this.defender.encaisserDommages(attackerRoll, this.attacker, this.attackerToken, defenderRoll?.show); } 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_SOCKET_ID, { msg: "msg_encaisser", data: { attackerId: this.attackerId, - attackerTokenId: this.attackerTokenId, - defenderTokenId: defenderTokenId, - attackerRoll: attackerRoll + attackerRoll: attackerRoll, + attackerToken: this.attackerToken, + defenderToken: this.defenderToken } }); } @@ -1354,12 +1350,12 @@ export class RdDCombat { } await ChatMessage.create({ content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-acteur.hbs`, formData), - alias: actor.name + alias: token.name ?? actor.name }) await ChatMessage.create({ content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-sante.hbs`, formData), whisper: ChatUtility.getOwners(actor), - alias: actor.name + alias: token.name ?? actor.name }); } } \ No newline at end of file diff --git a/module/rdd-roll-encaisser.js b/module/rdd-roll-encaisser.js index a9fc2d84..14748a6e 100644 --- a/module/rdd-roll-encaisser.js +++ b/module/rdd-roll-encaisser.js @@ -72,6 +72,6 @@ export class RdDEncaisser extends Dialog { encaisserSpecial: this.encaisserSpecial, mortalite: mortalite } - }); + }) } } diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 2153bfa7..70950c74 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -563,14 +563,14 @@ export class RdDUtility { } /* -------------------------------------------- */ - static async jetEncaissement(rollData, armure, options = { showDice: HIDE_DICE }) { + static async jetEncaissement(actor, rollData, armure, options = { showDice: HIDE_DICE }) { const diff = Math.abs(rollData.diffLibre); let formula = RdDUtility.formuleEncaissement(diff, options) const roll = await RdDDice.roll(formula, options); RdDUtility.remplaceDeMinParDifficulte(roll, diff, options); - return await RdDUtility.prepareEncaissement(rollData, roll, armure); + return await RdDUtility.prepareEncaissement(actor, rollData, roll, armure); } static remplaceDeMinParDifficulte(roll, diff, options) { @@ -602,15 +602,20 @@ export class RdDUtility { } /* -------------------------------------------- */ - static async prepareEncaissement(rollData, roll, armure) { + static async prepareEncaissement(actor, rollData, roll, armure) { // La difficulté d'ataque s'ajoute aux dégâts const bonusDegatsDiffLibre = ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(rollData.diffLibre ?? 0) : 0 const jetTotal = roll.total + rollData.dmg.total - armure + bonusDegatsDiffLibre const encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite); const over20 = Math.max(jetTotal - 20, 0); - encaissement.dmg = rollData.dmg; - encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(this.type); - encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;'; + encaissement.dmg = rollData.dmg + if (ReglesOptionnelles.isUsing('localisation-aleatoire')){ + encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(actor.type) + encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;' + } + else{ + encaissement.dmg.loc = {label:''} + } encaissement.dmg.bonusDegatsDiffLibre = bonusDegatsDiffLibre encaissement.roll = roll; encaissement.armure = armure; diff --git a/module/settings/regles-optionnelles.js b/module/settings/regles-optionnelles.js index 3eac1e2d..02c2cd60 100644 --- a/module/settings/regles-optionnelles.js +++ b/module/settings/regles-optionnelles.js @@ -11,6 +11,7 @@ const listeReglesOptionnelles = [ { group: 'Récupération', name: 'recuperation-moral', descr: "Le moral revient vers 0 durant Château Dormant"}, + { group: 'Règles de combat', name: 'localisation-aleatoire', descr: "Proposer une localisation aléatoire des blessures" }, { group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" }, { group: 'Règles de combat', name: 'resistanceArmeParade', descr: "Faire le jet de résistance des armes lors de parades pouvant les endommager" }, { group: 'Règles de combat', name: 'deteriorationArmure', descr: "Tenir compte de la détérioration des armures" }, From b892068b38a96186b121ca8466a885b415637630 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 26 Oct 2024 01:38:36 +0200 Subject: [PATCH 05/20] Utilisation du nom du Nom du token suite (pour les encaissements) --- module/actor/base-actor-reve.js | 22 +++++++++++----------- module/rdd-combat.js | 4 ++-- templates/chat-resultat-encaissement.html | 1 - 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/module/actor/base-actor-reve.js b/module/actor/base-actor-reve.js index 02e549d5..21d2e608 100644 --- a/module/actor/base-actor-reve.js +++ b/module/actor/base-actor-reve.js @@ -415,47 +415,47 @@ export class RdDBaseActorReve extends RdDBaseActor { /* -------------------------------------------- */ async encaisser() { await RdDEncaisser.encaisser(this) } - async encaisserDommages(rollData, attacker = undefined, attackerToken = undefined, show = undefined) { + async encaisserDommages(rollData, attacker = undefined, show = undefined, attackerToken = undefined, defenderToken = undefined) { if (attacker && !await attacker.accorder(this, 'avant-encaissement')) { return; } const armure = await this.computeArmure(rollData); if (ReglesOptionnelles.isUsing('validation-encaissement-gr')) { - await this.encaisserDommagesValidationGR(rollData, armure, attackerToken, show); + await this.encaisserDommagesValidationGR(rollData, armure, show, attackerToken, defenderToken); } else { const jet = await RdDUtility.jetEncaissement(this, rollData, armure, { showDice: SHOW_DICE }); - await this.$onEncaissement(jet, show, attackerToken) + await this.$onEncaissement(jet, show, attackerToken, defenderToken) } } - async encaisserDommagesValidationGR(rollData, armure, attackerToken, show) { + async encaisserDommagesValidationGR(rollData, armure, show, attackerToken, defenderToken) { if (!game.user.isGM) { RdDBaseActor.remoteActorCall({ tokenId: this.token?.id, actorId: this.id, method: 'encaisserDommagesValidationGR', - args: [rollData, armure, attackerToken, show] + args: [rollData, armure, show, attackerToken, defenderToken] }) } else { DialogValidationEncaissement.validerEncaissement(this, rollData, armure, - jet => this.$onEncaissement(jet, show, attackerToken)); + jet => this.$onEncaissement(jet, show, attackerToken, defenderToken)); } } - async $onEncaissement(jet, show, attackerToken) { + async $onEncaissement(jet, show, attackerToken, defenderToken) { await this.onAppliquerJetEncaissement(jet, attackerToken); - await this.$afficherEncaissement(jet, show); + await this.$afficherEncaissement(jet, show, defenderToken); } async onAppliquerJetEncaissement(encaissement, attackerToken) { } - async $afficherEncaissement(encaissement, show) { + async $afficherEncaissement(encaissement, show, defenderToken) { foundry.utils.mergeObject(encaissement, { - alias: this.name, + alias: defenderToken?.name ?? this.name, hasPlayerOwner: this.hasPlayerOwner, show: show ?? {} - }); + }, {overwrite: false}); await ChatUtility.createChatWithRollMode( { diff --git a/module/rdd-combat.js b/module/rdd-combat.js index 4de3fb5b..22cca49a 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -887,7 +887,7 @@ export class RdDCombat { attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite()); let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} } attackerRoll.show = { - cible: this.target ? this.defender.name : 'la cible', + cible: this.defenderToken?.name ?? 'la cible', isRecul: (attackerRoll.particuliere == 'force' || attackerRoll.tactique == 'charge') } await RdDResolutionTable.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.html'); @@ -1317,7 +1317,7 @@ export class RdDCombat { attackerRoll.defenderTokenId = this.defenderToken.id; await this.computeRecul(defenderRoll); - await this.defender.encaisserDommages(attackerRoll, this.attacker, this.attackerToken, defenderRoll?.show); + await this.defender.encaisserDommages(attackerRoll, this.attacker, defenderRoll?.show, this.attackerToken, this.defenderToken); } 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_SOCKET_ID, { diff --git a/templates/chat-resultat-encaissement.html b/templates/chat-resultat-encaissement.html index d2c7ce22..f10b9ee5 100644 --- a/templates/chat-resultat-encaissement.html +++ b/templates/chat-resultat-encaissement.html @@ -1,5 +1,4 @@ {{#if isGM}} -{{log this}} {{#if (gt endurance 0)}} De plus, {{alias}} a perdu {{endurance}} points d'endurance From 210b129934be9f3deebb2f1b7ab89a6b16d9d21c Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 26 Oct 2024 21:37:47 +0200 Subject: [PATCH 06/20] =?UTF-8?q?Fix:=20niveau=20de=20comp=C3=A9tence=20no?= =?UTF-8?q?n=20d=C3=A9fini?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - quand le niveau de compétence n'était pas défini, la feuille de personnage simplifiée et l'export scriptarium ne marchaient pas - on pouvait saisitr une compétence avec un niveau non défini --- module/actor/export-scriptarium/mapping.js | 3 ++- module/item-competence.js | 2 +- module/item-sheet.js | 13 ++++++++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/module/actor/export-scriptarium/mapping.js b/module/actor/export-scriptarium/mapping.js index ffb2b788..6aaee07e 100644 --- a/module/actor/export-scriptarium/mapping.js +++ b/module/actor/export-scriptarium/mapping.js @@ -327,7 +327,8 @@ export class Mapping { const txtByCategories = Object.values(byCategories) .map(it => it.competencesParNiveau) .map(byNiveau => { - const niveaux = Object.keys(byNiveau).map(it => Number(it)).sort(Misc.ascending()) + const niveaux = Object.keys(byNiveau) + .map(it => Number(it)).sort(Misc.ascending()) if (niveaux.length == 0) { return '' } diff --git a/module/item-competence.js b/module/item-competence.js index 25c6659d..f09ca6a8 100644 --- a/module/item-competence.js +++ b/module/item-competence.js @@ -190,7 +190,7 @@ export class RdDItemCompetence extends Item { /* -------------------------------------------- */ static isNiveauBase(item) { - return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie, item.type); + return item.system.niveau == undefined || Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie, item.type); } /* -------------------------------------------- */ diff --git a/module/item-sheet.js b/module/item-sheet.js index 93e3a6c5..dd58ab6f 100644 --- a/module/item-sheet.js +++ b/module/item-sheet.js @@ -267,10 +267,17 @@ export class RdDItemSheet extends ItemSheet { /* -------------------------------------------- */ /** @override */ _updateObject(event, formData) { - if (this.item.type == 'sort') { - // Données de bonus de cases ? - formData['system.bonuscase'] = RdDItemSort.buildBonuscaseFromArrays(formData.bonusValue, formData.caseValue); + switch (this.item.type) { + case ITEM_TYPES.sort: + // Données de bonus de cases ? + formData['system.bonuscase'] = RdDItemSort.buildBonuscaseFromArrays(formData.bonusValue, formData.caseValue) + break + case ITEM_TYPES.competence: + if (formData['system.niveau'] == undefined) { + formData['system.niveau'] = formData['system.base'] + } } + return this.item.update(formData); } From 92185d4a5b7ed11ec3248dafe78bf644e0dca5a7 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 26 Oct 2024 22:43:58 +0200 Subject: [PATCH 07/20] =?UTF-8?q?Portrait=20dans=20les=20feuilles=20simpli?= =?UTF-8?q?fi=C3=A9es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog.md | 3 +++ .../export-scriptarium/actor-encart-sheet.hbs | 22 ++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/changelog.md b/changelog.md index baf5946a..7cb22398 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,7 @@ # 12.0 +## 12.0.18 - A la barbe d'Astrobazzarh +- Ajout du portrait sur les feuilles simplifiées + ## 12.0.16 - Le secret d'Astrobazzarh - Fix: les jets envoyés messages uniquement au MJ ne sont plus envoyés à tous les autres joueurs (et dupliqués) - Les noms affichés dans les automatisations de combat sont maintenant ceux des tokens plutôt que ceux des acteurs diff --git a/templates/actor/export-scriptarium/actor-encart-sheet.hbs b/templates/actor/export-scriptarium/actor-encart-sheet.hbs index 91d943e6..1368d560 100644 --- a/templates/actor/export-scriptarium/actor-encart-sheet.hbs +++ b/templates/actor/export-scriptarium/actor-encart-sheet.hbs @@ -1,11 +1,17 @@
-
-
-
-

{{name}} -

+
+
+ +
+
+
+

{{name}}

-
+
+ + + + {{#if system.attributs.hautrevant.value}} @@ -17,10 +23,6 @@ {{/if}} - - - - {{#if @root.options.isGM}} {{/if}} From 1760d260148a0811932cc41726138a95f76d5ea0 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 27 Oct 2024 00:01:33 +0200 Subject: [PATCH 08/20] PNJ: support initiative --- module/actor-sheet.js | 2 +- templates/actor/combat.html | 2 +- templates/actor/export-scriptarium/arme.hbs | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 8e5ab07c..1b2f7abf 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -224,7 +224,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { this.html.find('.roll-arme').click(async event => this.actor.rollArme(foundry.utils.duplicate(this._getEventArmeCombat(event)), 'competence')) // Initiative pour l'arme - this.html.find('.arme-initiative a').click(async event => { + this.html.find('.roll-init-arme').click(async event => { let combatant = game.combat.combatants.find(c => c.actor.id == this.actor.id) if (combatant) { RdDCombatManager.rollInitiativeAction(combatant._id, this._getEventArmeCombat(event)); diff --git a/templates/actor/combat.html b/templates/actor/combat.html index 776f2b34..8179a27b 100644 --- a/templates/actor/combat.html +++ b/templates/actor/combat.html @@ -25,7 +25,7 @@ {{plusMoins arme.system.niveau}} {{plusMoins arme.system.dommagesReels}} - {{arme.system.initiative}} + {{arme.system.initiative}} {{/each}} {{#each esquives as |esq key|}} diff --git a/templates/actor/export-scriptarium/arme.hbs b/templates/actor/export-scriptarium/arme.hbs index 80b3b77e..264fce9f 100644 --- a/templates/actor/export-scriptarium/arme.hbs +++ b/templates/actor/export-scriptarium/arme.hbs @@ -10,7 +10,11 @@
{{niveau}}
{{#if init}} -
{{init}}
+ {{#if name}} + + {{else}} +
{{init}}
+ {{/if}}
{{dommages}}
{{else}}
From 2de9ea49c8b9b577af2eda35df733a915e583b22 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 27 Oct 2024 00:02:03 +0200 Subject: [PATCH 09/20] PNJ: ajout mains nues et empoignade --- module/actor/export-scriptarium/mapping.js | 39 +++++++++++++--------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/module/actor/export-scriptarium/mapping.js b/module/actor/export-scriptarium/mapping.js index 6aaee07e..c9161dba 100644 --- a/module/actor/export-scriptarium/mapping.js +++ b/module/actor/export-scriptarium/mapping.js @@ -140,16 +140,15 @@ export class Mapping { static prepareArmes(actor) { const armes = actor.items.filter(it => it.type == ITEM_TYPES.arme) - return armes.map(arme => - [ - arme.system.unemain ? Mapping.prepareArme(actor, arme, 'unemain') : undefined, - arme.system.deuxmains ? Mapping.prepareArme(actor, arme, 'deuxmains') : undefined, - !(arme.system.unemain || arme.system.deuxmains) ? Mapping.prepareArme(actor, arme, 'competence') : undefined, - arme.system.lancer != "" ? Mapping.prepareArme(actor, arme, 'lancer') : undefined, - arme.system.tir != "" ? Mapping.prepareArme(actor, arme, 'tir') : undefined - ] - .filter(it => it != undefined) - ).reduce((a, b) => a.concat(b), []) + RdDItemArme.ajoutCorpsACorps(armes, actor) + return armes.map(arme => [ + arme.system.unemain ? Mapping.prepareArme(actor, arme, 'unemain') : undefined, + arme.system.deuxmains ? Mapping.prepareArme(actor, arme, 'deuxmains') : undefined, + !(arme.system.unemain || arme.system.deuxmains) ? Mapping.prepareArme(actor, arme, 'competence') : undefined, + arme.system.lancer != "" ? Mapping.prepareArme(actor, arme, 'lancer') : undefined, + arme.system.tir != "" ? Mapping.prepareArme(actor, arme, 'tir') : undefined] + .filter(it => it != undefined)) + .reduce((a, b) => a.concat(b), []) } static prepareArme(actor, arme, maniement) { @@ -158,27 +157,35 @@ export class Mapping { if (RdDItemCompetence.isNiveauBase(competence)) { return undefined } - const dmgArme = RdDItemArme.dommagesReels(arme, maniement) - const dommages = dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme) const categorie = Mapping.complementCategorie(arme, maniement) + const dommages = Mapping.dommagesArme(actor, arme, maniement) return { name: arme.name + categorie, niveau: Misc.toSignedString(competence.system.niveau), init: Mapping.calculBaseInit(actor, competence.system.categorie) + competence.system.niveau, - dommages: Misc.toSignedString(dommages), + dommages: dommages, competence: competence, arme: arme } } + static dommagesArme(actor, arme, maniement){ + const dmgArme = RdDItemArme.dommagesReels(arme, maniement) + const dommages = Misc.toSignedString(dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme)) + switch(arme.system.mortalite) { + case 'non-mortel': return `(${dommages})` + case 'empoignade': return '-' + } + return dommages + } static complementCategorie(arme, maniement) { switch (maniement) { - case 'unemain': return (arme.system.deuxmains) ? ' 1 main' : (arme.system.lancer||arme.system.tir) ? ' mêlée': '' - case 'deuxmains': return (arme.system.unemain) ? ' 2 mains' : (arme.system.lancer||arme.system.tir) ? ' mêlée': '' + case 'unemain': return (arme.system.deuxmains) ? ' 1 main' : (arme.system.lancer || arme.system.tir) ? ' mêlée' : '' + case 'deuxmains': return (arme.system.unemain) ? ' 2 mains' : (arme.system.lancer || arme.system.tir) ? ' mêlée' : '' case 'lancer': return (arme.system.unemain || arme.system.deuxmains || arme.system.tir) ? ' jet' : '' case 'tir': return (arme.system.unemain || arme.system.deuxmains || arme.system.lancer) ? ' tir' : '' } - return '' + return '' } static calculBaseInit(actor, categorie) { From 5cab219e0ec7f050473224aa431d722d2937bc6f Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 27 Oct 2024 00:02:24 +0200 Subject: [PATCH 10/20] PNJ: affichage niveau d'esquive --- templates/actor/export-scriptarium/esquive.hbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/actor/export-scriptarium/esquive.hbs b/templates/actor/export-scriptarium/esquive.hbs index 550cc470..d07a4d21 100644 --- a/templates/actor/export-scriptarium/esquive.hbs +++ b/templates/actor/export-scriptarium/esquive.hbs @@ -2,7 +2,7 @@
{{upperFirst name}}
-
{{niveau}}
+
{{numberFormat competence.system.niveau decimals=0 sign=true}}
From 9bb45c2349303090a883d33b819c6c28a3c1544e Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 27 Oct 2024 00:03:30 +0200 Subject: [PATCH 11/20] PNJ: boutons des compteurs Pas de bouton + au max de vie/endurance. Pas de bouton - au min, de fatigue --- templates/actor/export-scriptarium/carac-compteur.hbs | 2 -- templates/actor/export-scriptarium/carac-derivee-compteur.hbs | 4 ++++ templates/actor/export-scriptarium/fatigue.hbs | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/templates/actor/export-scriptarium/carac-compteur.hbs b/templates/actor/export-scriptarium/carac-compteur.hbs index d80779c9..0d81f2de 100644 --- a/templates/actor/export-scriptarium/carac-compteur.hbs +++ b/templates/actor/export-scriptarium/carac-compteur.hbs @@ -11,8 +11,6 @@
- {{log carac.colName carac.value (eq carac.value actuel.value) actuel.value}} - {{log carac.colName carac.value (eq 1 1) actuel.value}} {{carac.value}} {{#unless (eq carac.value actuel.value)}}(Actuel : {{actuel.value}}){{/unless}}
diff --git a/templates/actor/export-scriptarium/carac-derivee-compteur.hbs b/templates/actor/export-scriptarium/carac-derivee-compteur.hbs index 574a0590..e9c97687 100644 --- a/templates/actor/export-scriptarium/carac-derivee-compteur.hbs +++ b/templates/actor/export-scriptarium/carac-derivee-compteur.hbs @@ -2,7 +2,11 @@
{{upperFirst carac.colName}} + {{#if (eq carac.value actuel.value)}} + + {{else}} + {{/if}}
{{carac.value}} {{#unless (eq carac.value actuel.value)}}(Actuel : {{actuel.value}}){{/unless}} diff --git a/templates/actor/export-scriptarium/fatigue.hbs b/templates/actor/export-scriptarium/fatigue.hbs index 6573afae..566d9eff 100644 --- a/templates/actor/export-scriptarium/fatigue.hbs +++ b/templates/actor/export-scriptarium/fatigue.hbs @@ -3,7 +3,11 @@ {{#if etat.fatigue.malus}} ({{etat.fatigue.malus}}) {{/if}} + {{#if (eq etat.fatigue.value 0)}} + + {{else}} + {{/if}}
From f896f1da6e983577bf47065a8139a0bf9b9bbd76 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 27 Oct 2024 08:47:44 +0100 Subject: [PATCH 12/20] Fix rename attackerToken MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit correction oubli sans gravité --- module/item/blessure.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/item/blessure.js b/module/item/blessure.js index 14c63724..b527249b 100644 --- a/module/item/blessure.js +++ b/module/item/blessure.js @@ -67,7 +67,7 @@ export class RdDItemBlessure extends RdDItem { } - static async createBlessure(actor, gravite, localisation = '', attacker) { + static async createBlessure(actor, gravite, localisation = '', attackerToken) { const definition = RdDItemBlessure.getDefinition(gravite) const blessure = { name: definition.label, @@ -77,7 +77,7 @@ export class RdDItemBlessure extends RdDItem { gravite: gravite, difficulte: - gravite, localisation: localisation, - origine: attacker?.name ?? "" + origine: attackerToken?.name ?? "" } } const blessures = await actor.createEmbeddedDocuments('Item', [blessure]) From 6106e2a19eb185b90e2dd1d61d2b22b7c16d30bb Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 27 Oct 2024 08:48:11 +0100 Subject: [PATCH 13/20] Fix changelog feuille PNJ --- changelog.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 7cb22398..15d1d650 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,11 @@ # 12.0 ## 12.0.18 - A la barbe d'Astrobazzarh -- Ajout du portrait sur les feuilles simplifiées +- Améliorations sur la feuille de PNJ simplifiée + - Ajout du portrait + - Ajout du corps à corps + - Affichage du niveau d'esquive + - Un clic sur l'initiative permet de lancer l'initiative + - les boutons +/- pour la vie, l'endurance et la fatigue changent si on est à la valeur normale ## 12.0.16 - Le secret d'Astrobazzarh - Fix: les jets envoyés messages uniquement au MJ ne sont plus envoyés à tous les autres joueurs (et dupliqués) From 85acb5a255adcdb8cef3e8c2680ba2ecd7ad5d64 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 3 Nov 2024 21:29:18 +0100 Subject: [PATCH 14/20] Fix: message de tchat des commerces --- changelog.md | 2 ++ module/actor/base-actor.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 15d1d650..c1355261 100644 --- a/changelog.md +++ b/changelog.md @@ -6,6 +6,8 @@ - Affichage du niveau d'esquive - Un clic sur l'initiative permet de lancer l'initiative - les boutons +/- pour la vie, l'endurance et la fatigue changent si on est à la valeur normale +- Fix: les achats des commerces sont de nouveau possibles + ## 12.0.16 - Le secret d'Astrobazzarh - Fix: les jets envoyés messages uniquement au MJ ne sont plus envoyés à tous les autres joueurs (et dupliqués) diff --git a/module/actor/base-actor.js b/module/actor/base-actor.js index c92b8318..b7553c68 100644 --- a/module/actor/base-actor.js +++ b/module/actor/base-actor.js @@ -317,7 +317,7 @@ export class RdDBaseActor extends Actor { RdDAudio.PlayContextAudio("argent"); // Petit son ChatMessage.create({ - whisper: ChatUtility.getOwners(this.name), + whisper: ChatUtility.getOwners(this), content: `Vous avez reçu ${sols} Sols ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.` }); } From 6e234411cab0c55434a4ecd6fd8d1ba62a509f96 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 3 Nov 2024 21:56:43 +0100 Subject: [PATCH 15/20] Fix: Commande /astro --- changelog.md | 5 +++-- module/misc.js | 2 +- module/rdd-utility.js | 14 +++++++------- module/time/rdd-timestamp.js | 22 ++++++++++++++-------- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/changelog.md b/changelog.md index c1355261..286af35e 100644 --- a/changelog.md +++ b/changelog.md @@ -6,8 +6,9 @@ - Affichage du niveau d'esquive - Un clic sur l'initiative permet de lancer l'initiative - les boutons +/- pour la vie, l'endurance et la fatigue changent si on est à la valeur normale -- Fix: les achats des commerces sont de nouveau possibles - +- Fix + - les achats des commerces sont de nouveau possibles + - la commande /astro fonctionne de nouveau ## 12.0.16 - Le secret d'Astrobazzarh - Fix: les jets envoyés messages uniquement au MJ ne sont plus envoyés à tous les autres joueurs (et dupliqués) diff --git a/module/misc.js b/module/misc.js index a3f5f43d..76a93ff3 100644 --- a/module/misc.js +++ b/module/misc.js @@ -139,7 +139,7 @@ export class Misc { } static join(params, separator = '') { - return params?.reduce(Misc.joining(separator)) ?? ''; + return (!params || params.length == 0) ? '' : params.reduce(Misc.joining(separator)) } static joining(separator = '') { diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 70950c74..59bc9809 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -609,12 +609,12 @@ export class RdDUtility { const encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite); const over20 = Math.max(jetTotal - 20, 0); encaissement.dmg = rollData.dmg - if (ReglesOptionnelles.isUsing('localisation-aleatoire')){ + if (ReglesOptionnelles.isUsing('localisation-aleatoire')) { encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(actor.type) encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;' } - else{ - encaissement.dmg.loc = {label:''} + else { + encaissement.dmg.loc = { label: '' } } encaissement.dmg.bonusDegatsDiffLibre = bonusDegatsDiffLibre encaissement.roll = roll; @@ -749,7 +749,7 @@ export class RdDUtility { static getSelectedToken(actor) { if (canvas.tokens.controlled.length > 0) { const tokens = canvas.tokens.controlled - .filter(it => it.actor.id == actor.id) + .filter(it => it.actor.id == actor.id) return tokens[0] } return undefined @@ -881,10 +881,10 @@ export class RdDUtility { /* -------------------------------------------- */ static afficherHeuresChanceMalchance(heureNaissance) { if (game.user.isGM) { - const heure = RdDTimestamp.findHeure(heureNaissance - 1); + const heure = RdDTimestamp.findHeure(heureNaissance) if (heureNaissance && heure) { - let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance); - const current = game.system.rdd.calendrier.heureCourante(); + const ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance) + const current = game.system.rdd.calendrier.heureCourante() ChatMessage.create({ content: `A l'heure de ${current.label}, le modificateur de Chance/Malchance est de ${Misc.toSignedString(ajustement)} pour l'heure de naissance ${heure.label}.`, whisper: ChatUtility.getGMs() diff --git a/module/time/rdd-timestamp.js b/module/time/rdd-timestamp.js index 27a5a80f..b1cb827b 100644 --- a/module/time/rdd-timestamp.js +++ b/module/time/rdd-timestamp.js @@ -160,15 +160,21 @@ export class RdDTimestamp { } static findHeure(heure) { - heure = Grammar.toLowerCaseNoAccentNoSpace(heure); - let parHeureOuLabel = DEFINITION_HEURES.filter(it => Grammar.toLowerCaseNoAccentNoSpace(it.label) == heure || it.heure == Misc.modulo(parseInt(heure), RDD_HEURES_PAR_JOUR)); - if (parHeureOuLabel.length == 1) { - return parHeureOuLabel[0]; + let filtered + if (Number.isInteger(Number(heure))) { + filtered = DEFINITION_HEURES.filter(it => it.heure == Misc.modulo(Number(heure) - 1, RDD_HEURES_PAR_JOUR)) } - let parLabelPartiel = DEFINITION_HEURES.filter(it => Grammar.toLowerCaseNoAccentNoSpace(it.label).includes(heure)); - if (parLabelPartiel.length > 0) { - parLabelPartiel.sort(Misc.ascending(h => h.label.length)); - return parLabelPartiel[0]; + else { + heure = Grammar.toLowerCaseNoAccentNoSpace(heure); + filtered = DEFINITION_HEURES.filter(it => Grammar.toLowerCaseNoAccentNoSpace(it.label) == heure || it.heure == Misc.modulo(parseInt(heure), RDD_HEURES_PAR_JOUR)); + } + if (filtered.length == 1) { + return filtered[0] + } + filtered = DEFINITION_HEURES.filter(it => Grammar.toLowerCaseNoAccentNoSpace(it.label).includes(heure)); + if (filtered.length > 0) { + filtered.sort(Misc.ascending(h => h.label.length)); + return filtered[0] } return undefined; } From 894d4f3941034159abb228c371f549b30073d8ec Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 3 Nov 2024 22:00:06 +0100 Subject: [PATCH 16/20] =?UTF-8?q?Fix:=20jet=20d'endurance=20feuille=20simp?= =?UTF-8?q?lifi=C3=A9e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog.md | 1 + module/actor/export-scriptarium/mapping.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 286af35e..9ee25acc 100644 --- a/changelog.md +++ b/changelog.md @@ -6,6 +6,7 @@ - Affichage du niveau d'esquive - Un clic sur l'initiative permet de lancer l'initiative - les boutons +/- pour la vie, l'endurance et la fatigue changent si on est à la valeur normale + - un clic sur l'endurance effectue un jet d'endurance - Fix - les achats des commerces sont de nouveau possibles - la commande /astro fonctionne de nouveau diff --git a/module/actor/export-scriptarium/mapping.js b/module/actor/export-scriptarium/mapping.js index c9161dba..8a4cd515 100644 --- a/module/actor/export-scriptarium/mapping.js +++ b/module/actor/export-scriptarium/mapping.js @@ -84,7 +84,7 @@ const MAPPING_BASE = [ { column: "malus_armure", getter: (actor, context) => Mapping.getMalusArmure(actor, context) }, { column: "reve_actuel", rollClass: 'roll-reve-actuel', colName: 'Rêve actuel', getter: (actor, context) => actor.system.reve.reve.value }, { column: "vie_actuel", rollClass: 'jet-vie', getter: (actor, context) => actor.system.sante.vie.value }, - { column: "endurance_actuel", rollClass: 'jet-vie', getter: (actor, context) => actor.system.sante.endurance.value }, + { column: "endurance_actuel", rollClass: 'jet-endurance', getter: (actor, context) => actor.system.sante.endurance.value }, { column: "esquive", getter: (actor, context) => Mapping.getEsquive(context) }, { column: "esquive_armure", getter: (actor, context) => Mapping.getEsquiveArmure(context) }, { column: "competences", getter: (actor, context) => Mapping.getCompetences(actor, CATEGORIES_COMPETENCES) }, From 09365eb7440221b4d30f97d333cfe44e62f34668 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 3 Nov 2024 23:31:56 +0100 Subject: [PATCH 17/20] Fix: reset des utilisations d'items --- changelog.md | 1 + module/actor.js | 2 +- module/actor/base-actor-reve.js | 9 +-- module/actor/base-actor-sang.js | 6 +- module/actor/base-actor.js | 9 +-- module/rdd-combat.js | 99 +++++++++++++++++++-------------- 6 files changed, 71 insertions(+), 55 deletions(-) diff --git a/changelog.md b/changelog.md index 9ee25acc..b5063c31 100644 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,7 @@ - Fix - les achats des commerces sont de nouveau possibles - la commande /astro fonctionne de nouveau + - le nombre d'utilisations d'items est réinitialisé à chaque round et fin de combat ## 12.0.16 - Le secret d'Astrobazzarh - Fix: les jets envoyés messages uniquement au MJ ne sont plus envoyés à tous les autres joueurs (et dupliqués) diff --git a/module/actor.js b/module/actor.js index b8e6cd10..75eec4e8 100644 --- a/module/actor.js +++ b/module/actor.js @@ -2615,7 +2615,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async resetItemUse() { - await this.setFlag(SYSTEM_RDD, 'itemUse', {}); + await this.unsetFlag(SYSTEM_RDD, 'itemUse'); } /* -------------------------------------------- */ diff --git a/module/actor/base-actor-reve.js b/module/actor/base-actor-reve.js index 21d2e608..53b5604b 100644 --- a/module/actor/base-actor-reve.js +++ b/module/actor/base-actor-reve.js @@ -78,8 +78,10 @@ export class RdDBaseActorReve extends RdDBaseActor { } async jetEndurance(resteEndurance = undefined) { return { jetEndurance: 0, sonne: false } } isDead() { return false } + isSonne() { return false } blessuresASoigner() { return [] } getEtatGeneral(options = { ethylisme: false }) { return 0 } + isActorCombat() { return true } async computeArmure(attackerRoll) { return this.getProtectionNaturelle() } async remiseANeuf() { } @@ -405,12 +407,7 @@ export class RdDBaseActorReve extends RdDBaseActor { return RdDItemArme.getCompetenceArme(arme, competenceName) } - verifierForceMin(item) { - } - /* -------------------------------------------- */ - async resetItemUse() { } - async incDecItemUse(itemId, inc = 1) { } - getItemUse(itemId) { return 0; } + verifierForceMin(item) { } /* -------------------------------------------- */ async encaisser() { await RdDEncaisser.encaisser(this) } diff --git a/module/actor/base-actor-sang.js b/module/actor/base-actor-sang.js index 48e5299a..26a58350 100644 --- a/module/actor/base-actor-sang.js +++ b/module/actor/base-actor-sang.js @@ -276,11 +276,11 @@ export class RdDBaseActorSang extends RdDBaseActorReve { ui.notifications.info(`${this.name} est hors combat, il ne reste donc pas sonné`); return; } - await this.setEffect(STATUSES.StatusStunned, sonne); + await this.setEffect(STATUSES.StatusStunned, sonne) } - getSonne() { - return this.getEffect(STATUSES.StatusStunned); + isSonne() { + return this.getEffect(STATUSES.StatusStunned) } isEffectAllowed(effectId) { return true } diff --git a/module/actor/base-actor.js b/module/actor/base-actor.js index b7553c68..7d8b64ab 100644 --- a/module/actor/base-actor.js +++ b/module/actor/base-actor.js @@ -205,11 +205,8 @@ export class RdDBaseActor extends Actor { /* -------------------------------------------- */ async onPreUpdateItem(item, change, options, id) { } - async onCreateItem(item, options, id) { } - async onDeleteItem(item, options, id) { } - async onUpdateActor(update, options, actorId) { } async onTimeChanging(oldTimestamp, newTimestamp) { @@ -708,5 +705,9 @@ export class RdDBaseActor extends Actor { } return undefined } - + async resetItemUse() { } + async incDecItemUse(itemId, inc = 1) { } + getItemUse(itemId) { return 0; } + async finDeRound(options = { terminer: false }) { } + isActorCombat() { return false } } \ No newline at end of file diff --git a/module/rdd-combat.js b/module/rdd-combat.js index 22cca49a..fb10350e 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -42,7 +42,8 @@ export class RdDCombatManager extends Combat { /* -------------------------------------------- */ Hooks.on("getCombatTrackerEntryContext", (html, options) => { RdDCombatManager.pushInitiativeOptions(html, options); }); Hooks.on("updateCombat", (combat, change, options, userId) => { RdDCombat.onUpdateCombat(combat, change, options, userId) }); - Hooks.on("preDeleteCombat", (combat, html, id) => { combat.onPreDeleteCombat() }); + Hooks.on("preDeleteCombat", (combat, html, id) => { combat.onPreDeleteCombat() }) + Hooks.on("deleteCombat", (combat, html, id) => { combat.onDeleteCombat() }) } /* -------------------------------------------- */ @@ -61,20 +62,31 @@ export class RdDCombatManager extends Combat { RdDEmpoignade.deleteAllEmpoignades() } } - - /* -------------------------------------------- */ - async finDeRound(options = { terminer: false }) { - this.turns.forEach(turn => turn.actor.resetItemUse()); - - for (let combatant of this.combatants) { - if (combatant.actor) { - await combatant.actor.finDeRound(options); - } - else { - ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur!`) + async onDeleteCombat() { + if (Misc.isFirstConnectedGM()) { + if (game.combats.size <= 1) { + game.actors.forEach(actor => actor.resetItemUse()) } } } + + /* -------------------------------------------- */ + async finDeRound(options = { terminer: false }) { + + for (let combatant of this.combatants) { + if (!combatant.actor) { + ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur!`) + } + else if (!combatant.actor.isActorCombat()) { + ui.notifications.warn(`Le combatant ${combatant.name} ne peut pas combattre!`) + } + else { + await combatant.actor.finDeRound(options) + await combatant.actor.resetItemUse() + } + } + } + static calculAjustementInit(actor, arme) { const efficacite = (arme?.system.magique) ? arme.system.ecaille_efficacite : 0 const etatGeneral = actor.getEtatGeneral() ?? 0 @@ -125,7 +137,6 @@ export class RdDCombatManager extends Combat { } } } - //console.log("Combatat", c); const roll = combatant.getInitiativeRoll(rollFormula); if (!roll.total) { await roll.evaluate(); @@ -236,29 +247,12 @@ export class RdDCombatManager extends Combat { return attaque; } - static listActionsCreature(competences) { - return competences - .filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it)) - .map(it => RdDItemCompetenceCreature.armeCreature(it)) - .filter(it => it != undefined); - } - - static listActionsPossessions(actor) { - return RdDCombatManager._indexActions(actor.getPossessions().map(p => { - return { - name: p.name, - action: 'possession', - system: { - competence: p.name, - possessionid: p.system.possessionid, - } - } - })); - } - /* -------------------------------------------- */ static listActionsCombat(combatant) { const actor = combatant.actor; + if (!actor.isActorCombat()) { + return + } let actions = RdDCombatManager.listActionsPossessions(actor); if (actions.length > 0) { return actions; @@ -281,6 +275,26 @@ export class RdDCombatManager extends Combat { return RdDCombatManager._indexActions(actions); } + static listActionsCreature(competences) { + return competences + .filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it)) + .map(it => RdDItemCompetenceCreature.armeCreature(it)) + .filter(it => it != undefined); + } + + static listActionsPossessions(actor) { + return RdDCombatManager._indexActions(actor.getPossessions().map(p => { + return { + name: p.name, + action: 'possession', + system: { + competence: p.name, + possessionid: p.system.possessionid, + } + } + })); + } + static _indexActions(actions) { for (let index = 0; index < actions.length; index++) { actions[index].index = index; @@ -457,8 +471,8 @@ export class RdDCombat { if (Misc.isFirstConnectedGM()) { let turn = combat.turns.find(t => t.token?.id == combat.current.tokenId); if (turn?.actor) { - RdDCombat.displayActorCombatStatus(combat, turn.actor, turn.token); // TODO Playaudio for player?? + RdDCombat.displayActorCombatStatus(combat, turn.actor, turn.token); } } } @@ -574,15 +588,15 @@ export class RdDCombat { static $extractAttackerTokenData(attacker, attackerTokenId) { const token = canvas.tokens.get(attackerTokenId); - return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(attackerTokenId, attacker) + return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(attackerTokenId, attacker) } - + static $extractDefenderTokenData(defender, defenderTokenId, target) { if (target) { return Targets.extractTokenData(target) } const token = canvas.tokens.get(defenderTokenId); - return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(defenderTokenId, defender) + return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(defenderTokenId, defender) } @@ -811,7 +825,7 @@ export class RdDCombat { dialog.render(true); } - + /* -------------------------------------------- */ _prepareAttaque(competence, arme) { let rollData = { @@ -825,7 +839,7 @@ export class RdDCombat { targetToken: this.defenderToken, essais: {} }; - + if (this.attacker.isCreatureEntite()) { RdDItemCompetenceCreature.setRollDataCreature(rollData); } @@ -978,7 +992,7 @@ export class RdDCombat { } /* -------------------------------------------- */ - _filterArmesParade(defender, competence) { + _filterArmesParade(defender, competence, arme) { let items = defender.items.filter(it => RdDItemArme.isArmeUtilisable(it) || RdDItemCompetenceCreature.isCompetenceParade(it)) items.forEach(item => item.system.nbUsage = defender.getItemUse(item.id)); // Ajout du # d'utilisation ce round @@ -1335,11 +1349,14 @@ export class RdDCombat { /* -------------------------------------------- */ static async displayActorCombatStatus(combat, actor, token) { + if (!actor?.isActorCombat()) { + return + } let formData = { combatId: combat._id, alias: token.name ?? actor.name, etatGeneral: actor.getEtatGeneral(), - isSonne: actor.getSonne(), + isSonne: actor.isSonne(), blessuresStatus: actor.computeResumeBlessure(), SConst: actor.getSConst(), actorId: actor.id, From bfe70c66347f4b7ee469b27f990470a2880302e5 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 3 Nov 2024 23:37:21 +0100 Subject: [PATCH 18/20] =?UTF-8?q?Fix=20difficult=C3=A9=20d=C3=A9fense=20di?= =?UTF-8?q?stance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog.md | 1 + templates/chat-demande-defense.html | 45 +++++++++++++++++------------ 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/changelog.md b/changelog.md index b5063c31..a4677db0 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,7 @@ - les achats des commerces sont de nouveau possibles - la commande /astro fonctionne de nouveau - le nombre d'utilisations d'items est réinitialisé à chaque round et fin de combat + - la difficulté de parade pour les armes à distances n'est plus indiquée ## 12.0.16 - Le secret d'Astrobazzarh - Fix: les jets envoyés messages uniquement au MJ ne sont plus envoyés à tous les autres joueurs (et dupliqués) diff --git a/templates/chat-demande-defense.html b/templates/chat-demande-defense.html index 1260e009..ece0c693 100644 --- a/templates/chat-demande-defense.html +++ b/templates/chat-demande-defense.html @@ -20,45 +20,54 @@ {{#if essais.defense}} {{#unless essais.defenseChance}} {{#if (eq defender.type 'personnage')}} - - Faire appel à la chance - -
+ + Faire appel à la chance + +
{{/if}} - {{#if (eq defender.type 'personnage')}} - {{#if (gt defender.system.compteurs.destinee.value 0)}} + {{#if (and (eq defender.type 'personnage') (gt defender.system.compteurs.destinee.value 0))}} Utiliser la destinée
{{/if}} - {{/if}} {{/unless}} {{else}} + {{log 'defense' attaqueArme attaqueCategorie this}} {{#each armes as |arme key|}} - Parer avec {{arme.name}} à {{../diffLibre }}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}} + Parer avec {{arme.name}} + {{#if (or (eq ../attaqueCategorie 'tir') (eq ../attaqueCategorie 'lancer'))}} + (difficulté à déterminer) + {{else}}à {{../diffLibre }} + {{/if}} + {{#if arme.system.nbUsage}}(Utilisations : {{arme.system.nbUsage}}){{/if}}
- {{/each}} - {{#if mainsNues}} + {{/each}} + {{#if mainsNues}} - Parer à mains nues à {{diffLibre}}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}} - -
+ data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}' + data-armeid='{{arme._id}}' data-competence='{{arme.system.competence}}'> + Parer à mains nues à {{diffLibre}}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}} + +
{{/if}} {{#if (ne attaqueCategorie 'tir')}} - {{#each esquives as |esquive key|}} + {{#each esquives as |esquive key|}} - {{esquive.name}} à {{../diffLibre}} {{#if esquive.system.nbUsage}} (Utilisations : {{esquive.system.nbUsage}}){{/if}} + {{esquive.name}} + {{#if (or (eq ../attaqueCategorie 'tir') (eq ../attaqueCategorie 'lancer'))}} + (difficulté à déterminer) + {{else}}à {{../diffLibre }} + {{/if}} + {{#if esquive.system.nbUsage}}(Utilisations : {{esquive.system.nbUsage}}){{/if}}
{{/each}} From 70198a572747265be47263eb81ed14a6a891f0eb Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Mon, 4 Nov 2024 00:19:21 +0100 Subject: [PATCH 19/20] =?UTF-8?q?Correction=20des=20armes=20de=20d=C3=A9fe?= =?UTF-8?q?nse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog.md | 2 ++ module/item-arme.js | 54 ++++++++++++++++++++--------- module/rdd-combat.js | 19 +++++----- templates/chat-demande-defense.html | 10 +++--- 4 files changed, 56 insertions(+), 29 deletions(-) diff --git a/changelog.md b/changelog.md index a4677db0..b696159d 100644 --- a/changelog.md +++ b/changelog.md @@ -12,6 +12,8 @@ - la commande /astro fonctionne de nouveau - le nombre d'utilisations d'items est réinitialisé à chaque round et fin de combat - la difficulté de parade pour les armes à distances n'est plus indiquée + - les propositions d'armes de parade sont corrigées +- Ajout d'un indicateur pour les armes de parade nécessitant une significative ## 12.0.16 - Le secret d'Astrobazzarh - Fix: les jets envoyés messages uniquement au MJ ne sont plus envoyés à tous les autres joueurs (et dupliqués) diff --git a/module/item-arme.js b/module/item-arme.js index 25cb4dd4..86255aa6 100644 --- a/module/item-arme.js +++ b/module/item-arme.js @@ -81,37 +81,59 @@ export class RdDItemArme extends Item { /* -------------------------------------------- */ static getCategorieParade(armeData) { if (armeData.system.categorie_parade) { - return armeData.system.categorie_parade; + return armeData.system.categorie_parade } // pour compatibilité avec des personnages existants if (armeData.type == ITEM_TYPES.competencecreature || armeData.system.categorie == 'creature') { - return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : ''); + return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : '') } if (!armeData.type.match(/arme|competencecreature/)) { - return ''; + return '' } if (armeData.system.competence == undefined) { return ITEM_TYPES.competencecreature; } let compname = armeData.system.competence.toLowerCase(); - if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return ''; + if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) { + return '' + } - if (compname.match('hache')) return 'haches'; - if (compname.match('hast')) return 'hast'; - if (compname.match('lance')) return 'lances'; - if (compname.match('bouclier')) return 'boucliers'; - if (compname.match('masse')) return 'masses'; + if (compname.match('hache')) return 'haches' + if (compname.match('hast')) return 'hast' + if (compname.match('lance')) return 'lances' + if (compname.match('bouclier')) return 'boucliers' + if (compname.match('masse')) return 'masses' if (compname.match('epée') || compname.match('épée')) { if (armeData.name.toLowerCase().match(/(gnome)/)) - return 'epees-courtes'; + return 'epees-courtes' if (armeData.name.toLowerCase().match(/((e|é)pée dragone|esparlongue|demi-dragonne)/)) - return 'epees-longues'; - return 'epees-lourdes'; + return 'epees-longues' + return 'epees-lourdes' } if (compname.match('dague')) { - return 'dagues'; + return 'dagues' + } + return 'sans-armes' + } + + static defenseArmeParade(armeAttaque, armeParade) { + const defCategory = RdDItemArme.getCategorieParade(armeParade) + if (defCategory == 'bouclier') { + return 'norm' + } + if (armeAttaque.system.competence.toLowerCase().match(/(fléau)/)) { + return '' + } + if (armeParade.system.tir) { + return '' + } + const attCategory = RdDItemArme.getCategorieParade(armeAttaque) + switch (attCategory) { + case 'armes-naturelles': case 'sans-armes': + return defCategory == 'sans-armes' ? 'norm' : '' + default: + return RdDItemArme.needParadeSignificative(armeAttaque, armeParade) ? 'sign' : 'norm' } - return 'sans-armes'; } /* -------------------------------------------- */ @@ -120,8 +142,8 @@ export class RdDItemArme extends Item { return false; } // categories d'armes à la parade (cf. page 115 ) - let attCategory = RdDItemArme.getCategorieParade(armeAttaque); - let defCategory = RdDItemArme.getCategorieParade(armeParade); + const attCategory = RdDItemArme.getCategorieParade(armeAttaque) + const defCategory = RdDItemArme.getCategorieParade(armeParade) // bouclier et mêmes catégorie: peuvent se parer sans difficulté if (defCategory == 'boucliers') { return false; diff --git a/module/rdd-combat.js b/module/rdd-combat.js index fb10350e..35b6bf9f 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -932,7 +932,7 @@ export class RdDCombat { // # utilisation esquive const corpsACorps = this.defender.getCompetenceCorpsACorps({ onMessage: it => console.info(it, this.defender) }); const esquives = foundry.utils.duplicate(this.defender.getCompetencesEsquive()) - esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0); + esquives.forEach(e => e.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0); const paramChatDefense = { passeArme: attackerRoll.passeArme, @@ -993,19 +993,20 @@ export class RdDCombat { /* -------------------------------------------- */ _filterArmesParade(defender, competence, arme) { - let items = defender.items.filter(it => RdDItemArme.isArmeUtilisable(it) || RdDItemCompetenceCreature.isCompetenceParade(it)) - items.forEach(item => item.system.nbUsage = defender.getItemUse(item.id)); // Ajout du # d'utilisation ce round + let defenses = defender.items.filter(it => RdDItemArme.isArmeUtilisable(it) || RdDItemCompetenceCreature.isCompetenceParade(it)) + defenses = foundry.utils.duplicate(defenses) + defenses.forEach(armeDefense => { + // Ajout du # d'utilisation ce round + armeDefense.nbUsage = defender.getItemUse(armeDefense.id) + armeDefense.typeParade = RdDItemArme.defenseArmeParade(arme, armeDefense) + }) switch (competence.system.categorie) { case 'tir': case 'lancer': - return items.filter(item => RdDItemArme.getCategorieParade(item) == 'boucliers') + return defenses.filter(armeDefense => RdDItemArme.getCategorieParade(armeDefense) == 'boucliers') default: - // Le fléau ne peut être paré qu’au bouclier p115 - if (competence.name == "Fléau") { - return items.filter(item => RdDItemArme.getCategorieParade(item) == 'boucliers') - } - return items.filter(item => RdDItemArme.getCategorieParade(item)); + return defenses.filter(armeDefense => armeDefense.typeParade != '') } } diff --git a/templates/chat-demande-defense.html b/templates/chat-demande-defense.html index ece0c693..4a8a0bd7 100644 --- a/templates/chat-demande-defense.html +++ b/templates/chat-demande-defense.html @@ -35,7 +35,6 @@ {{/if}} {{/unless}} {{else}} - {{log 'defense' attaqueArme attaqueCategorie this}} {{#each armes as |arme key|}} ×½ + {{/if}} + {{#if arme.nbUsage}}(Utilisations : {{arme.nbUsage}}){{/if}}
{{/each}} @@ -53,7 +55,7 @@ - Parer à mains nues à {{diffLibre}}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}} + Parer à mains nues à {{diffLibre}}{{#if arme.nbUsage}} (Utilisations : {{arme.nbUsage}}){{/if}}
{{/if}} @@ -67,7 +69,7 @@ (difficulté à déterminer) {{else}}à {{../diffLibre }} {{/if}} - {{#if esquive.system.nbUsage}}(Utilisations : {{esquive.system.nbUsage}}){{/if}} + {{#if esquive.nbUsage}}(Utilisations : {{esquive.nbUsage}}){{/if}}
{{/each}} From ed222c7b6da99c87f7d3e09ceebd8d249c8c3b27 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Mon, 4 Nov 2024 00:20:12 +0100 Subject: [PATCH 20/20] Version 12.0.18 --- system.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system.json b/system.json index c2c2c221..25c0e64d 100644 --- a/system.json +++ b/system.json @@ -1,8 +1,8 @@ { "id": "foundryvtt-reve-de-dragon", "title": "Rêve de Dragon", - "version": "12.0.17", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.17.zip", + "version": "12.0.18", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.18.zip", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json", "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md", "compatibility": {