nicer chat messages for rolls
This commit is contained in:
@@ -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;
|
||||
}
|
||||
+191
-16
@@ -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 = `<div class="dice-roll">`
|
||||
html += ` <div class="dice-result">`
|
||||
html += ` <div style="${styleOverride}" class="dice-formula">${resultString}</div>`
|
||||
html += ` <div class="dice-tooltip">`
|
||||
html += ` <section class="tooltip-part">`
|
||||
html += ` <div class="dice">`
|
||||
html += ` <p class="part-formula">`
|
||||
html += ` d100 OR d10 + d10`
|
||||
html += ` <span class="part-total">${roll.total}</span>`
|
||||
html += ` </p>`
|
||||
html += ` <ol class="dice-rolls">`
|
||||
//html += ` <li class="roll die d100">${roll.total}</li>`
|
||||
html += ` <li class="roll die d10">${damageDie1Label}</li>`
|
||||
html += ` <li class="roll die d10">${damageDie2Label}</li>`
|
||||
html += ` </ol>`
|
||||
html += ` </div>`
|
||||
html += ` </section>`
|
||||
html += ` </div>`
|
||||
html += ` <h4 class="dice-total">${roll.total} (${nonlethalDamage} Damage)</h4>`
|
||||
html += `</div>`
|
||||
|
||||
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 = `<div class="dice-roll">`
|
||||
html += ` <div class="dice-result">`
|
||||
html += ` <div style="${styleOverride}" class="dice-formula">${resultString}</div>`
|
||||
html += ` <div class="dice-tooltip">`
|
||||
html += ` <section class="tooltip-part">`
|
||||
html += ` <div class="dice">`
|
||||
html += ` <p class="part-formula">`
|
||||
html += ` ${roll.formula}`
|
||||
html += ` <span class="part-total">${roll.total}</span>`
|
||||
html += ` </p>`
|
||||
html += ` <ol class="dice-rolls">`
|
||||
html += ` <li class="roll die ${roll.formula}">${roll.total}</li>`
|
||||
html += ` </ol>`
|
||||
html += ` </div>`
|
||||
html += ` </section>`
|
||||
html += ` </div>`
|
||||
html += ` <h4 class="dice-total">${roll.total}</h4>`
|
||||
html += `</div>`
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<div class="resource flex-group-center">
|
||||
<label for="data.sanity.value" class="resource-label">SANITY</label>
|
||||
<div class="resource-content flexrow flex-center flex-between">
|
||||
<span class="rollable" data-roll="d100" data-target="sanity" data-label="SAN" title="Click to roll a sanity check...">SAN</span>
|
||||
<span class="rollable" data-rolltype="sanity" data-roll="d100" data-target="sanity" data-label="SAN" title="Click to roll a sanity check...">SAN</span>
|
||||
<input title="Starting sanity is equal to POW x 5." type="text" name="data.sanity.value" value="{{data.sanity.value}}" data-dtype="Number"/>
|
||||
<span> / </span>
|
||||
<span title="Maximum sanity is equal to 99 - the Unnatural skill." class="max-attribute-value-label">{{numberFormat data.sanity.max decimals=0 sign=false}}</span>
|
||||
@@ -67,7 +67,7 @@
|
||||
<div class="flex-group-center">
|
||||
<div class="horizontal-flex-column">
|
||||
<div class="flexrow" style="padding: 5px;">
|
||||
<label class="rollable" data-roll="d100" data-target="statistic.x5" data-label="{{key}}" title="Click to roll a x5 check." for="data.statistics.{{key}}.value" class="resource-label">{{toUpperCase key}}</label>
|
||||
<label class="rollable" data-rolltype="statistic.x5" data-roll="d100" data-target="statistic.x5" data-label="{{key}}" title="Click to roll a x5 check." for="data.statistics.{{key}}.value" class="resource-label">{{toUpperCase key}}</label>
|
||||
<input type="text" name="data.statistics.{{key}}.value" value="{{statistic.value}}" data-dtype="Number"/>
|
||||
<span >({{numberFormat statistic.x5 decimals=0 sign=false}}%)</span>
|
||||
</div>
|
||||
@@ -98,7 +98,7 @@
|
||||
<div class="grid grid-3col">
|
||||
{{#each data.skills as |skill key|}}
|
||||
<div class="flexrow flex-group-center">
|
||||
<label class="rollable skill-label" data-roll="d100" data-target="{{skill.proficiency}}" data-label="{{skill.label}}" title="Click to roll a skill check." for="data.skills.{{key}}.value" >{{skill.label}}</label>
|
||||
<label class="rollable skill-label" data-rolltype="skill" data-roll="d100" data-target="{{skill.proficiency}}" data-label="{{skill.label}}" title="Click to roll a skill check." for="data.skills.{{key}}.value" >{{skill.label}}</label>
|
||||
<input class="percentile-skill-input" type="text" name="data.skills.{{key}}.proficiency" value="{{skill.proficiency}}" data-dtype="Number"/>
|
||||
<input type="checkbox" name="data.skills.{{key}}.failure" {{checked skill.failure}} data-dtype="Boolean" {{#if skill.cannotBeImprovedByFailure}} disabled {{/if}} />
|
||||
</div>
|
||||
@@ -120,7 +120,7 @@
|
||||
|
||||
{{!-- Subtyped Skills take the form: data.type_skills.art.types[0].proficiency where 'types' is an array of object. --}}
|
||||
<a class="btn-tiny btn-remove-typed-skill" title="Add another skill." data-typeskill="{{key}}" data-index="{{@index}}">-</a>
|
||||
<span class="rollable" data-roll="d100" data-target="{{this.proficiency}}" data-label="{{this.specialization}}" title="Click to roll a skill check." name="data.type_skills.{{key}}.subskills.{{@index}}.specialization" >{{this.specialization}}</span>
|
||||
<span class="rollable" data-rolltype="typeskill" data-roll="d100" data-target="{{this.proficiency}}" data-label="{{this.specialization}}" title="Click to roll a skill check." name="data.type_skills.{{key}}.subskills.{{@index}}.specialization" >{{this.specialization}}</span>
|
||||
<input class="percentile-skill-input" type="text" name="data.type_skills.{{key}}.subskills.{{@index}}.proficiency" value="{{this.proficiency}}" data-dtype="Number"/>
|
||||
<input type="checkbox" name="data.type_skills.{{key}}.subskills.{{@index}}.failure" {{checked this.failure}} data-dtype="Boolean" />
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{!-- Owned Items Tab --}}
|
||||
{{!-- GEAR Tab --}}
|
||||
<div class="tab items" data-group="primary" data-tab="gear">
|
||||
<div>
|
||||
<h3>WEAPONS</h3>
|
||||
@@ -143,8 +143,8 @@
|
||||
<div class="item-image"></div>
|
||||
<div class="item-name">Name</div>
|
||||
<!-- <div class="item-name">Skill</div> -->
|
||||
<div class="item-name">Damage</div>
|
||||
<div class="item-name">Lethality</div>
|
||||
<div class="item-name">Damage/Lethality</div>
|
||||
<div class="item-name">Armor Piercing</div>
|
||||
<div class="item-controls">
|
||||
<a class="item-control item-create" title="Create item" data-type="weapon"><i class="fas fa-plus"></i> Add item</a>
|
||||
</div>
|
||||
@@ -159,7 +159,8 @@
|
||||
<h4 style="word-wrap: break-word;"
|
||||
|
||||
class="item-name rollable"
|
||||
data-roll="d100"
|
||||
data-roll="d100"
|
||||
data-rolltype="weapon"
|
||||
data-target="{{getActorSkillProp ../data item.data.skill 'proficiency'}}"
|
||||
data-label="{{getActorSkillProp ../data item.data.skill 'label'}}"
|
||||
title="Click to roll {{getActorSkillProp ../data item.data.skill 'label'}}"
|
||||
@@ -167,11 +168,20 @@
|
||||
{{item.name}}
|
||||
</h4>
|
||||
|
||||
<!-- <span class="item-name rollable" data-roll="d100" data-target="{{getActorSkillProp ../data item.data.skill 'proficiency'}}" data-label="{{getActorSkillProp ../data item.data.skill 'label'}}">{{getActorSkillProp ../data item.data.skill 'label'}}</span> -->
|
||||
<span class="rollable" data-target="damage" data-label="{{toUpperCase item.name}}" data-roll="{{toUpperCase item.data.damage}}" >{{toUpperCase item.data.damage}}</span>
|
||||
|
||||
<span class="rollable" data-target="lethality" data-label="{{toUpperCase item.name}}" data-roll="d100">{{formatLethality item.data.lethality}}</span>
|
||||
|
||||
{{#unless item.data.isLethal}}
|
||||
<span class="rollable" data-rolltype="damage" data-target="damage" data-label="{{toUpperCase item.name}}" data-roll="{{toUpperCase item.data.damage}}"
|
||||
title="A lethal weapon has a chance to instantly kill a target. Roll a D100 instead of damage die. If it is not lethal, damage is dealt instead as if the result was a 2d10 roll, with a '00' on the first d10 equaling a 10."
|
||||
>
|
||||
{{toUpperCase item.data.damage}}
|
||||
</span>
|
||||
{{/unless}}
|
||||
|
||||
{{#if item.data.isLethal}}
|
||||
<span class="rollable" data-rolltype="lethality" data-target="{{item.data.lethality}}" data-label="{{toUpperCase item.name}}" data-roll="d100">{{formatLethality item.data.lethality}}</span>
|
||||
{{/if}}
|
||||
|
||||
<span >{{item.data.armorPiercing}}</span>
|
||||
|
||||
<div class="item-controls">
|
||||
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||
|
||||
@@ -26,16 +26,30 @@
|
||||
<option {{#if_eq data.expense 'Extreme'}}selected{{/if_eq}} value="Extreme">Extreme</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{{#unless data.isLethal}}
|
||||
<div class="resource">
|
||||
<label class="resource-label">Damage</label>
|
||||
<input type="text" name="data.damage" value="{{data.damage}}" data-dtype="String"/>
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
{{#if data.isLethal}}
|
||||
<div class="resource">
|
||||
<label class="resource-label">Lethality %</label>
|
||||
<input type="text" name="data.lethality" value="{{data.lethality}}" data-dtype="Number"
|
||||
title="A lethal weapon has a chance to instantly kill a target. Roll a D100 instead of damage die. If it is not lethal, treat the result as 2d10 for damage."
|
||||
<input class="" type="text" name="data.lethality" value="{{data.lethality}}" data-dtype="Number"
|
||||
title="A lethal weapon has a chance to instantly kill a target. Roll a D100 instead of damage die. If it is not lethal, damage is dealt instead as if the result was a 2d10 roll, with a '00' on the first d10 equaling a 10."
|
||||
/>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="resource">
|
||||
<label class="resource-label">Is Lethal: </label>
|
||||
<input class="labeled-resource-checkbox" type="checkbox" name="data.isLethal" {{checked data.isLethal}} data-dtype="Boolean"
|
||||
title="Check this if the weapon has a lethality % associated with it."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="resource">
|
||||
<label class="resource-label">Armor Piercing</label>
|
||||
<input type="text" name="data.armorPiercing" value="{{data.armorPiercing}}" data-dtype="Number"/>
|
||||
|
||||
Reference in New Issue
Block a user