From 079b3d086fc0e55d2b34695c8ee1416679915e93 Mon Sep 17 00:00:00 2001 From: The Last Scrub Date: Sun, 5 Jul 2020 00:25:48 -0700 Subject: [PATCH] nicer chat messages for rolls --- css/deltagreen.css | 5 + module/actor/actor-sheet.js | 207 ++++++++++++++++++++++++-- templates/actor/actor-sheet.html | 36 +++-- templates/item/item-weapon-sheet.html | 18 ++- 4 files changed, 235 insertions(+), 31 deletions(-) diff --git a/css/deltagreen.css b/css/deltagreen.css index 90bf772..ba4479f 100644 --- a/css/deltagreen.css +++ b/css/deltagreen.css @@ -385,4 +385,9 @@ div span.bio-grid-label{ div .motivation-section{ border-bottom: 1px solid #AAA; margin-bottom: 10px; +} + +div .bottom-left-justified-resource{ + vertical-align: bottom; + text-align: left; } \ No newline at end of file diff --git a/module/actor/actor-sheet.js b/module/actor/actor-sheet.js index 0b39ac4..6522cb1 100644 --- a/module/actor/actor-sheet.js +++ b/module/actor/actor-sheet.js @@ -249,36 +249,40 @@ export class DeltaGreenActorSheet extends ActorSheet { if (dataset.roll) { let roll = new Roll(dataset.roll, this.actor.data.data); let key = dataset.label ? dataset.label : ''; - let label = dataset.label ? `Rolling ${dataset.label.toUpperCase()}` : ''; + //let label = dataset.label ? `Rolling ${dataset.label.toUpperCase()}` : ''; + let label = dataset.label ? `${dataset.label}` : ''; let targetVal = ""; + let rollType = dataset.rolltype ? dataset.rolltype : ''; // check the 'data-target="something" property to determine how to grab the target for the roll - if(Number.isNumeric(dataset.target)){ + if(rollType === "skill" || rollType === "typeskill"){ targetVal = dataset.target; - label += `, Target: ${targetVal}`; + this._sendPercentileTestToChat(label, targetVal); } else if(dataset.target === "statistic.x5"){ let stat = this.actor.data.data.statistics[key]; targetVal = stat.x5; - label += `, Target: ${targetVal}`; + this._sendPercentileTestToChat(label, targetVal); } - else if(dataset.target === "sanity"){ + else if(rollType === "sanity"){ targetVal = this.actor.data.data.sanity.value; - label += `, Target: ${targetVal}`; + //label += `, Target: ${targetVal}`; + this._sendPercentileTestToChat(label, targetVal); } - else if(dataset.target === "damage"){ + else if(rollType === "damage"){ // damage roll, not a skill check label = dataset.label ? `Rolling damage for ${dataset.label.toUpperCase()}` : ''; - } - else if(dataset.target === "lethality"){ - // a lethality roll - label = dataset.label ? `Rolling LETHALITY for ${dataset.label.toUpperCase()}` : ''; - } - roll.roll().toMessage({ - speaker: ChatMessage.getSpeaker({ actor: this.actor }), - flavor: label - }); + roll.roll().toMessage({ + speaker: ChatMessage.getSpeaker({ actor: this.actor }), + flavor: label + }); + } + else if(rollType === "lethality"){ + // a lethality roll + targetVal = dataset.target; + this._sendLethalityTestToChat(label, targetVal); + } } } @@ -297,4 +301,175 @@ export class DeltaGreenActorSheet extends ActorSheet { this.actor.update({"data": updatedData}); } + _sendLethalityTestToChat(weaponName, target){ + let roll = new Roll('d100', this.actor.data.data).roll(); + let isCritical = false; + let skillCheckTotal = roll.total; + + + // page 57 of agent's handbook + // Lethality rolls do not fumble or critically succeed, but the attack roll can. + // In this situation, the lethality threshold doubles (e.g. 20% would become 40%), + // and if the lethality roll fails, the damage is doubled per normal. However right now + // the attack roll and damage roll are completely separate... Perhaps in the future, use a + // hotkey to allow the doubling logic? + + // try to determine what the d100 result would be as if it was two d10's being rolled + let damageDie1 = Math.floor(skillCheckTotal / 10); + let damageDie2 = skillCheckTotal - (damageDie1 * 10); + if(damageDie2 === 0){ + // if the result is evenly divisible by 10 (e.g. 30, 40, 50...) + // then the percentile die result was actually one lower than the calculation above would show. + // For example, a '70' is actually a 60 + 10, so the damage die should be 6 + 10 = 16, not 7 + 0 = 7. + damageDie1 -= 1; + damageDie2 = 10; + } + + let damageDie1Label = damageDie1.toString(); + let damageDie2Label = damageDie2.toString(); + + if(damageDie1 === 0){ + // a roll of 00 on the tens part of the d100 counts as a ten if it becomes a damage die + // Will leave the labeling as a '0' though, to be consistent with a regular d10 roll + damageDie1 = 10; + } + + if(damageDie2 === 10){ + // keep the labelling consistent, show a '0' for a ten + damageDie2Label = '0'; + } + + let nonlethalDamage = damageDie1 + damageDie2; + + let isLethal = false; + let html = ''; + let label = `Rolling LETHALITY for ${weaponName.toUpperCase()} Target ${target}`; + let resultString = ''; + let styleOverride = ''; + + if(skillCheckTotal <= target){ + isLethal = true; + resultString = "LETHAL" + styleOverride="color: red"; + } + else{ + resultString = "Fail" + } + + html = `
` + html += `
` + html += `
${resultString}
` + html += `
` + html += `
` + html += `
` + html += `

` + html += ` d100 OR d10 + d10` + html += ` ${roll.total}` + html += `

` + html += `
    ` + //html += `
  1. ${roll.total}
  2. ` + html += `
  3. ${damageDie1Label}
  4. ` + html += `
  5. ${damageDie2Label}
  6. ` + html += `
` + html += `
` + html += `
` + html += `
` + html += `

${roll.total} (${nonlethalDamage} Damage)

` + html += `
` + + let chatData = { + speaker: ChatMessage.getSpeaker({actor: this.actor}), + content: html, + flavor: label + }; + + // play the dice rolling sound, like a regular in-chat roll + AudioHelper.play({src: "sounds/dice.wav", volume: 0.8, autoplay: true, loop: false}, true); + + ChatMessage.create(chatData, {}); + } + + _sendPercentileTestToChat(skill, target){ + let roll = new Roll('d100', this.actor.data.data).roll(); + let total = roll.total; + let isCritical = false; + let isSuccess = false; + let html = ''; + let label = `Rolling ${skill.toUpperCase()} Target ${target}`; + let resultString = ''; + let styleOverride = ''; + + isCritical = this._skillCheckResultIsCritical(total); + + if(total <= target){ + isSuccess = true; + } + + if(isCritical){ + resultString = 'CRITICAL '; + } + + if(isSuccess){ + resultString += "Success"; + + if(isCritical){ + resultString = resultString.toUpperCase() + '!'; + styleOverride="color: green"; + } + } + else{ + resultString += "Failure"; + + if(isCritical){ + resultString = resultString.toUpperCase() + '!'; + styleOverride="color: red"; + } + } + + html = `
` + html += `
` + html += `
${resultString}
` + html += `
` + html += `
` + html += `
` + html += `

` + html += ` ${roll.formula}` + html += ` ${roll.total}` + html += `

` + html += `
    ` + html += `
  1. ${roll.total}
  2. ` + html += `
` + html += `
` + html += `
` + html += `
` + html += `

${roll.total}

` + html += `
` + + let chatData = { + speaker: ChatMessage.getSpeaker({actor: this.actor}), + content: html, + flavor: label + }; + + // play the dice rolling sound, like a regular in-chat roll + AudioHelper.play({src: "sounds/dice.wav", volume: 0.8, autoplay: true, loop: false}, true); + + ChatMessage.create(chatData, {}); + } + + _skillCheckResultIsCritical(rollResult){ + let isCritical = false; + + if(rollResult === 1 || rollResult === 100){ + // really good, or reeaaaally bad + isCritical = true; + } + else if(rollResult % 11 === 0){ + // any matching dice are a crit, i.e. 11, 22, 33...99. + isCritical = true; + } + + return isCritical; + } + } diff --git a/templates/actor/actor-sheet.html b/templates/actor/actor-sheet.html index 50789b4..67f4838 100644 --- a/templates/actor/actor-sheet.html +++ b/templates/actor/actor-sheet.html @@ -45,7 +45,7 @@
- SAN + SAN / {{numberFormat data.sanity.max decimals=0 sign=false}} @@ -67,7 +67,7 @@
- + ({{numberFormat statistic.x5 decimals=0 sign=false}}%)
@@ -98,7 +98,7 @@
{{#each data.skills as |skill key|}}
- +
@@ -120,7 +120,7 @@ {{!-- Subtyped Skills take the form: data.type_skills.art.types[0].proficiency where 'types' is an array of object. --}} - - {{this.specialization}} + {{this.specialization}} @@ -133,7 +133,7 @@
- {{!-- Owned Items Tab --}} + {{!-- GEAR Tab --}}

WEAPONS

@@ -143,8 +143,8 @@
Name
-
Damage
-
Lethality
+
Damage/Lethality
+
Armor Piercing
@@ -159,7 +159,8 @@

- - {{toUpperCase item.data.damage}} - - {{formatLethality item.data.lethality}} - + {{#unless item.data.isLethal}} + + {{toUpperCase item.data.damage}} + + {{/unless}} + + {{#if item.data.isLethal}} + {{formatLethality item.data.lethality}} + {{/if}} + + {{item.data.armorPiercing}} +
diff --git a/templates/item/item-weapon-sheet.html b/templates/item/item-weapon-sheet.html index 1659d4e..3b35781 100644 --- a/templates/item/item-weapon-sheet.html +++ b/templates/item/item-weapon-sheet.html @@ -26,16 +26,30 @@
+ + {{#unless data.isLethal}}
+ {{/unless}} + + {{#if data.isLethal}}
-
+ {{/if}} + +
+ + +
+