Version 12.0.16 - Le secret d'Astrobazzarh #718
| @@ -1,4 +1,12 @@ | |||||||
| # 12.0 | # 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 | ||||||
|  | - Ajout d'une option pour la localisation des blessures | ||||||
|  |  | ||||||
| ## 12.0.15 - Le messager d'Astrobazzarh | ## 12.0.15 - Le messager d'Astrobazzarh | ||||||
| - Correction des faces de dés personalisés dice-so-nice | - Correction des faces de dés personalisés dice-so-nice | ||||||
| - Les messages de maladies ne sont plus publics | - Les messages de maladies ne sont plus publics | ||||||
|   | |||||||
| @@ -220,18 +220,18 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { | |||||||
|     // Points de reve actuel |     // Points de reve actuel | ||||||
|     this.html.find('.roll-reve-actuel').click(async event => this.actor.rollCarac('reve-actuel', true)) |     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('.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 |     // Initiative pour l'arme | ||||||
|     this.html.find('.arme-initiative a').click(async event => { |     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) { |       if (combatant) { | ||||||
|         let action = this._getEventArmeCombat(event); |         RdDCombatManager.rollInitiativeAction(combatant._id, this._getEventArmeCombat(event)); | ||||||
|         RdDCombatManager.rollInitiativeAction(combatant._id, action); |  | ||||||
|       } else { |       } else { | ||||||
|         ui.notifications.info("Impossible de lancer l'initiative sans être dans un combat."); |         ui.notifications.info("Impossible de lancer l'initiative sans être dans un combat."); | ||||||
|       } |       } | ||||||
|     }); |     }) | ||||||
|     // Display TMR |     // Display TMR | ||||||
|  |  | ||||||
|     this.html.find('.button-tmr').click(async event => this.actor.displayTMR("normal")) |     this.html.find('.button-tmr').click(async event => this.actor.displayTMR("normal")) | ||||||
|   | |||||||
| @@ -1548,7 +1548,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { |   async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { | ||||||
|     if (!Misc.firstConnectedGM()){ |     if (!Misc.isFirstConnectedGM()){ | ||||||
|       return |       return | ||||||
|     } |     } | ||||||
|     hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM) |     hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM) | ||||||
| @@ -3011,7 +3011,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async onCreateOwnedDraconique(item, options, id) { |   async onCreateOwnedDraconique(item, options, id) { | ||||||
|     if (Misc.isUniqueConnectedGM()) { |     if (Misc.isFirstConnectedGM()) { | ||||||
|       let draconique = Draconique.all().find(it => it.match(item)); |       let draconique = Draconique.all().find(it => it.match(item)); | ||||||
|       if (draconique) { |       if (draconique) { | ||||||
|         await draconique.onActorCreateOwned(this, item) |         await draconique.onActorCreateOwned(this, item) | ||||||
| @@ -3023,7 +3023,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async onDeleteOwnedDraconique(item, options, id) { |   async onDeleteOwnedDraconique(item, options, id) { | ||||||
|     if (Misc.isUniqueConnectedGM()) { |     if (Misc.isFirstConnectedGM()) { | ||||||
|       let draconique = Draconique.all().find(it => it.match(item)); |       let draconique = Draconique.all().find(it => it.match(item)); | ||||||
|       if (draconique) { |       if (draconique) { | ||||||
|         await draconique.onActorDeleteOwned(this, item) |         await draconique.onActorDeleteOwned(this, item) | ||||||
| @@ -3033,7 +3033,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async onDeleteOwnedCaseTmr(item, options, id) { |   async onDeleteOwnedCaseTmr(item, options, id) { | ||||||
|     if (Misc.isUniqueConnectedGM()) { |     if (Misc.isFirstConnectedGM()) { | ||||||
|       let draconique = Draconique.all().find(it => it.isCase(item)); |       let draconique = Draconique.all().find(it => it.isCase(item)); | ||||||
|       if (draconique) { |       if (draconique) { | ||||||
|         await draconique.onActorDeleteCaseTmr(this, item) |         await draconique.onActorDeleteCaseTmr(this, item) | ||||||
|   | |||||||
| @@ -327,14 +327,15 @@ export class RdDBaseActorReve extends RdDBaseActor { | |||||||
|     const competence = this.getCompetence(idOrName); |     const competence = this.getCompetence(idOrName); | ||||||
|     let rollData = { carac: this.system.carac, competence: competence, arme: options.arme } |     let rollData = { carac: this.system.carac, competence: competence, arme: options.arme } | ||||||
|     if (competence.type == ITEM_TYPES.competencecreature) { |     if (competence.type == ITEM_TYPES.competencecreature) { | ||||||
|  |       const token = RdDUtility.getSelectedToken(this) | ||||||
|       const arme = RdDItemCompetenceCreature.armeCreature(competence) |       const arme = RdDItemCompetenceCreature.armeCreature(competence) | ||||||
|       if (arme && options.tryTarget && Targets.hasTargets()) { |       if (arme && options.tryTarget && Targets.hasTargets()) { | ||||||
|         Targets.selectOneToken(target => { |         Targets.selectOneTargetToken(target => { | ||||||
|           if (arme.action == "possession") { |           if (arme.action == "possession") { | ||||||
|             RdDPossession.onAttaquePossession(target, this, competence) |             RdDPossession.onAttaquePossession(target, this, competence) | ||||||
|           } |           } | ||||||
|           else { |           else { | ||||||
|             RdDCombat.rddCombatTarget(target, this).attaque(competence, arme) |             RdDCombat.rddCombatTarget(target, this, token).attaque(competence, arme) | ||||||
|           } |           } | ||||||
|         }); |         }); | ||||||
|         return; |         return; | ||||||
| @@ -364,7 +365,8 @@ export class RdDBaseActorReve extends RdDBaseActor { | |||||||
|    * @param {*} categorieArme catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession |    * @param {*} categorieArme catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession | ||||||
|    * @returns  |    * @returns  | ||||||
|    */ |    */ | ||||||
|   rollArme(arme, categorieArme = "competence") { |   rollArme(arme, categorieArme, token) { | ||||||
|  |     token = token ?? RdDUtility.getSelectedToken(this) | ||||||
|     const compToUse = this.$getCompetenceArme(arme, categorieArme) |     const compToUse = this.$getCompetenceArme(arme, categorieArme) | ||||||
|     if (!RdDItemArme.isArmeUtilisable(arme)) { |     if (!RdDItemArme.isArmeUtilisable(arme)) { | ||||||
|       ui.notifications.warn(`Arme inutilisable: ${arme.name} a une résistance de 0 ou moins`) |       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 |       return | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Targets.selectOneToken(target => { |     Targets.selectOneTargetToken(target => { | ||||||
|       if (Targets.isTargetEntite(target)) { |       if (Targets.isTargetEntite(target)) { | ||||||
|         ui.notifications.warn(`Vous ne pouvez pas attaquer une entité non incarnée avec votre ${arme.name}!!!!`); |         ui.notifications.warn(`Vous ne pouvez pas attaquer une entité non incarnée avec votre ${arme.name}!!!!`); | ||||||
|         return |         return | ||||||
| @@ -395,7 +397,7 @@ export class RdDBaseActorReve extends RdDBaseActor { | |||||||
|       if (competence.isCompetencePossession()) { |       if (competence.isCompetencePossession()) { | ||||||
|         return RdDPossession.onAttaquePossession(target, this, competence); |         return RdDPossession.onAttaquePossession(target, this, competence); | ||||||
|       } |       } | ||||||
|       RdDCombat.rddCombatTarget(target, this).attaque(competence, arme); |       RdDCombat.rddCombatTarget(target, this, token).attaque(competence, arme); | ||||||
|     }) |     }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -413,48 +415,47 @@ export class RdDBaseActorReve extends RdDBaseActor { | |||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async encaisser() { await RdDEncaisser.encaisser(this) } |   async encaisser() { await RdDEncaisser.encaisser(this) } | ||||||
|  |  | ||||||
|   async encaisserDommages(rollData, attacker = undefined, show = undefined) { |   async encaisserDommages(rollData, attacker = undefined, show = undefined, attackerToken = undefined, defenderToken = undefined) { | ||||||
|     if (attacker && !await attacker.accorder(this, 'avant-encaissement')) { |     if (attacker && !await attacker.accorder(this, 'avant-encaissement')) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     const armure = await this.computeArmure(rollData); |     const armure = await this.computeArmure(rollData); | ||||||
|     if (ReglesOptionnelles.isUsing('validation-encaissement-gr')) { |     if (ReglesOptionnelles.isUsing('validation-encaissement-gr')) { | ||||||
|       await this.encaisserDommagesValidationGR(rollData, armure, attacker?.id, show); |       await this.encaisserDommagesValidationGR(rollData, armure, show, attackerToken, defenderToken); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|       const jet = await RdDUtility.jetEncaissement(rollData, armure, { showDice: SHOW_DICE }); |       const jet = await RdDUtility.jetEncaissement(this, rollData, armure, { showDice: SHOW_DICE }); | ||||||
|       await this.$onEncaissement(jet, show, attacker); |       await this.$onEncaissement(jet, show, attackerToken, defenderToken) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async encaisserDommagesValidationGR(rollData, armure, attackerId, show) { |   async encaisserDommagesValidationGR(rollData, armure, show, attackerToken, defenderToken) { | ||||||
|     if (!game.user.isGM) { |     if (!game.user.isGM) { | ||||||
|       RdDBaseActor.remoteActorCall({ |       RdDBaseActor.remoteActorCall({ | ||||||
|         tokenId: this.token?.id, |         tokenId: this.token?.id, | ||||||
|         actorId: this.id, |         actorId: this.id, | ||||||
|         method: 'encaisserDommagesValidationGR', |         method: 'encaisserDommagesValidationGR', | ||||||
|         args: [rollData, armure, attackerId, show] |         args: [rollData, armure, show, attackerToken, defenderToken] | ||||||
|       }); |       }) | ||||||
|     } else { |     } else { | ||||||
|       const attacker = game.actors.get(attackerId); |  | ||||||
|       DialogValidationEncaissement.validerEncaissement(this, rollData, armure, |       DialogValidationEncaissement.validerEncaissement(this, rollData, armure, | ||||||
|         jet => this.$onEncaissement(jet, show, attacker)); |         jet => this.$onEncaissement(jet, show, attackerToken, defenderToken)); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async $onEncaissement(jet, show, attacker) { |   async $onEncaissement(jet, show, attackerToken, defenderToken) { | ||||||
|     await this.onAppliquerJetEncaissement(jet, attacker); |     await this.onAppliquerJetEncaissement(jet, attackerToken); | ||||||
|     await this.$afficherEncaissement(jet, show); |     await this.$afficherEncaissement(jet, show, defenderToken); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async onAppliquerJetEncaissement(encaissement, attacker) { } |   async onAppliquerJetEncaissement(encaissement, attackerToken) { } | ||||||
|  |  | ||||||
|   async $afficherEncaissement(encaissement, show) { |   async $afficherEncaissement(encaissement, show, defenderToken) { | ||||||
|     foundry.utils.mergeObject(encaissement, { |     foundry.utils.mergeObject(encaissement, { | ||||||
|       alias: this.name, |       alias: defenderToken?.name ?? this.name, | ||||||
|       hasPlayerOwner: this.hasPlayerOwner, |       hasPlayerOwner: this.hasPlayerOwner, | ||||||
|       show: show ?? {} |       show: show ?? {} | ||||||
|     }); |     }, {overwrite: false}); | ||||||
|  |  | ||||||
|     await ChatUtility.createChatWithRollMode( |     await ChatUtility.createChatWithRollMode( | ||||||
|       { |       { | ||||||
|   | |||||||
| @@ -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 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 perteVie = await this.santeIncDec("vie", -encaissement.vie); | ||||||
|     const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, blessure?.isCritique()); |     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) return; | ||||||
|     if (encaissement.gravite > 0) { |     if (encaissement.gravite > 0) { | ||||||
|       while (this.countBlessures(it => it.system.gravite == encaissement.gravite) >= RdDItemBlessure.maxBlessures(encaissement.gravite) && encaissement.gravite <= 6) { |       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 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()) { |     if (blessure.isCritique()) { | ||||||
|       encaissement.endurance = endActuelle; |       encaissement.endurance = endActuelle; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -218,7 +218,7 @@ export class RdDBaseActor extends Actor { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   async creerObjetParMJ(object) { |   async creerObjetParMJ(object) { | ||||||
|     if (!Misc.isUniqueConnectedGM()) { |     if (!Misc.isFirstConnectedGM()) { | ||||||
|       RdDBaseActor.remoteActorCall({ |       RdDBaseActor.remoteActorCall({ | ||||||
|         tokenId: this.token?.id, |         tokenId: this.token?.id, | ||||||
|         actorId: this.id, |         actorId: this.id, | ||||||
| @@ -335,7 +335,7 @@ export class RdDBaseActor extends Actor { | |||||||
|       ui.notifications.info("Inutile de se vendre à soi-même"); |       ui.notifications.info("Inutile de se vendre à soi-même"); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     if (!Misc.isUniqueConnectedGM()) { |     if (!Misc.isFirstConnectedGM()) { | ||||||
|       RdDBaseActor.remoteActorCall({ |       RdDBaseActor.remoteActorCall({ | ||||||
|         actorId: achat.vendeurId ?? achat.acheteurId, |         actorId: achat.vendeurId ?? achat.acheteurId, | ||||||
|         method: 'achatVente', |         method: 'achatVente', | ||||||
|   | |||||||
| @@ -74,7 +74,7 @@ export class RdDEntite extends RdDBaseActorReve { | |||||||
|     return [STATUSES.StatusComma].includes(effectId); |     return [STATUSES.StatusComma].includes(effectId); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async onAppliquerJetEncaissement(encaissement, attacker) { |   async onAppliquerJetEncaissement(encaissement, attackerToken) { | ||||||
|     const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance); |     const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance); | ||||||
|     foundry.utils.mergeObject(encaissement, { |     foundry.utils.mergeObject(encaissement, { | ||||||
|       resteEndurance: perteEndurance.newValue, |       resteEndurance: perteEndurance.newValue, | ||||||
|   | |||||||
| @@ -327,7 +327,8 @@ export class Mapping { | |||||||
|     const txtByCategories = Object.values(byCategories) |     const txtByCategories = Object.values(byCategories) | ||||||
|       .map(it => it.competencesParNiveau) |       .map(it => it.competencesParNiveau) | ||||||
|       .map(byNiveau => { |       .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) { |         if (niveaux.length == 0) { | ||||||
|           return '' |           return '' | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ export class ChatUtility { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   static onRemoveMessages(socketData) { |   static onRemoveMessages(socketData) { | ||||||
|     if (Misc.isUniqueConnectedGM()) { |     if (Misc.isFirstConnectedGM()) { | ||||||
|       if (socketData.part) { |       if (socketData.part) { | ||||||
|         const toDelete = game.messages.filter(it => it.content.includes(socketData.part)); |         const toDelete = game.messages.filter(it => it.content.includes(socketData.part)); | ||||||
|         toDelete.forEach(it => it.delete()); |         toDelete.forEach(it => it.delete()); | ||||||
| @@ -63,7 +63,7 @@ export class ChatUtility { | |||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|  |  | ||||||
|   static removeMessages(socketData) { |   static removeMessages(socketData) { | ||||||
|     if (Misc.isUniqueConnectedGM()) { |     if (Misc.isFirstConnectedGM()) { | ||||||
|       ChatUtility.onRemoveMessages(socketData); |       ChatUtility.onRemoveMessages(socketData); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
| @@ -161,7 +161,7 @@ export class ChatUtility { | |||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   static handleGMChatMessage(socketData) { |   static handleGMChatMessage(socketData) { | ||||||
|     console.log("blindMessageToGM", socketData); |     console.log("blindMessageToGM", socketData); | ||||||
|     if (Misc.firstConnectedGM()) { |     if (Misc.isFirstConnectedGM()) { | ||||||
|       ChatMessage.create({ |       ChatMessage.create({ | ||||||
|         user: game.user.id, |         user: game.user.id, | ||||||
|         whisper: ChatUtility.getGMs(), |         whisper: ChatUtility.getGMs(), | ||||||
|   | |||||||
| @@ -8,14 +8,13 @@ import { RdDUtility } from "./rdd-utility.js"; | |||||||
| export class DialogValidationEncaissement extends Dialog { | export class DialogValidationEncaissement extends Dialog { | ||||||
|  |  | ||||||
|   static async validerEncaissement(actor, rollData, armure, onEncaisser) { |   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', { |     const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html', { | ||||||
|       actor: actor, |       actor: actor, | ||||||
|       rollData: rollData, |       rollData: rollData, | ||||||
|       encaissement: encaissement |       encaissement: encaissement | ||||||
|     }); |     }); | ||||||
|     const dialog = new DialogValidationEncaissement(html, actor, rollData, armure, encaissement, onEncaisser); |     new DialogValidationEncaissement(html, actor, rollData, armure, encaissement, onEncaisser).render(true); | ||||||
|     dialog.render(true); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
| @@ -56,14 +55,14 @@ export class DialogValidationEncaissement extends Dialog { | |||||||
|     this.html = html; |     this.html = html; | ||||||
|     this.html.find('input.encaissement-roll-result').keyup(async event => { |     this.html.find('input.encaissement-roll-result').keyup(async event => { | ||||||
|       this.forceDiceResult.total = event.currentTarget.value; |       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-total').text(this.encaissement.total); | ||||||
|       this.html.find('label.encaissement-blessure').text(this.encaissement.blessures) |       this.html.find('label.encaissement-blessure').text(this.encaissement.blessures) | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async onValider() { |   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) |     this.onEncaisser(this.encaissement) | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -190,7 +190,7 @@ export class RdDItemCompetence extends Item { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   static isNiveauBase(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); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   | |||||||
| @@ -267,10 +267,17 @@ export class RdDItemSheet extends ItemSheet { | |||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   /** @override */ |   /** @override */ | ||||||
|   _updateObject(event, formData) { |   _updateObject(event, formData) { | ||||||
|     if (this.item.type == 'sort') { |     switch (this.item.type) { | ||||||
|       // Données de bonus de cases ? |       case ITEM_TYPES.sort: | ||||||
|       formData['system.bonuscase'] = RdDItemSort.buildBonuscaseFromArrays(formData.bonusValue, formData.caseValue); |         // 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); |     return this.item.update(formData); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -195,7 +195,7 @@ export class Misc { | |||||||
|         return document |         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 document | ||||||
|     } |     } | ||||||
|     return undefined |     return undefined | ||||||
| @@ -206,14 +206,14 @@ export class Misc { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   static isOwnerPlayerOrUniqueConnectedGM(actor) { |   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 |    * @returns true pour un seul utilisateur: le premier GM connecté par ordre d'id | ||||||
|    */ |    */ | ||||||
|   static isUniqueConnectedGM() { |   static isFirstConnectedGM() { | ||||||
|     return game.user.id == Misc.firstConnectedGMId(); |     return game.user == Misc.firstConnectedGM(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static firstConnectedGMId() { |   static firstConnectedGMId() { | ||||||
|   | |||||||
| @@ -53,7 +53,7 @@ export class RdDCombatManager extends Combat { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async onPreDeleteCombat() { |   async onPreDeleteCombat() { | ||||||
|     if (Misc.isUniqueConnectedGM()) { |     if (Misc.isFirstConnectedGM()) { | ||||||
|       await this.finDeRound({ terminer: true }) |       await this.finDeRound({ terminer: true }) | ||||||
|       ChatUtility.removeChatMessageContaining(`<div data-combatid="${this.id}" data-combatmessage="actor-turn-summary">`) |       ChatUtility.removeChatMessageContaining(`<div data-combatid="${this.id}" data-combatmessage="actor-turn-summary">`) | ||||||
|       game.messages.filter(m => ChatUtility.getMessageData(m, 'attacker-roll') != undefined && ChatUtility.getMessageData(m, 'defender-roll') != undefined) |       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() { |   static processPremierRoundInit() { | ||||||
|     // Check if we have the whole init ! |     // 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); |       let initMissing = game.combat.combatants.find(it => !it.initiative); | ||||||
|       if (!initMissing) { // Premier round ! |       if (!initMissing) { // Premier round ! | ||||||
|         for (let combatant of game.combat.combatants) { |         for (let combatant of game.combat.combatants) { | ||||||
| @@ -454,10 +454,10 @@ export class RdDCombat { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   static combatNouveauTour(combat) { |   static combatNouveauTour(combat) { | ||||||
|     if (Misc.isUniqueConnectedGM()) { |     if (Misc.isFirstConnectedGM()) { | ||||||
|       let turn = combat.turns.find(t => t.token?.id == combat.current.tokenId); |       let turn = combat.turns.find(t => t.token?.id == combat.current.tokenId); | ||||||
|       if (turn?.actor) { |       if (turn?.actor) { | ||||||
|         RdDCombat.displayActorCombatStatus(combat, turn.actor, turn.token.id); |         RdDCombat.displayActorCombatStatus(combat, turn.actor, turn.token); | ||||||
|         // TODO Playaudio for player?? |         // TODO Playaudio for player?? | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @@ -469,52 +469,51 @@ export class RdDCombat { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   static rddCombatTarget(target, attacker) { |   static rddCombatTarget(target, attacker, attackerToken) { | ||||||
|     const defender = target?.actor; |     return new RdDCombat(attacker, attackerToken?.id, target?.actor, target?.id, target) | ||||||
|     const defenderTokenId = target?.id; |  | ||||||
|     return new RdDCombat(attacker, defender, defenderTokenId, target) |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   static rddCombatForAttackerAndDefender(attackerId, defenderTokenId) { |   static rddCombatForAttackerAndDefender(attackerId, attackerTokenId, defenderTokenId) { | ||||||
|     const attacker = game.actors.get(attackerId); |     const attacker = game.actors.get(attackerId) | ||||||
|     let defender = defenderTokenId ? canvas.tokens.get(defenderTokenId)?.actor : undefined; |     const defenderToken = defenderTokenId ? canvas.tokens.get(defenderTokenId) : undefined | ||||||
|  |     let defender = defenderToken?.actor; | ||||||
|     let target = undefined |     let target = undefined | ||||||
|     if (!defenderTokenId || !defender) { |     if (!defenderTokenId || !defender) { | ||||||
|       console.warn(`RdDCombat.rddCombatForAttackerAndDefender: appel avec defenderTokenId ${defenderTokenId} incorrect, ou pas de defender correspondant`); |       console.warn(`RdDCombat.rddCombatForAttackerAndDefender: appel avec defenderTokenId ${defenderTokenId} incorrect, ou pas de defender correspondant`); | ||||||
|       target = Targets.getTarget() |       target = Targets.getTarget() | ||||||
|       if (!target) { |       if (!target) { | ||||||
|         return; |         return | ||||||
|       } |       } | ||||||
|       defenderTokenId = target.id; |       defenderTokenId = target.id; | ||||||
|       defender = target.actor; |       defender = target.actor; | ||||||
|       if (!defenderTokenId || !defender) { |       if (!defenderTokenId || !defender) { | ||||||
|         return; |         return | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     return new RdDCombat(attacker, defender, defenderTokenId, target) |     return new RdDCombat(attacker, attackerTokenId, defender, defenderTokenId, target) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   static onMsgEncaisser(msg) { |   static onMsgEncaisser(msg) { | ||||||
|     let defender = canvas.tokens.get(msg.defenderTokenId).actor; |  | ||||||
|     if (Misc.isOwnerPlayerOrUniqueConnectedGM()) { |     if (Misc.isOwnerPlayerOrUniqueConnectedGM()) { | ||||||
|       let attackerRoll = msg.attackerRoll; |       let attackerRoll = msg.attackerRoll; | ||||||
|       let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined; |       let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined; | ||||||
|  |       let defender = canvas.tokens.get(msg.defenderToken.id).actor; | ||||||
|  |  | ||||||
|       defender.encaisserDommages(attackerRoll, attacker); |       defender.encaisserDommages(attackerRoll, attacker, msg.attackerToken); | ||||||
|       const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.defenderTokenId); |       const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerToken.id, msg.defenderToken.id); | ||||||
|       rddCombat?.removeChatMessageActionsPasseArme(attackerRoll.passeArme); |       rddCombat?.removeChatMessageActionsPasseArme(attackerRoll.passeArme); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   static onMsgDefense(msg) { |   static onMsgDefense(msg) { | ||||||
|     let defenderToken = canvas.tokens.get(msg.defenderTokenId); |     let defenderToken = canvas.tokens.get(msg.defenderToken.id) | ||||||
|     if (defenderToken && Misc.isUniqueConnectedGM()) { |     if (defenderToken && Misc.isFirstConnectedGM()) { | ||||||
|       const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.defenderTokenId); |       const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerToken.id, msg.defenderToken.id) | ||||||
|       rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme); |       rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme) | ||||||
|       rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll); |       rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -545,6 +544,7 @@ export class RdDCombat { | |||||||
|       html.on("click", button, event => { |       html.on("click", button, event => { | ||||||
|         const rddCombat = RdDCombat.rddCombatForAttackerAndDefender( |         const rddCombat = RdDCombat.rddCombatForAttackerAndDefender( | ||||||
|           event.currentTarget.attributes['data-attackerId']?.value, |           event.currentTarget.attributes['data-attackerId']?.value, | ||||||
|  |           event.currentTarget.attributes['data-attackerTokenId']?.value, | ||||||
|           event.currentTarget.attributes['data-defenderTokenId']?.value); |           event.currentTarget.attributes['data-defenderTokenId']?.value); | ||||||
|         if (rddCombat) { |         if (rddCombat) { | ||||||
|           rddCombat.onEvent(button, event); |           rddCombat.onEvent(button, event); | ||||||
| @@ -560,22 +560,38 @@ export class RdDCombat { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   constructor(attacker, defender, defenderTokenId, target) { |   constructor(attacker, attackerTokenId, defender, defenderTokenId, target) { | ||||||
|     this.attacker = attacker |     this.attacker = attacker | ||||||
|     this.defender = defender |     this.defender = defender | ||||||
|     this.target = target |     this.target = target | ||||||
|     this.attackerId = this.attacker.id |     this.attackerId = this.attacker.id | ||||||
|     this.defenderId = this.defender.id |     this.defenderId = this.defender.id | ||||||
|  |     this.attackerTokenId = attackerTokenId | ||||||
|     this.defenderTokenId = defenderTokenId |     this.defenderTokenId = defenderTokenId | ||||||
|  |     this.attackerToken = RdDCombat.$extractAttackerTokenData(attacker, attackerTokenId) | ||||||
|  |     this.defenderToken = RdDCombat.$extractDefenderTokenData(defender, defenderTokenId, 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(defenderTokenId); | ||||||
|  |     return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(defenderTokenId, defender)  | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async onEvent(button, event) { |   async onEvent(button, event) { | ||||||
|     const chatMessage = ChatUtility.getChatMessage(event); |     const chatMessage = ChatUtility.getChatMessage(event); | ||||||
|     const defenderRoll = ChatUtility.getMessageData(chatMessage, 'defender-roll'); |     const defenderRoll = ChatUtility.getMessageData(chatMessage, 'defender-roll'); | ||||||
|     const attackerRoll = defenderRoll?.attackerRoll ?? ChatUtility.getMessageData(chatMessage, 'attacker-roll'); |     const attackerRoll = defenderRoll?.attackerRoll ?? ChatUtility.getMessageData(chatMessage, 'attacker-roll'); | ||||||
|     console.log('RdDCombat', attackerRoll, defenderRoll); |     console.log('RdDCombat', attackerRoll, defenderRoll); | ||||||
|     const defenderTokenId = event.currentTarget.attributes['data-defenderTokenId']?.value; |  | ||||||
|  |  | ||||||
|     const armeParadeId = event.currentTarget.attributes['data-armeid']?.value; |     const armeParadeId = event.currentTarget.attributes['data-armeid']?.value; | ||||||
|     const competence = event.currentTarget.attributes['data-competence']?.value; |     const competence = event.currentTarget.attributes['data-competence']?.value; | ||||||
| @@ -585,7 +601,7 @@ export class RdDCombat { | |||||||
|       case '#particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value); |       case '#particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value); | ||||||
|       case '#parer-button': return this.parade(attackerRoll, armeParadeId); |       case '#parer-button': return this.parade(attackerRoll, armeParadeId); | ||||||
|       case '#esquiver-button': return this.esquive(attackerRoll, compId, competence); |       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 '#echec-total-attaque': return this._onEchecTotal(attackerRoll); | ||||||
|  |  | ||||||
|       case '#appel-chance-attaque': return this.attacker.rollAppelChance( |       case '#appel-chance-attaque': return this.attacker.rollAppelChance( | ||||||
| @@ -702,7 +718,7 @@ export class RdDCombat { | |||||||
|         }) |         }) | ||||||
|       } |       } | ||||||
|       else { |       else { | ||||||
|         const defenderToken = canvas.tokens.get(this.defenderTokenId); |         const defenderToken = canvas.tokens.get(this.defenderTokenId) | ||||||
|         const dist = this.distance(_token, defenderToken) |         const dist = this.distance(_token, defenderToken) | ||||||
|         const isVisible = this.isVisible(_token, defenderToken) |         const isVisible = this.isVisible(_token, defenderToken) | ||||||
|         const portee = this._ajustementPortee(dist, rollData.arme) |         const portee = this._ajustementPortee(dist, rollData.arme) | ||||||
| @@ -769,7 +785,7 @@ export class RdDCombat { | |||||||
|     } |     } | ||||||
|     RdDEmpoignade.checkEmpoignadeEnCours(this.attacker) |     RdDEmpoignade.checkEmpoignadeEnCours(this.attacker) | ||||||
|  |  | ||||||
|     let rollData = this._prepareAttaque(competence, arme); |     let rollData = this._prepareAttaque(competence, arme) | ||||||
|     console.log("RdDCombat.attaque >>>", rollData); |     console.log("RdDCombat.attaque >>>", rollData); | ||||||
|     if (arme) { |     if (arme) { | ||||||
|       this.attacker.verifierForceMin(arme); |       this.attacker.verifierForceMin(arme); | ||||||
| @@ -795,15 +811,18 @@ export class RdDCombat { | |||||||
|     dialog.render(true); |     dialog.render(true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |    | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   _prepareAttaque(competence, arme) { |   _prepareAttaque(competence, arme) { | ||||||
|     let rollData = { |     let rollData = { | ||||||
|  |       alias: this.attackerToken.name, | ||||||
|       passeArme: foundry.utils.randomID(16), |       passeArme: foundry.utils.randomID(16), | ||||||
|       mortalite: arme?.system.mortalite, |       mortalite: arme?.system.mortalite, | ||||||
|       competence: competence, |       competence: competence, | ||||||
|       surprise: this.attacker.getSurprise(true), |       surprise: this.attacker.getSurprise(true), | ||||||
|       surpriseDefenseur: this.defender.getSurprise(true), |       surpriseDefenseur: this.defender.getSurprise(true), | ||||||
|       targetToken: Targets.extractTokenData(this.target), |       sourceToken: this.attackerToken, | ||||||
|  |       targetToken: this.defenderToken, | ||||||
|       essais: {} |       essais: {} | ||||||
|     }; |     }; | ||||||
|      |      | ||||||
| @@ -848,9 +867,10 @@ export class RdDCombat { | |||||||
|       alias: this.attacker.name, |       alias: this.attacker.name, | ||||||
|       whisper: ChatUtility.getOwners(this.attacker), |       whisper: ChatUtility.getOwners(this.attacker), | ||||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html', { |       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, |         attackerId: this.attackerId, | ||||||
|         defenderTokenId: this.defenderTokenId, |         attackerToken: this.attackerToken, | ||||||
|  |         defenderToken: this.defenderToken, | ||||||
|         isForce: isForce, |         isForce: isForce, | ||||||
|         isFinesse: isFinesse, |         isFinesse: isFinesse, | ||||||
|         isRapide: isRapide, |         isRapide: isRapide, | ||||||
| @@ -867,7 +887,7 @@ export class RdDCombat { | |||||||
|     attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite()); |     attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite()); | ||||||
|     let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} } |     let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} } | ||||||
|     attackerRoll.show = { |     attackerRoll.show = { | ||||||
|       cible: this.target ? this.defender.name : 'la cible', |       cible: this.defenderToken?.name ?? 'la cible', | ||||||
|       isRecul: (attackerRoll.particuliere == 'force' || attackerRoll.tactique == 'charge') |       isRecul: (attackerRoll.particuliere == 'force' || attackerRoll.tactique == 'charge') | ||||||
|     } |     } | ||||||
|     await RdDResolutionTable.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.html'); |     await RdDResolutionTable.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.html'); | ||||||
| @@ -908,7 +928,8 @@ export class RdDCombat { | |||||||
|       attacker: this.attacker, |       attacker: this.attacker, | ||||||
|       attackerId: this.attackerId, |       attackerId: this.attackerId, | ||||||
|       esquives: esquives, |       esquives: esquives, | ||||||
|       defenderTokenId: this.defenderTokenId, |       attackerToken: this.attackerToken, | ||||||
|  |       defenderToken: this.defenderToken, | ||||||
|       mainsNues: attackerRoll.dmg.mortalite != 'mortel' && corpsACorps, |       mainsNues: attackerRoll.dmg.mortalite != 'mortel' && corpsACorps, | ||||||
|       armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme), |       armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme), | ||||||
|       diffLibre: attackerRoll.ajustements?.diffLibre?.value ?? 0, |       diffLibre: attackerRoll.ajustements?.diffLibre?.value ?? 0, | ||||||
| @@ -919,7 +940,7 @@ export class RdDCombat { | |||||||
|       dmg: attackerRoll.dmg, |       dmg: attackerRoll.dmg, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     if (Misc.isUniqueConnectedGM()) { |     if (Misc.isFirstConnectedGM()) { | ||||||
|       await this._chatMessageDefense(paramChatDefense, defenderRoll); |       await this._chatMessageDefense(paramChatDefense, defenderRoll); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
| @@ -932,7 +953,7 @@ export class RdDCombat { | |||||||
|     const choixDefense = await ChatMessage.create({ |     const choixDefense = await ChatMessage.create({ | ||||||
|       // message privé: du défenseur à lui même (et aux GMs) |       // message privé: du défenseur à lui même (et aux GMs) | ||||||
|       speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)), |       speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)), | ||||||
|       alias: this.attacker.name, |       alias: this.attackerToken.name, | ||||||
|       whisper: ChatUtility.getOwners(this.defender), |       whisper: ChatUtility.getOwners(this.defender), | ||||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.html', paramDemandeDefense), |       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.html', paramDemandeDefense), | ||||||
|     }); |     }); | ||||||
| @@ -946,8 +967,9 @@ export class RdDCombat { | |||||||
|     game.socket.emit(SYSTEM_SOCKET_ID, { |     game.socket.emit(SYSTEM_SOCKET_ID, { | ||||||
|       msg: "msg_defense", data: { |       msg: "msg_defense", data: { | ||||||
|         attackerId: this.attacker?.id, |         attackerId: this.attacker?.id, | ||||||
|  |         attackerToken: this.attackerToken, | ||||||
|         defenderId: this.defender?.id, |         defenderId: this.defender?.id, | ||||||
|         defenderTokenId: this.defenderTokenId, |         defenderToken: this.defenderToken, | ||||||
|         defenderRoll: defenderRoll, |         defenderRoll: defenderRoll, | ||||||
|         paramChatDefense: paramChatDefense, |         paramChatDefense: paramChatDefense, | ||||||
|         rollMode: true |         rollMode: true | ||||||
| @@ -980,7 +1002,8 @@ export class RdDCombat { | |||||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', { |       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', { | ||||||
|         attackerId: this.attackerId, |         attackerId: this.attackerId, | ||||||
|         attacker: this.attacker, |         attacker: this.attacker, | ||||||
|         defenderTokenId: this.defenderTokenId, |         attackerToken: this.attackerToken, | ||||||
|  |         defenderToken: this.defenderToken, | ||||||
|         essais: attackerRoll.essais |         essais: attackerRoll.essais | ||||||
|       }) |       }) | ||||||
|     }); |     }); | ||||||
| @@ -1052,8 +1075,11 @@ export class RdDCombat { | |||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   _prepareParade(attackerRoll, armeParade, competenceParade) { |   _prepareParade(attackerRoll, armeParade, competenceParade) { | ||||||
|     let defenderRoll = { |     let defenderRoll = { | ||||||
|  |       alias: this.defenderToken?.name, | ||||||
|       passeArme: attackerRoll.passeArme, |       passeArme: attackerRoll.passeArme, | ||||||
|       diffLibre: attackerRoll.diffLibre, |       diffLibre: attackerRoll.diffLibre, | ||||||
|  |       attackerToken: this.attackerToken, | ||||||
|  |       defenderToken: this.defenderToken, | ||||||
|       attackerRoll: attackerRoll, |       attackerRoll: attackerRoll, | ||||||
|       competence: this.defender.getCompetence(competenceParade), |       competence: this.defender.getCompetence(competenceParade), | ||||||
|       arme: armeParade, |       arme: armeParade, | ||||||
| @@ -1133,8 +1159,11 @@ export class RdDCombat { | |||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   _prepareEsquive(attackerRoll, competence) { |   _prepareEsquive(attackerRoll, competence) { | ||||||
|     let rollData = { |     let rollData = { | ||||||
|  |       alias: this.defenderToken?.name, | ||||||
|       passeArme: attackerRoll.passeArme, |       passeArme: attackerRoll.passeArme, | ||||||
|       diffLibre: attackerRoll.diffLibre, |       diffLibre: attackerRoll.diffLibre, | ||||||
|  |       attackerToken: this.attackerToken, | ||||||
|  |       defenderToken: this.defenderToken, | ||||||
|       attackerRoll: attackerRoll, |       attackerRoll: attackerRoll, | ||||||
|       competence: competence, |       competence: competence, | ||||||
|       surprise: this.defender.getSurprise(true), |       surprise: this.defender.getSurprise(true), | ||||||
| @@ -1276,9 +1305,8 @@ export class RdDCombat { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async encaisser(attackerRoll, defenderRoll, defenderTokenId) { |   async encaisser(attackerRoll, defenderRoll) { | ||||||
|     defenderTokenId = defenderTokenId || this.defenderTokenId; |     console.log("RdDCombat.encaisser >>>", attackerRoll, defenderRoll); | ||||||
|     console.log("RdDCombat.encaisser >>>", attackerRoll, defenderTokenId); |  | ||||||
|  |  | ||||||
|     if (defenderRoll?.rolled && RdDCombat.isEchecTotal(defenderRoll)) { |     if (defenderRoll?.rolled && RdDCombat.isEchecTotal(defenderRoll)) { | ||||||
|       this._onEchecTotal(defenderRoll); |       this._onEchecTotal(defenderRoll); | ||||||
| @@ -1286,18 +1314,19 @@ export class RdDCombat { | |||||||
|  |  | ||||||
|     if (Misc.isOwnerPlayerOrUniqueConnectedGM(this.defender)) { |     if (Misc.isOwnerPlayerOrUniqueConnectedGM(this.defender)) { | ||||||
|       attackerRoll.attackerId = this.attackerId; |       attackerRoll.attackerId = this.attackerId; | ||||||
|       attackerRoll.defenderTokenId = defenderTokenId; |       attackerRoll.defenderTokenId = this.defenderToken.id; | ||||||
|  |  | ||||||
|       await this.computeRecul(defenderRoll); |       await this.computeRecul(defenderRoll); | ||||||
|       await this.defender.encaisserDommages(attackerRoll, this.attacker, 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 |     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, { |       game.socket.emit(SYSTEM_SOCKET_ID, { | ||||||
|         msg: "msg_encaisser", |         msg: "msg_encaisser", | ||||||
|         data: { |         data: { | ||||||
|           attackerId: this.attackerId, |           attackerId: this.attackerId, | ||||||
|           defenderTokenId: defenderTokenId, |           attackerRoll: attackerRoll, | ||||||
|           attackerRoll: attackerRoll |           attackerToken: this.attackerToken, | ||||||
|  |           defenderToken: this.defenderToken | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
| @@ -1305,28 +1334,28 @@ export class RdDCombat { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   static async displayActorCombatStatus(combat, actor, tokenId) { |   static async displayActorCombatStatus(combat, actor, token) { | ||||||
|     let formData = { |     let formData = { | ||||||
|       combatId: combat._id, |       combatId: combat._id, | ||||||
|       alias: actor.name, |       alias: token.name ?? actor.name, | ||||||
|       etatGeneral: actor.getEtatGeneral(), |       etatGeneral: actor.getEtatGeneral(), | ||||||
|       isSonne: actor.getSonne(), |       isSonne: actor.getSonne(), | ||||||
|       blessuresStatus: actor.computeResumeBlessure(), |       blessuresStatus: actor.computeResumeBlessure(), | ||||||
|       SConst: actor.getSConst(), |       SConst: actor.getSConst(), | ||||||
|       actorId: actor.id, |       actorId: actor.id, | ||||||
|       actor: actor, |       actor: actor, | ||||||
|       tokenId: tokenId, |       tokenId: token.id, | ||||||
|       isGrave: actor.countBlessures(it => it.isGrave()) > 0, |       isGrave: actor.countBlessures(it => it.isGrave()) > 0, | ||||||
|       isCritique: actor.countBlessures(it => it.isCritique()) > 0 |       isCritique: actor.countBlessures(it => it.isCritique()) > 0 | ||||||
|     } |     } | ||||||
|     await ChatMessage.create({ |     await ChatMessage.create({ | ||||||
|       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-acteur.hbs`, formData), |       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({ |     await ChatMessage.create({ | ||||||
|       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-sante.hbs`, formData), |       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-sante.hbs`, formData), | ||||||
|       whisper: ChatUtility.getOwners(actor), |       whisper: ChatUtility.getOwners(actor), | ||||||
|       alias: actor.name |       alias: token.name ?? actor.name | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -278,7 +278,7 @@ export class SystemReveDeDragon { | |||||||
|     /*  Foundry VTT Initialization                  */ |     /*  Foundry VTT Initialization                  */ | ||||||
|     /* -------------------------------------------- */ |     /* -------------------------------------------- */ | ||||||
|     game.system.rdd.calendrier = new RdDCalendrier() |     game.system.rdd.calendrier = new RdDCalendrier() | ||||||
|     if (Misc.isUniqueConnectedGM()) { |     if (Misc.isFirstConnectedGM()) { | ||||||
|       new Migrations().migrate() |       new Migrations().migrate() | ||||||
|       this.messageDeBienvenue() |       this.messageDeBienvenue() | ||||||
|       import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter => { |       import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter => { | ||||||
|   | |||||||
| @@ -72,6 +72,6 @@ export class RdDEncaisser extends Dialog { | |||||||
|         encaisserSpecial: this.encaisserSpecial, |         encaisserSpecial: this.encaisserSpecial, | ||||||
|         mortalite: mortalite |         mortalite: mortalite | ||||||
|       } |       } | ||||||
|     }); |     }) | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ export class RdDTokenHud { | |||||||
|       // initiative |       // initiative | ||||||
|       await RdDTokenHud.addExtensionHudInit(html, combatant, actions); |       await RdDTokenHud.addExtensionHudInit(html, combatant, actions); | ||||||
|       // combat |       // 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) { |   static async addExtensionHudCombat(html, combatant, token, actions) { | ||||||
|     const hudData = { combatant, actions, commandes: [] }; |     const hudData = { combatant, token, actions, commandes: [] }; | ||||||
|     const controlIconTarget = html.find('.control-icon[data-action=target]'); |     const controlIconTarget = html.find('.control-icon[data-action=target]'); | ||||||
|     await RdDTokenHud._configureSubMenu(controlIconTarget, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData, |     await RdDTokenHud._configureSubMenu(controlIconTarget, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData, | ||||||
|       (event) => { |       (event) => { | ||||||
| @@ -80,7 +80,7 @@ export class RdDTokenHud { | |||||||
|           combatant.actor.conjurerPossession(possession); |           combatant.actor.conjurerPossession(possession); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|           combatant.actor.rollArme(action); |           combatant.actor.rollArme(action, 'competence', token) | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -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); |     const diff = Math.abs(rollData.diffLibre); | ||||||
|     let formula = RdDUtility.formuleEncaissement(diff, options) |     let formula = RdDUtility.formuleEncaissement(diff, options) | ||||||
|     const roll = await RdDDice.roll(formula, options); |     const roll = await RdDDice.roll(formula, options); | ||||||
|  |  | ||||||
|     RdDUtility.remplaceDeMinParDifficulte(roll, diff, 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) { |   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 |     // 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 bonusDegatsDiffLibre = ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(rollData.diffLibre ?? 0) : 0 | ||||||
|     const jetTotal = roll.total + rollData.dmg.total - armure + bonusDegatsDiffLibre |     const jetTotal = roll.total + rollData.dmg.total - armure + bonusDegatsDiffLibre | ||||||
|     const encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite); |     const encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite); | ||||||
|     const over20 = Math.max(jetTotal - 20, 0); |     const over20 = Math.max(jetTotal - 20, 0); | ||||||
|     encaissement.dmg = rollData.dmg; |     encaissement.dmg = rollData.dmg | ||||||
|     encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(this.type); |     if (ReglesOptionnelles.isUsing('localisation-aleatoire')){ | ||||||
|     encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;'; |       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.dmg.bonusDegatsDiffLibre = bonusDegatsDiffLibre | ||||||
|     encaissement.roll = roll; |     encaissement.roll = roll; | ||||||
|     encaissement.armure = armure; |     encaissement.armure = armure; | ||||||
| @@ -741,6 +746,15 @@ export class RdDUtility { | |||||||
|     return undefined; |     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) { |   static getSelectedActor(msgPlayer = undefined) { | ||||||
|     if (canvas.tokens.controlled.length == 1) { |     if (canvas.tokens.controlled.length == 1) { | ||||||
|       let token = canvas.tokens.controlled[0]; |       let token = canvas.tokens.controlled[0]; | ||||||
|   | |||||||
| @@ -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é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: '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: '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" }, |   { group: 'Règles de combat', name: 'deteriorationArmure',         descr: "Tenir compte de la détérioration des armures" }, | ||||||
|   | |||||||
| @@ -186,7 +186,7 @@ export class AppAstrologie extends Application { | |||||||
|       date: this.html.find('[name="joursAstrologie"]').val(), |       date: this.html.find('[name="joursAstrologie"]').val(), | ||||||
|       userId: game.user.id |       userId: game.user.id | ||||||
|     } |     } | ||||||
|     if (Misc.isUniqueConnectedGM()) { |     if (Misc.isFirstConnectedGM()) { | ||||||
|       game.system.rdd.calendrier.requestNombreAstral(socketData); |       game.system.rdd.calendrier.requestNombreAstral(socketData); | ||||||
|     } else { |     } else { | ||||||
|       game.socket.emit(SYSTEM_SOCKET_ID, { |       game.socket.emit(SYSTEM_SOCKET_ID, { | ||||||
|   | |||||||
| @@ -13,18 +13,21 @@ export class Targets { | |||||||
|   static extractTokenData(target) { |   static extractTokenData(target) { | ||||||
|     return { id: target?.id, name: target?.document.name, img: target?.document.texture.src ?? target?.actor.img ?? 'icons/svg/mystery-man.svg' }; |     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) { |   static isTargetEntite(target) { | ||||||
|     return target?.actor.type == 'entite' && target?.actor.system.definition.typeentite == ENTITE_NONINCARNE; |     return target?.actor.type == 'entite' && target?.actor.system.definition.typeentite == ENTITE_NONINCARNE; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static async selectOneToken(onSelectTarget = target => { }) { |   static async selectOneTargetToken(onSelectTarget = target => { }) { | ||||||
|     const targets = Targets.listTargets(); |     const targets = Targets.listTargets() | ||||||
|     switch (targets.length) { |     switch (targets.length) { | ||||||
|       case 0: return; |       case 0: | ||||||
|  |         return | ||||||
|       case 1: |       case 1: | ||||||
|         onSelectTarget(targets[0]); |         onSelectTarget(targets[0]) | ||||||
|         return; |         return | ||||||
|       default: |       default: | ||||||
|         { |         { | ||||||
|           const selectData = { |           const selectData = { | ||||||
| @@ -32,7 +35,7 @@ export class Targets { | |||||||
|             label: "Choisir une seule des cibles", |             label: "Choisir une seule des cibles", | ||||||
|             list: targets.map(it => Targets.extractTokenData(it)) |             list: targets.map(it => Targets.extractTokenData(it)) | ||||||
|           }; |           }; | ||||||
|           DialogSelect.select(selectData, onSelectTarget); |           DialogSelect.select(selectData, onSelectTarget) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -48,7 +48,7 @@ export class RdDCalendrier extends Application { | |||||||
|   constructor() { |   constructor() { | ||||||
|     super(); |     super(); | ||||||
|     this.timestamp = RdDTimestamp.getWorldTime(); |     this.timestamp = RdDTimestamp.getWorldTime(); | ||||||
|     if (Misc.isUniqueConnectedGM()) { // Uniquement si GM |     if (Misc.isFirstConnectedGM()) { // Uniquement si GM | ||||||
|       RdDTimestamp.setWorldTime(this.timestamp); |       RdDTimestamp.setWorldTime(this.timestamp); | ||||||
|       this.rebuildNombresAstraux(); // Ensure always up-to-date |       this.rebuildNombresAstraux(); // Ensure always up-to-date | ||||||
|     } |     } | ||||||
| @@ -258,7 +258,7 @@ export class RdDCalendrier extends Application { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async rebuildNombresAstraux() { |   async rebuildNombresAstraux() { | ||||||
|     if (Misc.isUniqueConnectedGM()) { |     if (Misc.isFirstConnectedGM()) { | ||||||
|       const nombresAstraux = this.getNombresAstraux() |       const nombresAstraux = this.getNombresAstraux() | ||||||
|       let newNombresAstraux = []; |       let newNombresAstraux = []; | ||||||
|       for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) { |       for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) { | ||||||
| @@ -337,7 +337,7 @@ export class RdDCalendrier extends Application { | |||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async requestNombreAstral(request) { |   async requestNombreAstral(request) { | ||||||
|     const actor = game.actors.get(request.id); |     const actor = game.actors.get(request.id); | ||||||
|     if (Misc.isUniqueConnectedGM()) { // Only once |     if (Misc.isFirstConnectedGM()) { // Only once | ||||||
|       console.log(request); |       console.log(request); | ||||||
|       let jourDiff = this.getLectureAstrologieDifficulte(request.date); |       let jourDiff = this.getLectureAstrologieDifficulte(request.date); | ||||||
|       let niveau = Number(request.astrologie.system.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat); |       let niveau = Number(request.astrologie.system.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat); | ||||||
|   | |||||||
| @@ -1561,6 +1561,11 @@ div.control-icon.token-hud-icon { | |||||||
|   height: 100%; |   height: 100%; | ||||||
|   object-fit: contain; |   object-fit: contain; | ||||||
| } | } | ||||||
|  | .chat-inline-icon { | ||||||
|  |   border: 0; | ||||||
|  |   padding: 1px; | ||||||
|  |   vertical-align: text-top; | ||||||
|  | } | ||||||
|  |  | ||||||
| #sidebar-tabs { | #sidebar-tabs { | ||||||
|   flex: 0 0 28px; |   flex: 0 0 28px; | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| { | { | ||||||
|   "id": "foundryvtt-reve-de-dragon", |   "id": "foundryvtt-reve-de-dragon", | ||||||
|   "title": "Rêve de Dragon", |   "title": "Rêve de Dragon", | ||||||
|   "version": "12.0.15", |   "version": "12.0.17", | ||||||
|   "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.15.zip", |   "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.17.zip", | ||||||
|   "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json", |   "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", |   "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md", | ||||||
|   "compatibility": { |   "compatibility": { | ||||||
|   | |||||||
| @@ -1,11 +1,17 @@ | |||||||
| <form class="{{cssClass}}" autocomplete="off" > | <form class="{{cssClass}}" autocomplete="off" > | ||||||
|   <section class="sheet-header"> |   <section class="sheet-header flexrow"> | ||||||
|     <div class="flexrow"> |     <div class="flex-grow-0-5"> | ||||||
|       <div class="flex-group-left flex-grow-0-5"> |       <img class="profile-img" src="{{img}}" data-edit="img" data-tooltip="{{name}}" /> | ||||||
|         <h1 class="charname">{{name}} |     </div> | ||||||
|         </h1> |     <div class="flexcol flex-grow-2"> | ||||||
|  |       <div> | ||||||
|  |         <h1 class="charname">{{name}}</h1> | ||||||
|       </div> |       </div> | ||||||
|       <div class="flex-group-right flex-grow-3"> |       <div> | ||||||
|  |         <a class="button-appel-chance"><img class="button-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/appel-chance.svg" data-tooltip="Appel à la chance"/></a> | ||||||
|  |         <a class="button-encaissement"><img class="button-img" src="icons/svg/bones.svg" data-tooltip="Encaisser des dommages"/></a> | ||||||
|  |         <a class="button-ethylisme"><img class="button-img" src="icons/svg/tankard.svg" data-tooltip="Boire"/></a> | ||||||
|  |         <a class="button-repos"><img class="button-img" src="icons/svg/sleep.svg" data-tooltip="Se reposer"/></a> | ||||||
|         {{#if system.attributs.hautrevant.value}} |         {{#if system.attributs.hautrevant.value}} | ||||||
|         <a class="button-tmr" data-tooltip="Montée dans les Terres Médianes !" {{#if hautreve.isDemiReve}}disabled{{/if}}> |         <a class="button-tmr" data-tooltip="Montée dans les Terres Médianes !" {{#if hautreve.isDemiReve}}disabled{{/if}}> | ||||||
|           <img class="button-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/icon-tmr-normal.svg"/> |           <img class="button-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/icon-tmr-normal.svg"/> | ||||||
| @@ -17,10 +23,6 @@ | |||||||
|           <img class="button-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/icon-tmr-view.svg"/> |           <img class="button-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/icon-tmr-view.svg"/> | ||||||
|         </a> |         </a> | ||||||
|         {{/if}} |         {{/if}} | ||||||
|         <a class="button-appel-chance"><img class="button-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/appel-chance.svg" data-tooltip="Appel à la chance"/></a> |  | ||||||
|         <a class="button-encaissement"><img class="button-img" src="icons/svg/bones.svg" data-tooltip="Encaisser des dommages"/></a> |  | ||||||
|         <a class="button-ethylisme"><img class="button-img" src="icons/svg/tankard.svg" data-tooltip="Boire"/></a> |  | ||||||
|         <a class="button-repos"><img class="button-img" src="icons/svg/sleep.svg" data-tooltip="Se reposer"/></a> |  | ||||||
|         {{#if @root.options.isGM}} |         {{#if @root.options.isGM}} | ||||||
|         <a class="button-remise-a-neuf"><img class="button-img" src="icons/svg/regen.svg" data-tooltip="Remise à neuf"/></a> |         <a class="button-remise-a-neuf"><img class="button-img" src="icons/svg/regen.svg" data-tooltip="Remise à neuf"/></a> | ||||||
|         {{/if}} |         {{/if}} | ||||||
|   | |||||||
| @@ -3,20 +3,22 @@ | |||||||
|   <br> |   <br> | ||||||
|   {{#if (eq attacker.type 'personnage')}} |   {{#if (eq attacker.type 'personnage')}} | ||||||
|     {{#unless essais.attaqueChance}} |     {{#unless essais.attaqueChance}} | ||||||
|       <a class='chat-card-button' id='appel-chance-attaque' data-attackerId='{{attackerId}}' |       <a class='chat-card-button' id='appel-chance-attaque' | ||||||
|         data-defenderTokenId='{{defenderTokenId}}'>Faire appel à la chance</a> |         data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'> | ||||||
|  |         Faire appel à la chance</a> | ||||||
|       </a> |       </a> | ||||||
|       <br> |       <br> | ||||||
|     {{/unless}} |     {{/unless}} | ||||||
|     {{#if (gt attacker.system.compteurs.destinee.value 0)}} |     {{#if (gt attacker.system.compteurs.destinee.value 0)}} | ||||||
|       <a class='chat-card-button' id='appel-destinee-attaque' data-attackerId='{{attackerId}}' |       <a class='chat-card-button' id='appel-destinee-attaque' | ||||||
|         data-defenderTokenId='{{defenderTokenId}}'>Utiliser la destinée</a> |         data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'> | ||||||
|  |         Utiliser la destinée</a> | ||||||
|       </a> |       </a> | ||||||
|       <br> |       <br> | ||||||
|     {{/if}} |     {{/if}} | ||||||
|   {{/if}} |   {{/if}} | ||||||
|   <a class='chat-card-button' id='echec-total-attaque' data-attackerId='{{attackerId}}' |   <a class='chat-card-button' id='echec-total-attaque' | ||||||
|     data-defenderTokenId='{{defenderTokenId}}'> |     data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'> | ||||||
|     Tirer la maladresse ! |     Tirer la maladresse ! | ||||||
|   </a> |   </a> | ||||||
| </div> | </div> | ||||||
| @@ -1,17 +1,17 @@ | |||||||
| <div data-passearme="{{passeArme}}"> | <div data-passearme="{{passeArme}}"> | ||||||
|   {{#if (eq surprise 'totale')}} |   {{#if (eq surprise 'totale')}} | ||||||
|     <span><strong>{{defender.name}}</strong> est totalement surpris</span> |     <span><strong>{{defenderToken.name}}</strong> est totalement surpris</span> | ||||||
|   {{else if essais.defense}} |   {{else if essais.defense}} | ||||||
|     <span><strong>{{defender.name}}</strong> doit :</span> |     <span><strong>{{defenderToken.name}}</strong> doit :</span> | ||||||
|   {{else}} |   {{else}} | ||||||
|     <span><strong>{{defender.name}}</strong> doit se défendre |     <span><strong>{{defenderToken.name}}</strong> doit se défendre | ||||||
|       {{~#if (eq surprise 'demi')}} avec une significative {{/if}} d'une attaque |       {{~#if (eq surprise 'demi')}} avec une significative {{/if}} d'une attaque | ||||||
|       {{~#if attaqueParticuliere}} <strong>particulière en |       {{~#if attaqueParticuliere}} <strong>particulière en | ||||||
|         {{~#if (eq attaqueParticuliere 'finesse')}} finesse |         {{~#if (eq attaqueParticuliere 'finesse')}} finesse | ||||||
|         {{else if (eq attaqueParticuliere 'force')}} force |         {{else if (eq attaqueParticuliere 'force')}} force | ||||||
|         {{else if (eq attaqueParticuliere 'rapidite')}} rapidité |         {{else if (eq attaqueParticuliere 'rapidite')}} rapidité | ||||||
|         {{/if~}}</strong> |         {{/if~}}</strong> | ||||||
|       {{/if}} de {{attacker.name}} ({{attaqueArme.name}}): |       {{/if}} de {{attackerToken.name}} ({{attaqueArme.name}}): | ||||||
|     </span> |     </span> | ||||||
|   {{/if}} |   {{/if}} | ||||||
|   <span class='chat-card-button-area'> |   <span class='chat-card-button-area'> | ||||||
| @@ -20,15 +20,17 @@ | |||||||
|         {{#if essais.defense}} |         {{#if essais.defense}} | ||||||
|           {{#unless essais.defenseChance}} |           {{#unless essais.defenseChance}} | ||||||
|             {{#if (eq defender.type 'personnage')}} |             {{#if (eq defender.type 'personnage')}} | ||||||
|             <a class='chat-card-button' id='appel-chance-defense' data-attackerId='{{attackerId}}' |             <a class='chat-card-button' id='appel-chance-defense' | ||||||
|               data-defenderTokenId='{{defenderTokenId}}'>Faire appel à la chance</a> |               data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'> | ||||||
|  |               Faire appel à la chance</a> | ||||||
|             </a> |             </a> | ||||||
|             <br> |             <br> | ||||||
|             {{/if}} |             {{/if}} | ||||||
|             {{#if (eq defender.type 'personnage')}} |             {{#if (eq defender.type 'personnage')}} | ||||||
|             {{#if (gt defender.system.compteurs.destinee.value 0)}} |             {{#if (gt defender.system.compteurs.destinee.value 0)}} | ||||||
|               <a class='chat-card-button' id='appel-destinee-defense' data-attackerId='{{attackerId}}' |               <a class='chat-card-button' id='appel-destinee-defense' | ||||||
|                 data-defenderTokenId='{{defenderTokenId}}'>Utiliser la destinée</a> |                 data-attackerId='{{attackerId}}' data-attackerTokenId='{{attackerToken.id}}' data-defenderTokenId='{{defenderToken.id}}'> | ||||||
|  |                 Utiliser la destinée</a> | ||||||
|               </a> |               </a> | ||||||
|               <br> |               <br> | ||||||
|             {{/if}} |             {{/if}} | ||||||
| @@ -36,24 +38,26 @@ | |||||||
|           {{/unless}} |           {{/unless}} | ||||||
|         {{else}} |         {{else}} | ||||||
|           {{#each armes as |arme key|}} |           {{#each armes as |arme key|}} | ||||||
|             <a class='chat-card-button' id='parer-button' data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderTokenId}}' |             <a class='chat-card-button' id='parer-button' | ||||||
|                 data-armeid='{{arme._id}}'> |               data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderToken.id}}' data-attackerTokenId='{{../attackerToken.id}}' | ||||||
|  |               data-armeid='{{arme._id}}'> | ||||||
|               Parer avec {{arme.name}} à {{../diffLibre }}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}} |               Parer avec {{arme.name}} à {{../diffLibre }}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}} | ||||||
|             </a> |             </a> | ||||||
|             <br> |             <br> | ||||||
|           {{/each}} |           {{/each}} | ||||||
|           {{#if mainsNues}} |           {{#if mainsNues}} | ||||||
|             <a class='chat-card-button' id='parer-button' data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderTokenId}}' |             <a class='chat-card-button' id='parer-button' | ||||||
|                 data-armeid='{{arme._id}}' data-competence='{{arme.system.competence}}'> |               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}} |               Parer à mains nues à {{diffLibre}}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}} | ||||||
|             </a> |             </a> | ||||||
|             <br> |             <br> | ||||||
|           {{/if}} |           {{/if}} | ||||||
|           {{#if (ne attaqueCategorie 'tir')}} |           {{#if (ne attaqueCategorie 'tir')}} | ||||||
|             {{#each esquives as |esquive key|}} |             {{#each esquives as |esquive key|}} | ||||||
|             <a class='chat-card-button' id='esquiver-button' data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderTokenId}}' |             <a class='chat-card-button' id='esquiver-button'  | ||||||
|                 data-compid='{{esquive._id}}'  data-competence='{{esquive.name}}'> |               data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderToken.id}}' data-attackerTokenId='{{../attackerToken.id}}' | ||||||
|                 {{log 'esquive' esquive}} |               data-compid='{{esquive._id}}'  data-competence='{{esquive.name}}'> | ||||||
|               {{esquive.name}} à {{../diffLibre}} {{#if esquive.system.nbUsage}} (Utilisations : {{esquive.system.nbUsage}}){{/if}} |               {{esquive.name}} à {{../diffLibre}} {{#if esquive.system.nbUsage}} (Utilisations : {{esquive.system.nbUsage}}){{/if}} | ||||||
|             </a> |             </a> | ||||||
|             <br> |             <br> | ||||||
| @@ -61,8 +65,8 @@ | |||||||
|           {{/if}} |           {{/if}} | ||||||
|         {{/if}} |         {{/if}} | ||||||
|       {{/unless}} |       {{/unless}} | ||||||
|     <a class='chat-card-button' id='encaisser-button' data-attackerId='{{attackerId}}' |     <a class='chat-card-button' id='encaisser-button'  | ||||||
|       data-defenderTokenId='{{defenderTokenId}}'> |       data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'> | ||||||
|       Encaisser à {{plusMoins dmg.total}} |       Encaisser à {{plusMoins dmg.total}} | ||||||
|       {{#if (eq dmg.mortalite 'non-mortel')~}} |       {{#if (eq dmg.mortalite 'non-mortel')~}} | ||||||
|       (non-mortel) ! |       (non-mortel) ! | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| {{#if isGM}} | {{#if isGM}} | ||||||
| {{log this}} |  | ||||||
| <span> | <span> | ||||||
|   {{#if (gt endurance 0)}} |   {{#if (gt endurance 0)}} | ||||||
|   De plus, {{alias}} a perdu {{endurance}} points d'endurance |   De plus, {{alias}} a perdu {{endurance}} points d'endurance | ||||||
| @@ -18,18 +17,18 @@ | |||||||
| </h4> | </h4> | ||||||
| <div> | <div> | ||||||
|   Jet d'encaissement de {{roll.total}} |   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 (eq penetration 0)}} (pénétration de {{penetration}}){{/unless}} | ||||||
|   {{~/unless}}, total: <span class="rdd-roll-echec">{{total}}</span> |   {{~/unless~}}, total: <span class="rdd-roll-echec">{{total}}</span> | ||||||
|   <br>   |   <br>   | ||||||
|   {{alias}}  |   {{alias}}  | ||||||
|   {{#if (eq dmg.mortalite 'entiteincarnee')}}subit le coup |   {{#if (eq dmg.mortalite 'entiteincarnee')}}subit le coup | ||||||
|   {{else if mort}}vient de mourir |   {{else if mort}}vient de mourir | ||||||
|   {{else if blessure}} |   {{else if blessure}} | ||||||
|     {{#if (gt blessure.system.gravite 0)}}subit une blessure {{blessure.system.label}} |     {{#if (gt blessure.system.gravite 0)}}subit une blessure {{blessure.system.label}} | ||||||
|     {{else}}subit une contusion |     {{~else~}}subit une contusion | ||||||
|     {{~/if~}} |     {{~/if~}} | ||||||
|   {{else}}s'en sort sans une égratignure |   {{~else~}}s'en sort sans une égratignure | ||||||
|   {{~/if~}} |   {{~/if~}} | ||||||
|  |  | ||||||
|   {{~#unless (eq dmg.mortalite 'entiteincarnee')}} |   {{~#unless (eq dmg.mortalite 'entiteincarnee')}} | ||||||
| @@ -39,11 +38,11 @@ | |||||||
|   {{/unless~}} |   {{/unless~}} | ||||||
|   {{~#if (gt endurance 0)}} |   {{~#if (gt endurance 0)}} | ||||||
|   {{~#if hasPlayerOwner}}, a perdu {{endurance}} points d'endurance |   {{~#if hasPlayerOwner}}, a perdu {{endurance}} points d'endurance | ||||||
|   {{#if (ne vie 0)}}, <span class="rdd-roll-echec">{{vie}} points de vie</span>{{/if}} |   {{~#if (ne vie 0)}}, <span class="rdd-roll-echec">{{vie}} points de vie</span>{{/if~}} | ||||||
|   {{/if}} |   {{/if}} | ||||||
|   {{#if (ne dmg.mortalite 'entiteincarnee')}} |   {{#if (ne dmg.mortalite 'entiteincarnee')}} | ||||||
|   {{#if (gt endurance 1)}}et |   {{#if (gt endurance 1)}}et | ||||||
|   {{#if sonne}}est <strong>sonné</strong><img class="chat-icon" src="icons/svg/stoned.svg" data-tooltip="charge" height="16" width="16" /> jusqu'à la fin du prochain round{{else}}n'est pas sonné{{/if}}! |   {{#if sonne}}est <strong>sonné</strong><img class="chat-inline-icon" src="icons/svg/stoned.svg" data-tooltip="charge" height="16" width="16" /> jusqu'à la fin du prochain round{{else}}n'est pas sonné{{/if}}! | ||||||
|   {{#if hasPlayerOwner}}Jet d'endurance : {{jetEndurance}} / {{resteEndurance}}{{/if}} |   {{#if hasPlayerOwner}}Jet d'endurance : {{jetEndurance}} / {{resteEndurance}}{{/if}} | ||||||
|   {{/if}} |   {{/if}} | ||||||
|   {{/if}} |   {{/if}} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user