From 318396cde90054feac158660d70059612060cc63 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 9 Jan 2021 19:38:24 +0100 Subject: [PATCH] =?UTF-8?q?#100=20Am=C3=A9lioration=20messages=20encaissem?= =?UTF-8?q?ent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit +fix: coup non mortel à 20 ne fait pas perdre de vie, c'est le passage de l'endurance à 0 et l'inconscience qui font perdre la vie. --- module/actor.js | 153 ++++++++++++---------- module/rdd-utility.js | 31 ++--- templates/chat-resultat-encaissement.html | 42 ++++++ 3 files changed, 144 insertions(+), 82 deletions(-) create mode 100644 templates/chat-resultat-encaissement.html diff --git a/module/actor.js b/module/actor.js index 433db6b4..c8deb06f 100644 --- a/module/actor.js +++ b/module/actor.js @@ -1024,20 +1024,25 @@ export class RdDActor extends Actor { return 0; } - /* -------------------------------------------- */ - testSiSonne( sante, endurance ) - { - let result = new Roll("1d20").roll().total; - if ( result <= endurance) - sante.sonne.value = false; - if ( result > endurance || result == 20) // 20 is always a failure - sante.sonne.value = true; - if (result == 1) { - sante.sonne.value = false; - let xp = Misc.toInt(this.data.data.carac.constitution.xp) + 1; - this.update( {"data.carac.constitution.xp": xp } ); // +1 XP ! + /* -------------------------------------------- */ + testSiSonne(sante, endurance) { + const roll = new Roll("1d20").roll(); + roll.showDice = true; + RdDDice.show(roll); + let result = { + roll: roll, + sonne: roll.total > endurance || roll.total == 20 + } + if (roll.total == 1) { + let xp = Misc.toInt(this.data.data.carac.constitution.xp) + 1; + this.update({ "data.carac.constitution.xp": xp }); // +1 XP ! // TODO : Output to chat } + if (result.sonne) { + // 20 is always a failure + sante.sonne.value = true; + } + return result; } /* -------------------------------------------- */ @@ -1083,40 +1088,48 @@ export class RdDActor extends Actor { if (!data) { return; } + let result = { + sonne: false, + }; + let minValue = 0; if (this.type == 'personnage') { // TODO: les animaux/humanoïdes on théoriquement aussi un sconst, mais la SPA n'est pas passé par là minValue = name == "vie" ? -Number(this.data.data.attributs.sconst.value) : 0; } - let newValue = Math.max(minValue, Math.min(data.value + inc, data.max)); - //console.log("New value ", inc, minValue, newValue); + result.newValue = Math.max(minValue, Math.min(data.value + inc, data.max)); + //console.log("New value ", inc, minValue, result.newValue); - if (name == "endurance" && this.data.type != 'entite' ) { - if ( sante.fatigue && inc < 0 ) { // Each endurance lost -> fatigue lost + if (name == "endurance" && this.data.type != 'entite') { + if (sante.fatigue && inc < 0) { // Each endurance lost -> fatigue lost sante.fatigue.value = sante.fatigue.value - inc } - if ( !isCritique && newValue == 0 && inc < 0) { // perte endurance et endurance devient 0 -> -1 vie sauf si coup critique + if (!isCritique && result.newValue == 0 && inc < 0) { // perte endurance et endurance devient 0 -> -1 vie sauf si coup critique sante.vie.value = sante.vie.value - 1; } - newValue = Math.max(0, newValue); - if (inc>0) { // le max d'endurance s'applique seulement à la récupération - newValue = Math.min(newValue, this._computeEnduranceMax()) + result.newValue = Math.max(0, result.newValue); + if (inc > 0) { // le max d'endurance s'applique seulement à la récupération + result.newValue = Math.min(result.newValue, this._computeEnduranceMax()) } - if (data.value - newValue > 1) { - this.testSiSonne(sante, newValue); // Peut-être sonné si 2 points d'endurance perdus d'un coup - } else if (inc>0) { + if (data.value - result.newValue > 1) { + // Peut-être sonné si 2 points d'endurance perdus d'un coup + const testIsSonne = this.testSiSonne(sante, result.newValue); + result.sonne = testIsSonne.sonne; + result.jetEndurance = testIsSonne.roll.total; + } else if (inc > 0 && !this.isEntiteCauchemar()) { sante.sonne.value = false; } } - data.value = newValue; - //console.log(name, inc, data.value, newValue, minValue, data.max); - if ( sante.fatigue) { // If endurance lost, then the same amount of fatigue cannot be recovered + data.value = result.newValue; + //console.log(name, inc, data.value, result.newValue, minValue, data.max); + if (sante.fatigue) { // If endurance lost, then the same amount of fatigue cannot be recovered sante.fatigue.value = Math.max(sante.fatigue.value, this._computeFatigueMin()); - } + } //console.log("SANTE::::", sante); - - await this.update( {"data.sante": sante } ); + + await this.update({ "data.sante": sante }); + return result; } /* -------------------------------------------- */ @@ -2148,56 +2161,62 @@ export class RdDActor extends Actor { console.log("encaisserDommages", attackerRoll) + let santeOrig = duplicate(this.data.data.sante); let encaissement = this.jetEncaissement(attackerRoll); this.ajouterBlessure(encaissement); // Will upate the result table - - await this.santeIncDec("vie", encaissement.vie); - await this.santeIncDec("endurance", encaissement.endurance, (encaissement.critiques > 0)); - - const blessureLegere = (encaissement.legeres > 0 ? "une blessure légère" : ""); - const blessureGrave = (encaissement.graves > 0 ? "une blessure grave" : ""); - const blessureCritique = (encaissement.critiques > 0 ? "une blessure critique" : ""); - - let commonMsg = { - title: "Blessures !", - roll: encaissement.roll, - content: `${this.data.name} a encaissé ${blessureLegere}${blessureGrave}${blessureCritique} (${encaissement.locName})` - } - let addonMsg = "
Et a perdu :
" + encaissement.endurance + " Endurance et " + encaissement.vie + " Points de Vie"; - if ( this.hasPlayerOwner ) { - commonMsg.content += addonMsg; // Message pour tout le monde - ChatMessage.create( commonMsg ); - } else { // Le defenseur n'est pas un PJ, donc message complet uniquement pour le MJ - ChatMessage.create( commonMsg ); // Message pour tout le monde - let gmMsg = duplicate(commonMsg); - gmMsg.content = addonMsg; // Et message complémentaire uniquement pour le MJ - gmMsg.whisper = ChatMessage.getWhisperRecipients( "GM" ); - ChatMessage.create( gmMsg ); - } - + const perteVie = await this.santeIncDec("vie", - encaissement.vie); + const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, (encaissement.critiques > 0)); + this.computeEtatGeneral(); this.sheet.render(false); + + let santeActuelle = duplicate(this.data.data.sante); + + encaissement.alias = this.data.name; + encaissement.hasPlayerOwner = this.hasPlayerOwner; + encaissement.resteEndurance = santeActuelle.endurance.value + encaissement.sonne = perteEndurance.sonne; + encaissement.jetEndurance = perteEndurance.jetEndurance, + encaissement.endurance = santeOrig.endurance.value - perteEndurance.newValue; + encaissement.vie = santeOrig.vie.value - perteVie.newValue; + + ChatUtility.createChatWithRollMode(this.name, { + roll: encaissement.roll, + content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html', encaissement) + }); + + if (!encaissement.hasPlayerOwner && encaissement.endurance != 0) { + encaissement = duplicate(encaissement); + encaissement.isGM = true; + ChatMessage.create({ + whisper: ChatMessage.getWhisperRecipients("GM"), + content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html', encaissement) + }); + } } /* -------------------------------------------- */ jetEncaissement(rollData) { - - rollData.dmg.loc = rollData.dmg.loc?? RdDUtility.getLocalisation(); - - const roll = new Roll("2d10 + @dmg - @armure", { - dmg: rollData.dmg.total, - armure: this.computeArmure( rollData ) - }).roll(); + const roll = new Roll("2d10").roll(); + roll.showDice = true; RdDDice.show(roll, game.settings.get("core", "rollMode")); - let encaissement = RdDUtility.selectEncaissement(roll.total, rollData.dmg.mortalite) - let over20 = Math.max(roll.total - 20, 0); + const armure = this.computeArmure(rollData); + const jetTotal = roll.total + rollData.dmg.total - armure; + + let encaissement = RdDUtility.selectEncaissement(jetTotal, rollData.dmg.mortalite) + let over20 = Math.max(jetTotal - 20, 0); + encaissement.dmg = rollData.dmg; + encaissement.dmg.loc = rollData.dmg.loc ?? RdDUtility.getLocalisation(); + encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;' encaissement.roll = roll; - encaissement.vie = - RdDUtility._evaluatePerte(encaissement.vie, over20); - encaissement.endurance = - RdDUtility._evaluatePerte(encaissement.endurance, over20); - encaissement.loc = rollData.dmg.loc; - encaissement.locName = rollData.dmg.loc.label ?? "Corps"; + encaissement.armure = armure; + encaissement.total = jetTotal; + encaissement.vie = RdDUtility._evaluatePerte(encaissement.vie, over20); + encaissement.endurance = RdDUtility._evaluatePerte(encaissement.endurance, over20); + encaissement.penetration = rollData.arme?.data.penetration ?? 0; + return encaissement; } diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 80428e13..7b263dff 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -98,25 +98,25 @@ const nomEthylisme = ["Emeché", "Gris", "Pinté", "Pas frais", "Ivre", "Bu", "C /* -------------------------------------------- */ const definitionsEncaissement = { "mortel": [ - { minimum: undefined, maximum: 0, endurance: "0", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", legeres: 1, graves: 0, critiques: 0 }, - { minimum: 16, maximum: 19, endurance: "2d6", vie: "2", legeres: 0, graves: 1, critiques: 0 }, - { minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", legeres: 0, graves: 0, critiques: 1 }, + { minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 }, + { minimum: 16, maximum: 19, endurance: "2d6", vie: "2", eraflures: 0, legeres: 0, graves: 1, critiques: 0 }, + { minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", eraflures: 0, legeres: 0, graves: 0, critiques: 1 }, ], "non-mortel": [ - { minimum: undefined, maximum: 0, endurance: "0", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", legeres: 1, graves: 0, critiques: 0 }, - { minimum: 20, maximum: undefined, endurance: "100", vie: "1", legeres: 1, graves: 0, critiques: 0 }, + { minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 }, + { minimum: 20, maximum: undefined, endurance: "100", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 }, ], "cauchemar": [ - { minimum: undefined, maximum: 0, endurance: "0", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", legeres: 0, graves: 0, critiques: 0 }, + { minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, ] }; @@ -193,6 +193,7 @@ export class RdDUtility { 'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-appelchance.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-attaque.html', + 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-parade.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-esquive.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-competence.html', diff --git a/templates/chat-resultat-encaissement.html b/templates/chat-resultat-encaissement.html new file mode 100644 index 00000000..8413dd3e --- /dev/null +++ b/templates/chat-resultat-encaissement.html @@ -0,0 +1,42 @@ +{{#if isGM}} + + {{#if (gt endurance 0)}} + De plus, {{alias}} a perdu {{endurance}} points d'endurance + {{#if (ne vie 0)}}et {{vie}} points de vie{{/if}} + {{/if}} + +{{else}} +

{{alias}} encaisse à + + {{numberFormat dmg.total decimals=0 sign=true}} + {{#if (eq dmg.mortalite 'non-mortel')~}}(coups non mortels) + {{~else if (eq dmg.mortalite 'cauchemar')}}(entité de cauchemar) + {{~/if}} + +

+
+ Je d'encaissement de {{roll.total}} + {{#unless (eq armure 0)}}, l'armure a protègé de {{armure}} {{#unless (eq penetration 0)}}(pénétration de {{penetration}}) + {{/unless}} + {{/unless}}, total: {{total}} +
+ {{alias}} subit + {{#if (gt eraflures 0)}}une contusion + {{else if (gt legeres 0)}}une blessure légère + {{else if (gt graves 0)}}une blessure grave + {{else if (gt critique 0)}}une blessure critique + {{else}}Rien du tout + {{/if}} + + ({{dmg.loc.label}}) + {{#if (gt endurance 0)}} + {{#if hasPlayerOwner}}, a perdu {{endurance}} points d'endurance + {{#if (ne vie 0)}}, {{vie}} points de vie{{/if}} + {{/if}} + {{#if (gt endurance 1)}} + et {{#if sonne}}est sonnécharge jusqu'à la fin du prochain round{{else}}n'est pas sonné{{/if}} + ({{jetEndurance}} / {{resteEndurance}})! + {{/if}} + {{/if}} +
+{{/if}} \ No newline at end of file