diff --git a/assets/ui/chance.svg b/assets/ui/chance.svg new file mode 100644 index 00000000..a3d14d01 --- /dev/null +++ b/assets/ui/chance.svg @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + Layer 1 + + + + Layer 1 + + + + diff --git a/assets/ui/destinee.svg b/assets/ui/destinee.svg new file mode 100644 index 00000000..e24ce40e --- /dev/null +++ b/assets/ui/destinee.svg @@ -0,0 +1,90 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/assets/ui/encaisser.svg b/assets/ui/encaisser.svg new file mode 100644 index 00000000..8d752e50 --- /dev/null +++ b/assets/ui/encaisser.svg @@ -0,0 +1,66 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/assets/ui/recul.svg b/assets/ui/recul.svg new file mode 100644 index 00000000..ea20bc0d --- /dev/null +++ b/assets/ui/recul.svg @@ -0,0 +1,66 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/css/foundryvtt-reve-de-dragon.css b/css/foundryvtt-reve-de-dragon.css index 2a3846c8..603e7c50 100644 --- a/css/foundryvtt-reve-de-dragon.css +++ b/css/foundryvtt-reve-de-dragon.css @@ -424,7 +424,7 @@ select, .system-foundryvtt-reve-de-dragon .roll-dialog { font-family: CaslonAntique; display: grid; - grid-template-areas: "header header header header header header header" "action action action action action action action" "type separation separation separation separation separation separation" "type carac carac carac comp comp resume" "type choix choix choix choix choix modifiers" "type resolution resolution resolution resolution resolution modifiers" "type chances chances chances chances chances buttons" "footer footer footer footer footer footer footer"; + grid-template-areas: "header header header header header header header" "action action action action action action action" "type separation separation separation separation separation separation" "type carac carac carac comp comp resume" "type choix choix choix choix choix conditions" "type resolution resolution resolution resolution resolution conditions" "type chances chances chances chances chances buttons" "footer footer footer footer footer footer footer"; grid-template-columns: 2rem 1rem 1fr 1fr 2fr 2fr 3fr; gap: 0.2rem; } @@ -450,7 +450,7 @@ select, grid-area: resolution; } .system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions { - grid-area: modifiers; + grid-area: conditions; } .system-foundryvtt-reve-de-dragon .roll-dialog roll-chances { grid-area: chances; @@ -655,6 +655,80 @@ select, width: 1.5rem; text-align: center; } +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat { + font-family: CaslonAntique; + display: grid; + grid-template-areas: "img header buttons" "img resume buttons" "details details details" "actions actions actions"; + grid-template-columns: 3rem 1fr 1.4rem; + grid-template-rows: max-content max-content max-content max-content; + gap: 0 0.5rem; +} +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-img { + grid-area: img; + display: flex; + flex-direction: column; +} +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-img img { + border: 0; + max-height: 3rem; + max-width: 3rem; + object-fit: contain; + height: 100%; +} +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-header { + grid-area: header; + font-weight: bold; + font-size: 0.9rem; +} +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-resume { + grid-area: resume; + text-align: justify; +} +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-details { + grid-area: details; + text-align: justify; + display: flex; + flex-direction: column; +} +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-actions { + grid-area: actions; + display: flex; + flex-direction: column; +} +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-actions a { + display: flex; + flex-direction: row; +} +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-actions a img { + margin-right: 0.5rem; +} +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons { + grid-area: buttons; + display: flex; + flex-direction: column; +} +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons a { + border-radius: 0.2rem; + cursor: pointer; + padding: 0.2rem; + position: relative; + box-shadow: inset 1x 1px #a6827e; + color: var(--color-controls); + border: 1px ridge #846109; + display: inline-block; + align-items: center; +} +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons a img { + max-width: 1rem; + max-height: 1rem; +} +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons a:hover { + background: var(--background-custom-button-hover); +} +.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons a:active { + position: relative; + top: 1px; +} .system-foundryvtt-reve-de-dragon .window-header { background: rgba(0, 0, 0, 0.75); } @@ -1991,11 +2065,13 @@ select, flex-grow: 2; } .system-foundryvtt-reve-de-dragon #sidebar { - font-size: 1rem; background: #695541 url(../assets/ui/bg_sid_dark.webp) no-repeat right bottom; background-position: 100%; color: rgba(220, 220, 220, 0.75); } +.system-foundryvtt-reve-de-dragon #sidebar .chat-message { + font-size: 1rem; +} .system-foundryvtt-reve-de-dragon #sidebar-tabs > .collapsed, .system-foundryvtt-reve-de-dragon #chat-controls .chat-control-icon { color: rgba(220, 220, 220, 0.75); @@ -2606,6 +2682,11 @@ select, border: 2px ridge #846109; display: inline-block; } +.system-foundryvtt-reve-de-dragon .chat-card-button img, +.system-foundryvtt-reve-de-dragon .chat-card-button-pushed img { + max-width: 1rem; + max-height: 1rem; +} .system-foundryvtt-reve-de-dragon .chat-card-button { text-shadow: 1px 1px #4d3534; box-shadow: inset 1x 1px #a6827e; diff --git a/less/foundryvtt-reve-de-dragon.less b/less/foundryvtt-reve-de-dragon.less index 479e8a2d..f8d1e31b 100644 --- a/less/foundryvtt-reve-de-dragon.less +++ b/less/foundryvtt-reve-de-dragon.less @@ -7,6 +7,7 @@ @import "item/munition.less"; @import "item/tarot.less"; @import "roll-dialog.less"; + @import "roll-chat.less"; .window-header{ background: rgba(0,0,0,0.75); } @@ -1451,7 +1452,9 @@ /* ======================================== */ /* Sidebar CSS */ #sidebar { - font-size: 1rem; + .chat-message{ + font-size: 1rem; + } background: rgb(105,85,65) url(../assets/ui/bg_sid_dark.webp) no-repeat right bottom; background-position: 100%; color: rgba(220,220,220,0.75); @@ -1961,6 +1964,10 @@ border: 2px ridge #846109; display: inline-block; + img { + max-width: 1rem; + max-height: 1rem; + } } .chat-card-button{ diff --git a/less/roll-chat.less b/less/roll-chat.less new file mode 100644 index 00000000..c5da339c --- /dev/null +++ b/less/roll-chat.less @@ -0,0 +1,87 @@ +.chat-message { + div.roll-chat { + font-family: CaslonAntique; + display: grid; + grid-template-areas: + "img header buttons" + "img resume buttons" + "details details details" + "actions actions actions"; + grid-template-columns: 3rem 1fr 1.4rem; + grid-template-rows: max-content max-content max-content max-content; + gap: 0 0.5rem; + + div.chat-img { + grid-area: img; + display: flex; + flex-direction: column; + img { + border: 0; + max-height: 3rem; + max-width: 3rem; + object-fit: contain; + height: 100%; + } + } + div.chat-header { + grid-area: header; + font-weight: bold; + font-size: 0.9rem; + } + div.chat-resume { + grid-area: resume; + text-align: justify; + } + div.chat-details { + grid-area: details; + text-align: justify; + display: flex; + flex-direction: column; + } + div.chat-actions { + grid-area: actions; + display: flex; + flex-direction: column; + a { + display: flex; + flex-direction: row; + img { + margin-right: 0.5rem; + } + } + } + + div.chat-buttons { + grid-area: buttons; + display: flex; + flex-direction: column; + + a { + border-radius: 0.2rem; + cursor: pointer; + padding: 0.2rem; + position: relative; + box-shadow: inset 1x 1px #a6827e; + color: var(--color-controls); + border: 1px ridge #846109; + display: inline-block; + align-items: center; + + img { + max-width: 1rem; + max-height: 1rem; + } + } + + a:hover { + background: var(--background-custom-button-hover); + } + + a:active{ + position:relative; + top:1px; + } + + } + } +} \ No newline at end of file diff --git a/less/roll-dialog.less b/less/roll-dialog.less index 9afd9f70..c5628f3a 100644 --- a/less/roll-dialog.less +++ b/less/roll-dialog.less @@ -6,8 +6,8 @@ "action action action action action action action" "type separation separation separation separation separation separation" "type carac carac carac comp comp resume" - "type choix choix choix choix choix modifiers" - "type resolution resolution resolution resolution resolution modifiers" + "type choix choix choix choix choix conditions" + "type resolution resolution resolution resolution resolution conditions" "type chances chances chances chances chances buttons" "footer footer footer footer footer footer footer"; grid-template-columns: 2rem 1rem 1fr 1fr 2fr 2fr 3fr; @@ -22,7 +22,7 @@ roll-choix { grid-area: choix; } roll-table { grid-area: resolution; } - roll-conditions { grid-area: modifiers; } + roll-conditions { grid-area: conditions; } roll-chances { grid-area: chances; } roll-resume { grid-area: resume; } roll-buttons { grid-area: buttons; } diff --git a/module/actor.js b/module/actor.js index ed0189b1..fe8eea8c 100644 --- a/module/actor.js +++ b/module/actor.js @@ -3049,7 +3049,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ - async _rollArtV2(oeuvreId, callbackAction = async (actor, rd) => await actor._resultArtV2(rd)) { + async _rollArtV2(oeuvreId, callbackAction = async (rd) => await this._resultArtV2(rd)) { const oeuvre = this.items.get(oeuvreId) const rollData = { title: `Interpretation de ${oeuvre.name} par ${this.name}`, @@ -3074,15 +3074,16 @@ export class RdDActor extends RdDBaseActorSang { }) } + // TODO: move vers ChatRollResult async _resultArtV2(artData) { - const niveau = artData.oeuvre.system.niveau ?? 0; - const baseQualite = (artData.rolled.isSuccess ? niveau : artData.competence.system.niveau); - artData.qualiteFinale = Math.min(baseQualite, niveau) + artData.rolled.ptQualite; - - await RdDRollResult.displayRollData(artData, this.name, `chat-resultat-${artData.art}.hbs`); + const niveau = artData.oeuvre.system.niveau ?? 0 + const baseQualite = (artData.rolled.isSuccess ? niveau : artData.competence.system.niveau) + artData.qualiteFinale = Math.min(baseQualite, niveau) + artData.rolled.ptQualite + //this.$onRollCompetence(artData) + await RdDRollResult.displayRollData(artData, this.name, `chat-resultat-${artData.art}.hbs`) } - /* -------------------------------------------- */ + /* -------------------------------------------- */ async rollOeuvre(id) { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { return await this._rollArtV2(id) @@ -3168,7 +3169,7 @@ export class RdDActor extends RdDBaseActorSang { async _resultArt(artData) { const niveau = artData.oeuvre.system.niveau ?? 0; const baseQualite = (artData.rolled.isSuccess ? niveau : artData.competence.system.niveau); - artData.qualiteFinale = Math.min(baseQualite, niveau) + artData.rolled.ptQualite; + artData.qualiteFinale = Math.min(baseQualite, niveau) + artData.rolled.ptQualite await RdDRollResult.displayRollData(artData, this.name, `chat-resultat-${artData.art}.hbs`); } @@ -3189,7 +3190,7 @@ export class RdDActor extends RdDBaseActorSang { async _resultRecetteCuisine(cuisine) { const niveauRecette = cuisine.oeuvre.system.niveau ?? 0; const baseQualite = (cuisine.rolled.isSuccess ? niveauRecette : cuisine.competence.system.niveau); - cuisine.qualiteFinale = Math.min(baseQualite, niveauRecette) + cuisine.rolled.ptQualite; + cuisine.qualiteFinale = Math.min(baseQualite, niveauRecette) + cuisine.rolled.ptQualite cuisine.exotismeFinal = Math.min(Math.min(cuisine.qualiteFinale, cuisine.oeuvre.system.exotisme ?? 0), 0); cuisine.sust = cuisine.oeuvre.system.sust * Math.min(cuisine.proportions, cuisine.proportionsMax ?? cuisine.proportions) const platCuisine = { diff --git a/module/rdd-combat.js b/module/rdd-combat.js index 6e384eea..026285de 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -17,9 +17,8 @@ import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDInitiative } from "./initiative.mjs"; import RollDialog from "./roll/roll-dialog.mjs"; import { PART_DEFENSE } from "./roll/roll-part-defense.mjs"; -import { PART_ATTAQUE } from "./roll/roll-part-attaque.mjs"; import { RollDialogAdapter } from "./roll/roll-dialog-adapter.mjs"; -import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs"; +import { DIFF, ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs"; /* -------------------------------------------- */ const premierRoundInit = [ @@ -413,6 +412,9 @@ export class RdDCombat { '.appel-chance-attaque', '.appel-destinee-attaque', '.echec-total-attaque', + '.appel-chance', + '.chat-encaissement', + '.resister-recul', ]) { $(html).on("click", button, event => { const rddCombat = RdDCombat.rddCombatForAttackerAndDefender( @@ -807,8 +809,6 @@ export class RdDCombat { /* -------------------------------------------- */ async _sendMessageDefense(attackerRoll, defenderRoll, essaisPrecedents = undefined) { - console.log("RdDCombat._sendMessageDefense", attackerRoll, defenderRoll, essaisPrecedents, " / ", this.attacker, this.target, this.attackerId, attackerRoll.competence.system.categorie); - this.removeChatMessageActionsPasseArme(attackerRoll.passeArme); if (essaisPrecedents) { foundry.utils.mergeObject(attackerRoll.essais, essaisPrecedents, { overwrite: true }); @@ -980,18 +980,21 @@ export class RdDCombat { opponentId: this.attackerId, }, type: { allowed: ['defense'], current: 'defense' }, - attaque: RollDialogAdapter.mapActionAttaque(attackerRoll), + attackerRoll: RollDialogAdapter.mapActionAttaque(attackerRoll), passeArme: attackerRoll.passeArme, } await RollDialog.create(rollData, { - onRollDone: (dialog) => { dialog.close() }, + onRollDone: (dialog) => { + // dialog.close() + }, customChatMessage: true, callbacks: [async (roll) => { this.removeChatMessageActionsPasseArme(roll.passeArme) // defense: esquive / arme de parade / competence de défense - if (!RdDCombat.isParticuliere(roll)) + if (!RdDCombat.isParticuliere(roll)) { await roll.active.actor.incDecItemUse(roll.current[PART_DEFENSE].defense?.id,) + } await this._onDefense(roll) }] }) @@ -1025,57 +1028,49 @@ export class RdDCombat { } async _onDefense(rollData) { + console.log("RdDCombat._onDefense >>>", rollData) + const isEsquive = rollData.current[PART_DEFENSE].isEsquive + const isParade = !isEsquive if (RdDCombat.isReussite(rollData)) { - await this._onDefenseNormale(rollData) + if (isParade) { + await this.computeRecul(rollData) + await this.computeDeteriorationArme(rollData) + } + if (RdDCombat.isParticuliere(rollData)) { - await this._onDefenseParticuliere(rollData) + await this._onDefenseParticuliere(rollData, isEsquive) } } else { - await this._onDefenseEchec(dialog, rollData) + //await this._sendMessageDefense(rollData.attackerRoll, rollData, { defense: true }) } + + // TODO: modify chat message + this.removeChatMessageActionsPasseArme(rollData.passeArme) } - async _onDefenseParticuliere(rollData) { - console.log("RdDCombat._onDefenseParticuliere >>>", rollData); - if (/*TODO: parade?*/!rollData.attackerRoll?.isPart) { + async _onDefenseParticuliere(rollData, isEsquive) { + if (isEsquive) { + ChatUtility.createChatWithRollMode( + { content: "Vous pouvez esquiver une deuxième fois!" }, + this.defender) + } + else if (/*TODO: parade?*/!rollData.attackerRoll?.particuliere) { // TODO: attaquant doit jouer résistance et peut être désarmé p132 ChatUtility.createChatWithRollMode( { content: `(à gérer) L'attaquant doit jouer résistance et peut être désarmé (p132)` }, this.defender) } - ChatUtility.createChatWithRollMode( - { content: "Vous pouvez esquiver une deuxième fois!" }, - this.defender); } async _onDefenseNormale(rollData) { console.log("RdDCombat._onDefenseNormale >>>", rollData); - // console.log("RdDCombat._onEsquiveNormal >>>", rollData); - // await RdDRollResult.displayRollData(rollData, this.defender, 'chat-resultat-esquive.hbs'); - // this.removeChatMessageActionsPasseArme(rollData.passeArme); - //TODO await this.computeRecul(rollData); await this.computeDeteriorationArme(rollData); await RdDRollResult.displayRollData(rollData, this.defender, 'chat-resultat-parade.hbs'); this.removeChatMessageActionsPasseArme(rollData.passeArme); } - async _onDefenseEchec(rollData) { - console.log("RdDCombat._onDefenseEchec >>>", rollData); - // console.log("RdDCombat._onEsquiveEchec >>>", rollData); - - // await RdDRollResult.displayRollData(rollData, this.defender, 'chat-resultat-esquive.hbs'); - - // this.removeChatMessageActionsPasseArme(rollData.passeArme); - // this._sendMessageDefense(rollData.attackerRoll, rollData, { defense: true }) - - await RdDRollResult.displayRollData(rollData, this.defender, 'chat-resultat-parade.hbs'); - - this.removeChatMessageActionsPasseArme(rollData.passeArme); - this._sendMessageDefense(rollData.attackerRoll, rollData, { defense: true }); - } - @@ -1214,7 +1209,7 @@ export class RdDCombat { // Est-ce une parade normale? if (defenderRoll.arme && attackerRoll && !defenderRoll.rolled.isPart) { // Est-ce que l'attaque est une particulière en force ou une charge - if (defenderRoll.needResist || this._isForceOuCharge(attackerRoll)) { + if (defenderRoll.needResist || this._isForceOuCharge(attackerRoll, defenderRoll.v2)) { defenderRoll.show = defenderRoll.show || {} @@ -1262,7 +1257,7 @@ export class RdDCombat { finalLevel: Misc.toInt(defenderRoll.competence.system.niveau) - dmg, showDice: HIDE_DICE }); - defenderRoll.show.desarme = desarme.rolled.isEchec; + defenderRoll.show.desarme = desarme.rolled.isEchec } } } @@ -1270,39 +1265,47 @@ export class RdDCombat { /* -------------------------------------------- */ async computeRecul(defenderRoll) { // Calcul du recul (p. 132) - const attackerRoll = defenderRoll.attackerRoll; - if (ReglesOptionnelles.isUsing('recul') && this._isForceOuCharge(attackerRoll)) { - const impact = this._computeImpactRecul(attackerRoll); - const rollRecul = await RdDResolutionTable.rollData({ caracValue: 10, finalLevel: impact }); - if (rollRecul.rolled.isSuccess) { - defenderRoll.show.recul = 'encaisse'; - } else if (rollRecul.rolled.isETotal || this._isReculCauseChute(impact)) { - defenderRoll.show.recul = 'chute'; - await this.defender.setEffect(STATUSES.StatusProne, true); - } - else { - defenderRoll.show.recul = 'recul'; - } + if (!ReglesOptionnelles.isUsing('recul')) { + return } + const attackerRoll = defenderRoll.attackerRoll; + if (this._isForceOuCharge(attackerRoll, defenderRoll.v2)) { + const impact = this._computeImpactRecul(attackerRoll); + const rollRecul = await RdDResolutionTable.roll(10, impact) + defenderRoll.show.recul = await this.gererRecul(rollRecul, impact) + } + } + + async gererRecul(rolled, impact) { + if (rolled.isSuccess) { + return 'encaisse' + } + if (rolled.isETotal || this._isReculCauseChute(impact)) { + + await this.defender.setEffect(STATUSES.StatusProne, true) + return 'chute' + } + return 'recul' } /* -------------------------------------------- */ async _isReculCauseChute(impact) { - const agilite = this.defender.getAgilite(); - const chute = await RdDResolutionTable.rollData({ caracValue: agilite, finalLevel: impact }); - return chute.rolled.isEchec; + const agilite = this.defender.getAgilite() + const chute = await RdDResolutionTable.rollData({ caracValue: agilite, finalLevel: impact }) + return chute.rolled.isEchec + } + + _isForceOuCharge(attaque, isRollV2 = false /* TODO: delete roll V1 */) { + return attaque.particuliere == 'force' || 'charge' == (isRollV2 ? attaque.tactique?.key : attaque.tactique) } /* -------------------------------------------- */ - _isForceOuCharge(attaque) { - return attaque.particuliere == 'force' || attaque.tactique == 'charge'; - } - - /* -------------------------------------------- */ - _computeImpactRecul(attaque) { - const taille = this.defender.getTaille(); - const force = this.attacker.getForce(); - const dommages = attaque.arme.system.dommagesReels ?? attaque.arme.system.dommages; + _computeImpactRecul(attackerRoll) { + const taille = this.defender.getTaille() + const force = this.attacker.getForce() + const dommages = attackerRoll.dmg /* TODO: delete roll V1 */ + ? attackerRoll.dmg.dmgArme + : attackerRoll.arme.system.dommagesReels ?? attaque.arme.system.dommages; return taille - (force + dommages); } diff --git a/module/roll/chat-roll-result.mjs b/module/roll/chat-roll-result.mjs new file mode 100644 index 00000000..270785bf --- /dev/null +++ b/module/roll/chat-roll-result.mjs @@ -0,0 +1,59 @@ +import { ChatUtility } from "../chat-utility.js" +import RollDialog from "./roll-dialog.mjs" +import { RdDCarac } from "../rdd-carac.js"; + +export class ChatRollResult { + + static onReady() { + foundry.applications.handlebars.loadTemplates({ + 'partial-appel-chance': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-appel-chance.hbs', + 'partial-encaissement': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-encaissement.hbs', + 'partial-recul-choc': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-recul-choc.hbs', + 'partial-info-appel-moral': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-info-appel-moral.hbs', + }) + } + + async display(roll) { + roll.show = roll.show || {}; + roll.show.chance = this.isAppelChancePossible(roll) + roll.show.encaissement = this.isShowEncaissement(roll) + roll.show.recul = this.isShowReculChoc(roll) + + const chatMessage = await ChatUtility.createChatWithRollMode( + { + content: await this.buildRollHtml(roll) + }, + roll.active.actor, + roll.current?.rollmode?.key + ) + if (roll.show.chance) { + const save = RollDialog.saveParts(roll) + console.log("Store message roll", save) + ChatUtility.setMessageData(chatMessage, 'rollData', save) + } + return chatMessage + } + + isAppelChancePossible(roll) { + return roll.active.actor.isPersonnage() && + roll.rolled.isEchec && + RdDCarac.isActionPhysique(roll.current.carac?.key) + } + + isShowEncaissement(roll) { + return roll.rolled.isEchec && + roll.attackerRoll?.dmg.mortalite != 'empoignade' + } + + isShowReculChoc(roll) { + return roll.rolled.isEchec && + roll.attackerRoll && + !roll.current.defense.isEsquive && + (roll.attackerRoll.particuliere == 'force' || 'charge' == attackerRoll.tactique?.key) + } + + async buildRollHtml(roll) { + const template = `systems/foundryvtt-reve-de-dragon/templates/roll/result/chat-${roll.type.current}.hbs` + return await foundry.applications.handlebars.renderTemplate(template, roll) + } +} \ No newline at end of file diff --git a/module/roll/roll-chat-result.mjs b/module/roll/roll-chat-result.mjs deleted file mode 100644 index 045b2b6e..00000000 --- a/module/roll/roll-chat-result.mjs +++ /dev/null @@ -1,15 +0,0 @@ -export class RollChatResult { - constructor(rollType) { - this.rollType = rollType - } - - async display(rollData) { - const template = this.rollType.chatResultTemplate() - const chatContent = await renderTemplate(template, rollData) - - ChatMessage.create({ - whisper: ChatUtility.getOwners(this), - content: chatContent - }) - } -} \ No newline at end of file diff --git a/module/roll/roll-dialog-adapter.mjs b/module/roll/roll-dialog-adapter.mjs index 76b88c9d..55beea84 100644 --- a/module/roll/roll-dialog-adapter.mjs +++ b/module/roll/roll-dialog-adapter.mjs @@ -6,13 +6,12 @@ import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; import { PART_OEUVRE } from "./roll-part-oeuvre.mjs"; import { RdDItemArme } from "../item/arme.js"; import { RdDBonus } from "../rdd-bonus.js"; -import { ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"; /* -------------------------------------------- */ export class RollDialogAdapter { - async rollDice(rollData, rollTitle) { - const chances = this.computeChances({ + static async rollDice(rollData, rollTitle) { + const chances = RollDialogAdapter.computeChances({ carac: rollData.current.carac.value, diff: rollData.current.totaldiff, bonus: rollData.current.bonus, @@ -21,13 +20,13 @@ export class RollDialogAdapter { rollMode: rollData.current.rollmode.key }) - const rolled = await this.rollChances(rollData, chances) - this.adjustRollDataForV1(rollData, rolled, rollTitle) + const rolled = await RollDialogAdapter.rollChances(rollData, chances) + RollDialogAdapter.adjustRollDataForV1(rollData, rolled, rollTitle) return rolled } - computeChances({ carac, diff, bonus, sign, showDice, rollMode }) { + static computeChances({ carac, diff, bonus, sign, showDice, rollMode }) { const chances = foundry.utils.duplicate(RdDResolutionTable.computeChances(carac, diff)) RdDResolutionTable._updateChancesWithBonus(chances, bonus, diff) RdDResolutionTable._updateChancesFactor(chances, sign) @@ -36,7 +35,7 @@ export class RollDialogAdapter { return chances } - async rollChances(rollData, chances) { + static async rollChances(rollData, chances) { const rolled = await RdDResolutionTable.rollChances(chances, rollData.current.sign, rollData.current.resultat) @@ -47,7 +46,7 @@ export class RollDialogAdapter { return rolled } - adjustRollDataForV1(rollData, rolled, rollTitle) { + static adjustRollDataForV1(rollData, rolled, rollTitle) { // temporaire pour être homogène roll v1 rollData.alias = rollData.active.actor.getAlias() // pour experience diff --git a/module/roll/roll-dialog.mjs b/module/roll/roll-dialog.mjs index 2c9e61d9..1bd6b6b4 100644 --- a/module/roll/roll-dialog.mjs +++ b/module/roll/roll-dialog.mjs @@ -38,7 +38,8 @@ import { RollPartDefense } from "./roll-part-defense.mjs"; import { RollDialogAdapter } from "./roll-dialog-adapter.mjs"; import { ROLLDIALOG_SECTION } from "./roll-part.mjs"; import { ROLL_TYPE_COMP } from "./roll-constants.mjs"; -import { RollChatResult } from "./roll-chat-result.mjs"; +import { ChatRollResult } from "./chat-roll-result.mjs"; + const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api const doNothing = (dialog) => { } @@ -48,11 +49,12 @@ const ALL_ROLL_TYPES = [ new RollTypeTache(), new RollTypeAttaque(), new RollTypeDefense(), - // new RollTypeResistance ?? new RollTypeSort(), new RollTypeMeditation(), new RollTypeOeuvre(), new RollTypeJeu(), + // new RollTypeResistance ?? + // new RollTypeFixedCarac ?? ] const BASIC_PARTS = new RollBasicParts() @@ -182,6 +184,8 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 'roll-button': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-button.hbs', }) + ChatRollResult.onReady() + foundry.applications.handlebars.loadTemplates(ALL_ROLL_TYPES.map(m => m.template)) foundry.applications.handlebars.loadTemplates(ROLL_PARTS.map(p => p.template)) ROLL_PARTS.forEach(p => p.onReady()) @@ -246,9 +250,49 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 // rien pour l'instant } + /** pre-configure les paramètres des différentes parties de la fenêtre (par exemple, prépare les listes de caractéristiques/compétences */ + static $prepareRollData(rollData) { + rollData.current = rollData.current ?? {} + rollData.selected = rollData.selected ?? {} + rollData.type = rollData.type ?? {} + rollData.type.retry = rollData.type.retry ?? false + BASIC_PARTS.restore(rollData) + + const potential = ALL_ROLL_TYPES.find(m => m.code == rollData.type.current)?.code + const allowed = rollData.type.retry && potential + ? [potential] + : (rollData.type.allowed ?? ALL_ROLL_TYPES.filter(m => m.isAllowed(rollData) && m.visible(rollData)).map(m => m.code)) + const rollType = allowed.find(c => c == rollData.type.current) ?? (allowed.length > 0 ? allowed[0].code : ROLL_TYPE_COMP); + + rollData.type.allowed = allowed + rollData.type.current = rollType + ALL_ROLL_TYPES.find(m => m.code == rollType).setRollDataType(rollData) + + rollData.refs = foundry.utils.mergeObject(rollData.refs ?? {}, Object.fromEntries(ROLL_PARTS.map(p => [p.code, {}]))); + rollData.options = rollData.options ?? { rollMode: game.settings.get("core", "rollMode") } + + ROLL_PARTS.forEach(p => p.initialize(rollData)) + ROLL_PARTS.forEach(p => p.restore(rollData)) + ROLL_PARTS.filter(p => p.isValid(rollData)) + .forEach(p => { + p.loadRefs(rollData) + p.prepareContext(rollData) + }) + return rollData + } + + static saveParts(rollData) { + const target = BASIC_PARTS.initFrom(rollData) + ROLL_PARTS.filter(p => p.isActive(rollData)) + .forEach(p => p.storeClean(rollData, target)) + target.attackerRoll = rollData.attackerRoll + return target + } + constructor(rollData, rollOptions) { super() - this.rollData = rollData + + this.rollData = RollDialog.$prepareRollData(rollData) this.rollOptions = { callbacks: [ async r => await r.active.actor.appliquerAjoutExperience(r), @@ -258,37 +302,8 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 customChatMessage: rollOptions.customChatMessage, onRollDone: rollOptions.onRollDone ?? doNothing } - this.$loadParts() - } - - /** pre-configure les paramètres des différentes parties de la fenêtre (par exemple, prépare les listes de caractéristiques/compétences */ - $loadParts() { - const rollData = this.rollData; - rollData.current = rollData.current ?? {} - rollData.selected = rollData.selected ?? {} - rollData.type = rollData.type ?? {} - rollData.type.retry = rollData.type.retry ?? false - BASIC_PARTS.restore(rollData) - - const loadedType = ALL_ROLL_TYPES.find(m => m.code == rollData.type?.current)?.code - const allowedTypes = ALL_ROLL_TYPES.filter(m => m.isAllowed(rollData) && m.visible(rollData)).map(m => m.code) - - rollData.type.allowed = rollData.type.retry ? [loadedType] : rollData.type.allowed ?? ALL_ROLL_TYPES.map(m => m.code) - rollData.type.current = allowedTypes.find(m => m == rollData.type?.current) ?? (allowedTypes.length > 0 ? allowedTypes[0] : ROLL_TYPE_COMP) - - this.getSelectedType().setRollDataType(rollData) - - rollData.refs = this.$prepareRefs(rollData) - rollData.options = rollData.options ?? { showDice: true, rollMode: game.settings.get("core", "rollMode") } - - ROLL_PARTS.forEach(p => p.initialize(rollData)) - ROLL_PARTS.forEach(p => p.restore(rollData)) - ROLL_PARTS.filter(p => p.isValid(rollData)) - .forEach(p => { - p.loadRefs(rollData) - p.prepareContext(rollData) - }) - this.selectType(); + this.chatRollResult = new ChatRollResult(); + this.selectType() } selectType() { @@ -301,23 +316,21 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 ROLL_PARTS.find(it => it.code == PART_COMP).filterComps(this.rollData) } - $prepareRefs(rollData) { - return foundry.utils.mergeObject(rollData.refs ?? {}, Object.fromEntries(ROLL_PARTS.map(p => [p.code, {}]))); - } - - $saveParts() { - const target = BASIC_PARTS.initFrom(this.rollData) - ROLL_PARTS.filter(p => p.isActive(this.rollData)) - .forEach(p => p.store(this.rollData, target)) - return target - } getActiveParts() { return ROLL_PARTS.filter(p => p.isActive(this.rollData)) } - get title() { - return this.rollData.title ?? `Jet de dés de ${this.rollData.active.actor.name}` + // get title() { + // return this.rollData.title ?? `Jet de dés de ${this.rollData.active.actor.name}` + // } + + rollTitle(rollData) { + return rollData.label ?? ROLL_PARTS + .filter(it => it.section == ROLLDIALOG_SECTION.ACTION) + .filter(it => it.isActive(rollData)) + .map(it => it.title(rollData)) + .reduce(Misc.joining(' ')) } async _onRender(context, options) { @@ -344,9 +357,9 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 ) } - getAjustements() { + getAjustements(rollData = this.rollData) { return this.getActiveParts() - .map(p => p.getAjustements(this.rollData)) + .map(p => p.getAjustements(rollData)) .reduce((a, b) => a.concat(b)) .sort((a, b) => a.diff == undefined ? 1 : b.diff == undefined ? -1 : 0) } @@ -392,10 +405,10 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 } } - calculAjustements() { - this.rollData.ajustements = this.getAjustements() - this.rollData.ajustements.forEach(it => it.isDiff = it.diff != undefined) - this.rollData.current.totaldiff = this.rollData.ajustements + calculAjustements(rollData = this.rollData) { + rollData.ajustements = this.getAjustements(rollData) + rollData.ajustements.forEach(it => it.isDiff = it.diff != undefined) + rollData.current.totaldiff = rollData.ajustements .map(adj => adj.diff) .filter(d => d != undefined) .reduce(Misc.sum(), 0) @@ -406,36 +419,27 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 } async roll() { - this.calculAjustements() - const rollData = this.rollData - console.info('Roll parts:', this.$saveParts()) - const rolled = await this.$rollDice(rollData) - rollData.rolled = rolled - Promise.all(this.rollOptions.callbacks.map(async callback => await callback(rollData))) - if (!this.rollOptions.customChatMessage) { - const rollChatResult = new RollChatResult(this.getSelectedType()) - await rollChatResult.display(this.rollData) - rollData.active.actor.$onRollCompetence(this.rollData) - } + + const roll = RollDialog.saveParts(this.rollData) + RollDialog.$prepareRollData(roll) + this.calculAjustements(roll) + roll.current.resultat = this.rollData.current.resultat + roll.v2 = true + roll.rolled = await this.$rollDice(roll) + roll.result = this.getSelectedType(roll).getResult(roll) + console.info('RollDialog.roll:', roll) + await Promise.all(this.rollOptions.callbacks.map(async callback => await callback(roll))) + await this.chatRollResult.display(roll) + this.rollOptions.onRollDone(this) } - async defaultCallback(rollData, rolled) { await rollData.active.actor.appliquerAjoutExperience(rollData) await rollData.active.actor.appliquerAppelMoral(rollData) } async $rollDice(rollData) { - const adapter = new RollDialogAdapter(ROLL_PARTS); - return await adapter.rollDice(rollData, this.rollTitle(rollData)); - } - - rollTitle(rollData) { - return ROLL_PARTS - .filter(it => it.section == ROLLDIALOG_SECTION.ACTION) - .filter(it => it.isActive(rollData)) - .map(it => it.title(rollData)) - .reduce(Misc.joining(' ')) + return await RollDialogAdapter.rollDice(rollData, this.rollTitle(rollData)); } } diff --git a/module/roll/roll-part-attaque.mjs b/module/roll/roll-part-attaque.mjs index ec78c3ef..22e25877 100644 --- a/module/roll/roll-part-attaque.mjs +++ b/module/roll/roll-part-attaque.mjs @@ -1,10 +1,8 @@ import { RdDBonus } from "../rdd-bonus.js" -import { StatusEffects } from "../settings/status-effects.js" import { ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs" import { PART_CARAC } from "./roll-part-carac.mjs" import { PART_COMP } from "./roll-part-comp.mjs" import { RollPartSelect } from "./roll-part-select.mjs" -import { PART_SIGN } from "./roll-part-sign.mjs" import { ROLLDIALOG_SECTION } from "./roll-part.mjs" export const PART_ATTAQUE = 'attaque' @@ -28,6 +26,16 @@ export class RollPartAttaque extends RollPartSelect { } } + store(rollData, targetData) { + super.store(rollData, targetData) + this.getSaved(targetData).dmg = this.getCurrent(rollData).dmg + } + + restore(rollData) { + super.restore(rollData) + this.getCurrent(rollData).dmg = this.getSaved(rollData).dmg + } + choices(refs) { return refs.attaques } static $extractAttaque(attaque, actor) { diff --git a/module/roll/roll-part-carac.mjs b/module/roll/roll-part-carac.mjs index 4475c47f..b143859f 100644 --- a/module/roll/roll-part-carac.mjs +++ b/module/roll/roll-part-carac.mjs @@ -43,6 +43,7 @@ export class RollPartCarac extends RollPartSelect { // ? refs.all.filter(it => allowed.includes(Grammar.toLowerCaseNoAccent(it.key))) ? refs.all.filter(it => allowed.includes(it.key)) : refs.all + this.$selectCarac(rollData) } prepareContext(rollData) { diff --git a/module/roll/roll-part-comp.mjs b/module/roll/roll-part-comp.mjs index b7b261e3..0463307f 100644 --- a/module/roll/roll-part-comp.mjs +++ b/module/roll/roll-part-comp.mjs @@ -52,6 +52,7 @@ export class RollPartComp extends RollPartSelect { // ? refs.all.filter(it => allowed.includes(Grammar.toLowerCaseNoAccent(it.label))) ? refs.all.filter(it => allowed.includes(it.label)) : refs.all + this.$selectComp(rollData) } prepareContext(rollData) { diff --git a/module/roll/roll-part-defense.mjs b/module/roll/roll-part-defense.mjs index dda56974..82d33c51 100644 --- a/module/roll/roll-part-defense.mjs +++ b/module/roll/roll-part-defense.mjs @@ -27,14 +27,14 @@ export class RollPartDefense extends RollPartSelect { loadRefs(rollData) { const refs = this.getRefs(rollData) - const attaque = rollData.attaque + const attackerRoll = rollData.attackerRoll const defenseur = rollData.active.actor - refs.isDistance = [ATTAQUE_TYPE.TIR, ATTAQUE_TYPE.LANCER].find(it => it == attaque?.main) + refs.isDistance = [ATTAQUE_TYPE.TIR, ATTAQUE_TYPE.LANCER].find(it => it == attackerRoll?.main) const esquives = refs.isDistance == ATTAQUE_TYPE.TIR ? [] : defenseur.getCompetencesEsquive() .map(it => RollPartDefense.$extractEsquive(it, defenseur)) const parades = defenseur.items.filter(it => it.isParade() && (!refs.isDistance || it.isBouclier())) - .map(it => RollPartDefense.$extractParade(it, attaque?.attaque.arme, defenseur)) + .map(it => RollPartDefense.$extractParade(it, attackerRoll?.attaque.arme, defenseur)) refs.defenses = [...esquives, ...parades].filter(it => it != undefined) this.$selectDefense(rollData) @@ -48,7 +48,8 @@ export class RollPartDefense extends RollPartSelect { // TODO: carac pour créatures carac: defenseur.isPersonnage() ? CARACS.DEROBEE : esquive.name, verb: "esquive", - comp: esquive + comp: esquive, + isEsquive: true } } @@ -66,7 +67,8 @@ export class RollPartDefense extends RollPartSelect { comp: comp, arme: armeDefense, forceRequise: armeDefense ? RdDItemArme.valeurMain(armeDefense.system.force ?? 0, RdDItemArme.getMainAttaque(comp)) : 0, - typeParade: armeAttaque ? RdDItemArme.defenseArmeParade(armeDefense, armeAttaque) : 'norm' + typeParade: armeAttaque ? RdDItemArme.defenseArmeParade(armeDefense, armeAttaque) : 'norm', + isEsquive: false } } @@ -111,7 +113,7 @@ export class RollPartDefense extends RollPartSelect { isArmeDisparate(rollData) { const armeDefense = this.getCurrent(rollData).arme if (armeDefense) { - const armeAttaque = rollData.attaque?.attaque.arme + const armeAttaque = rollData.attackerRoll?.attaque.arme return RdDItemArme.defenseArmeParade(armeAttaque, armeDefense) == 'sign' } return false @@ -120,12 +122,12 @@ export class RollPartDefense extends RollPartSelect { getDiffDefense(rollData) { const current = this.getCurrent(rollData) const refs = this.getRefs(rollData) - if (refs.isDistance || !rollData.attaque) { + if (refs.isDistance || !rollData.attackerRoll) { // Déterminer la difficulté de parade return { diff: 0, type: DIFF.LIBRE } } else { - return { diff: rollData.attaque.diff ?? 0, type: DIFF.DEFENSE } + return { diff: rollData.attackerRoll.diff ?? 0, type: DIFF.DEFENSE } } } } diff --git a/module/roll/roll-part-oeuvre.mjs b/module/roll/roll-part-oeuvre.mjs index 2ae95e75..d59dd63a 100644 --- a/module/roll/roll-part-oeuvre.mjs +++ b/module/roll/roll-part-oeuvre.mjs @@ -1,5 +1,4 @@ import { ITEM_TYPES } from "../constants.js" -import { Grammar } from "../grammar.js" import { Misc } from "../misc.js" import { CARACS } from "../rdd-carac.js" import { ROLL_TYPE_OEUVRE } from "./roll-constants.mjs" @@ -59,6 +58,7 @@ export class RollPartOeuvre extends RollPartSelect { label: oeuvre.name, art: art, caracs: art.caracs(oeuvre), + qualite: oeuvre.system.niveau, value: -oeuvre.system.niveau, oeuvre: oeuvre, comp: actor.getCompetence(art.competence(oeuvre)) diff --git a/module/roll/roll-part-tricher.mjs b/module/roll/roll-part-tricher.mjs index e1909be2..9ea83617 100644 --- a/module/roll/roll-part-tricher.mjs +++ b/module/roll/roll-part-tricher.mjs @@ -1,6 +1,6 @@ import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs" -const PART_TRICHER = "tricher" +export const PART_TRICHER = "tricher" export class RollPartTricher extends RollPart { diff --git a/module/roll/roll-part.mjs b/module/roll/roll-part.mjs index 18d4610c..94481559 100644 --- a/module/roll/roll-part.mjs +++ b/module/roll/roll-part.mjs @@ -53,7 +53,23 @@ export class RollPart { } restore(rollData) { } - store(rollData, targetData) { } + + storeClean(rollData, targetData) { + this.store(rollData, targetData) + if (rollData.selected[this.code]) { + const toDelete = Object.entries(rollData.selected[this.code]) + .map(([k, v]) => v == undefined ? k : undefined) + .filter(k => k != undefined) + toDelete.forEach(k => delete rollData.selected[this.code][k]) + if (Object.keys(rollData.selected[this.code]).length == 0) { + delete rollData.selected[this.code] + } + } + } + + store(rollData, targetData) { + this.setSaved(targetData, { key: this.getCurrent(rollData).key }) + } /** * le texte à ajouter dans la barre de titre @@ -92,4 +108,14 @@ export class RollPart { async _onRender(rollDialog, context, options) { } + addResult(rollData) { + const result = this.getResult(rollData) + if (result){ + rollData.result[this.code] = result + } + } + + getResult(rollData){ + return undefined + } } \ No newline at end of file diff --git a/module/roll/roll-type-oeuvre.mjs b/module/roll/roll-type-oeuvre.mjs index 82388883..1cfbc90d 100644 --- a/module/roll/roll-type-oeuvre.mjs +++ b/module/roll/roll-type-oeuvre.mjs @@ -15,5 +15,14 @@ export class RollTypeOeuvre extends RollType { onSelect(rollData) { this.setDiffType(rollData, DIFF.AUCUN) } + + getResult(rollData){ + const current = rollData.current[PART_OEUVRE] + const qualite = rollData.rolled.isSuccess ? current.qualite : Math.min(current.qualite, current.comp.system.niveau) + return { + qualite: qualite + rollData.rolled.ptQualite + } + } + } diff --git a/module/roll/roll-type.mjs b/module/roll/roll-type.mjs index ad5fdd5b..ef7547bc 100644 --- a/module/roll/roll-type.mjs +++ b/module/roll/roll-type.mjs @@ -52,4 +52,8 @@ export class RollType { rollData.current[PART_DIFF].type = type this.setRollDataType(rollData) } + + getResult(rollData){ + return undefined + } } diff --git a/templates/roll/result/chat-defense.hbs b/templates/roll/result/chat-defense.hbs index 607558ef..65c66787 100644 --- a/templates/roll/result/chat-defense.hbs +++ b/templates/roll/result/chat-defense.hbs @@ -1,31 +1,52 @@ -

- {{log this}} - - {{alias}} esquive une attaque à {{diffLibre}}

-

{{selectedCarac.label}}{{#unless (eq selectedCarac.label competence.name)}} / {{competence.name}}{{/unless}}

-{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.hbs"}} -
-

- {{#if rolled.isSuccess}} - Attaque esquivée! - {{#if rolled.isPart}} - - {{alias}} peut faire une deuxième esquive! - {{/if}} - {{else}} - L'esquive de {{alias}} a échoué! - {{/if}} - {{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.hbs"}} -

+{{log this}} +
+
+ + +
-{{#if attackerRoll.tactique}} -

- {{#if (eq attackerRoll.tactique 'charge')}} - - C'était une charge, les parades de l'adversaire de {{alias}} auront un -4 et il ne pourra pas esquiver! - {{ else if (eq attackerRoll.tactique 'feinte')}} - - C'était une feinte! - {{/if}} -

-{{/if}} +
+ {{active.name}} {{#if current.defense.isEsquive}}esquive{{else}}pare{{/if}} une attaque {{grammar-apostrophe 'de' opponent.name}} +
+ +
+ {{current.carac.label}} / {{current.comp.label}} à {{current.diff.value}} +
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.hbs"}} +
+ +
+
+ {{#if rolled.isSuccess}} +

+ Attaque {{#if current.defense.isEsquive}}esquivée{{else}}parée{{/if}} + {{#if rolled.isPart}}, {{active.name}} peut + {{#if current.defense.isEsquive}}faire une deuxième esquive{{else}}réutiliser son arme{{/if}} + {{/if}} +

+ {{else}} +

{{#if current.defense.isEsquive}}Esquive{{else}}parade{{/if}} échouée!

+ {{/if}} + {{!-- {{else}} + + {{/if}} --}} + {{#if attackerRoll.tactique}} +

+ {{#if (eq attackerRoll.tactique.key 'charge')}} + + C'était une charge, les parades de {{opponent.name}} auront un -4 et il ne pourra pas esquiver! + {{else if (eq attackerRoll.tactique.key 'feinte')}} + + C'était une feinte! + {{/if}} +

+ {{/if}} + {{> 'partial-info-appel-moral'}} +
+
+ {{> 'partial-recul-choc'}} + {{> 'partial-encaissement'}} +
+
+ {{> 'partial-appel-chance'}} +
+
diff --git a/templates/roll/result/chat-oeuvre.hbs b/templates/roll/result/chat-oeuvre.hbs index e69de29b..f1b0b31e 100644 --- a/templates/roll/result/chat-oeuvre.hbs +++ b/templates/roll/result/chat-oeuvre.hbs @@ -0,0 +1,30 @@ +{{log this}} +
+
+ + +
+
+ {{active.name}} {{current.oeuvre.art.action}}: {{current.oeuvre.label}} (de niveau {{current.oeuvre.oeuvre.system.niveau}}) +
+ +
+ {{current.carac.label}} / {{current.comp.label}} à {{current.diff.value}} +
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.hbs"}} +
+ +
+

+ {{active.name}} + {{#if rolled.isSuccess}}réussit son interprétation avec + {{else}}manque d'inspiration, son interprétation a + {{/if}} + une qualité de {{result.qualite}}. +

+ {{> 'partial-info-appel-moral'}} + {{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.hbs" current.oeuvre.oeuvre.system}} +
+
+ {{> 'partial-appel-chance'}} +
+
diff --git a/templates/roll/result/partial-appel-chance.hbs b/templates/roll/result/partial-appel-chance.hbs new file mode 100644 index 00000000..cf115129 --- /dev/null +++ b/templates/roll/result/partial-appel-chance.hbs @@ -0,0 +1,22 @@ +{{#unless type.retry}} +{{#if show.chance}} + + + + {{#if (gt active.actor.system.compteurs.destinee.value 0)}} + + + + {{/if}} +{{/if}} +{{/unless}} diff --git a/templates/roll/result/partial-encaissement.hbs b/templates/roll/result/partial-encaissement.hbs new file mode 100644 index 00000000..098ed21c --- /dev/null +++ b/templates/roll/result/partial-encaissement.hbs @@ -0,0 +1,12 @@ +{{#if show.encaissement}} + + Encaisser à {{plusMoins attackerRoll.dmg.total}} + {{#if (eq attackerRoll.dmg.mortalite 'non-mortel')~}}(non-mortel){{/if}} + +{{/if}} diff --git a/templates/roll/result/partial-info-appel-moral.hbs b/templates/roll/result/partial-info-appel-moral.hbs new file mode 100644 index 00000000..7f583bd3 --- /dev/null +++ b/templates/roll/result/partial-info-appel-moral.hbs @@ -0,0 +1,15 @@ +{{#if current.appelmoral.checked}} +
+ {{{current.appelmoral.icon}}} + Vous avez fait appel {{#if (gt refs.appelmoral.moral 0)}}au moral{{else}}à l'énergie du désespoir{{/if}} + {{#if rolled.isSuccess}} + et réussi, votre moral reste de {{refs.appelmoral.moral}}. + {{else}} + et échoué, + {{#if (eq refs.appelmoral.moral -3)}} + vous marquez un point de dissolution! + {{else}}votre moral baisse de 1. + {{/if}} + {{/if}} +
+{{/if}} diff --git a/templates/roll/result/partial-recul-choc.hbs b/templates/roll/result/partial-recul-choc.hbs new file mode 100644 index 00000000..5471d1bb --- /dev/null +++ b/templates/roll/result/partial-recul-choc.hbs @@ -0,0 +1,11 @@ +{{#if show.recul}} + + Résister au recul + +{{/if}} diff --git a/templates/roll/roll-dialog.hbs b/templates/roll/roll-dialog.hbs index bed071ce..748460bc 100644 --- a/templates/roll/roll-dialog.hbs +++ b/templates/roll/roll-dialog.hbs @@ -6,7 +6,6 @@ {{#each templates as |template|}}{{> 'roll-section' rollData=@root.rollData currentsection='comp'}}{{/each}} {{#each templates as |template|}}{{> 'roll-section' rollData=@root.rollData currentsection='choix'}}{{/each}} {{#each templates as |template|}}{{> 'roll-section' rollData=@root.rollData currentsection='conditions'}}{{/each}} - {{log rollData.current rollData.current.carac rollData.current.totaldiff}} {{> 'roll-table' carac=rollData.current.carac.value diff=rollData.current.totaldiff}} {{> 'roll-chances' carac=rollData.current.carac.value diff=rollData.current.totaldiff}} {{> 'roll-ajustements' }} diff --git a/templates/roll/roll-table.hbs b/templates/roll/roll-table.hbs index a8edb3ce..f109c567 100644 --- a/templates/roll/roll-table.hbs +++ b/templates/roll/roll-table.hbs @@ -1,4 +1,3 @@ -{{log 'roll-table' carac diff this}}