Add resistance roll (#105)

Co-authored-by: megastruktur <astromortis@gmail.com>
This commit is contained in:
Clément Bonnet 2021-04-22 12:30:56 +02:00 committed by GitHub
parent 9d77e8b733
commit 63946298c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 150 additions and 49 deletions

View file

@ -129,6 +129,8 @@
"BITD.RollFailurePositionControlled": "You falter. Press on by seizing a <strong>risky</strong> opportunity, or withdraw and try a different approach.",
"BITD.RollFailurePositionRisky": "Things go badly. You suffer <strong>harm</strong> a <strong>complication</strong> occurs, you end up in a <strong>desperate</strong> position, you <strong>lose this opportunity</strong>.",
"BITD.RollFailurePositionDesperate": "Its the worst outcome. You suffer <strong>severe harm</strong>, a <strong>serious complication occurs</strong>, you <strong>lose this opportunity for action</strong>.",
"BITD.RollResistance": "You <strong>reduce</strong> or <strong>avoid</strong> the effects of the consequence (GM chooses).<br/>Suffer <strong>{stress} stress</strong>.",
"BITD.RollResistanceCritical": "You <strong>reduce</strong> or <strong>avoid</strong> the effects of the consequence (GM chooses).<br/>Clear <strong>1 stress</strong>.",
"BITD.PositionControlled": "Controlled",
"BITD.PositionRisky": "Risky",

View file

@ -64,9 +64,7 @@ export class BladesActor extends Actor {
// const roll = new Roll("1d20 + @abilities.wis.mod", actor.getRollData());
let attribute_label = BladesHelpers.getAttributeLabel(attribute_name);
new Dialog({
title: `${game.i18n.localize('BITD.Roll')} ${game.i18n.localize(attribute_label)}`,
content: `
var content = `
<h2>${game.i18n.localize('BITD.Roll')} ${game.i18n.localize(attribute_label)}</h2>
<form>
<div class="form-group">
@ -74,25 +72,37 @@ export class BladesActor extends Actor {
<select id="mod" name="mod">
${this.createListOfDiceMods(-3,+3,0)}
</select>
</div>`;
if (BladesHelpers.isAttributeAction(attribute_name)) {
content += `
<div class="form-group">
<label>${game.i18n.localize('BITD.Position')}:</label>
<select id="pos" name="pos">
<option value="controlled">${game.i18n.localize('BITD.PositionControlled')}</option>
<option value="risky" selected>${game.i18n.localize('BITD.PositionRisky')}</option>
<option value="desperate">${game.i18n.localize('BITD.PositionDesperate')}</option>
</select>
</div>
<div class="form-group">
<label>${game.i18n.localize('BITD.Position')}:</label>
<select id="pos" name="pos">
<option value="controlled">${game.i18n.localize('BITD.PositionControlled')}</option>
<option value="risky" selected>${game.i18n.localize('BITD.PositionRisky')}</option>
<option value="desperate">${game.i18n.localize('BITD.PositionDesperate')}</option>
</select>
</div>
<div class="form-group">
<label>${game.i18n.localize('BITD.Effect')}:</label>
<select id="fx" name="fx">
<option value="limited">${game.i18n.localize('BITD.EffectLimited')}</option>
<option value="standard" selected>${game.i18n.localize('BITD.EffectStandard')}</option>
<option value="great">${game.i18n.localize('BITD.EffectGreat')}</option>
</select>
</div>
<label>${game.i18n.localize('BITD.Effect')}:</label>
<select id="fx" name="fx">
<option value="limited">${game.i18n.localize('BITD.EffectLimited')}</option>
<option value="standard" selected>${game.i18n.localize('BITD.EffectStandard')}</option>
<option value="great">${game.i18n.localize('BITD.EffectGreat')}</option>
</select>
</div>`;
} else {
content += `
<input id="pos" name="pos" type="hidden" value="">
<input id="fx" name="fx" type="hidden" value="">`;
}
content += `
</form>
`,
`;
new Dialog({
title: `${game.i18n.localize('BITD.Roll')} ${game.i18n.localize(attribute_label)}`,
content: content,
buttons: {
yes: {
icon: "<i class='fas fa-check'></i>",

View file

@ -186,7 +186,6 @@ export class BladesHelpers {
* @returns {string}
*/
static getAttributeLabel(attribute_name) {
// Calculate Dice to throw.
let attribute_labels = {};
const attributes = game.system.model.Actor.character.attributes;
@ -200,6 +199,19 @@ export class BladesHelpers {
return attribute_labels[attribute_name];
}
/**
* Returns true if the attribute is an action
*
* @param {string} attribute_name
* @returns {bool}
*/
static isAttributeAction(attribute_name) {
let attribute_labels = {};
const attributes = game.system.model.Actor.character.attributes;
return !(attribute_name in attributes);
}
/* -------------------------------------------- */

View file

@ -46,33 +46,40 @@ async function showChatRollMessage(r, zeromode, attribute_name = "", position =
// Retrieve Roll status.
let roll_status = getBladesRollStatus(rolls, zeromode);
let position_localize = '';
switch (position) {
case 'controlled':
position_localize = 'BITD.PositionControlled'
break;
case 'desperate':
position_localize = 'BITD.PositionDesperate'
break;
case 'risky':
default:
position_localize = 'BITD.PositionRisky'
}
let result;
if (BladesHelpers.isAttributeAction(attribute_name)) {
let position_localize = '';
switch (position) {
case 'controlled':
position_localize = 'BITD.PositionControlled'
break;
case 'desperate':
position_localize = 'BITD.PositionDesperate'
break;
case 'risky':
default:
position_localize = 'BITD.PositionRisky'
}
let effect_localize = '';
switch (effect) {
case 'limited':
effect_localize = 'BITD.EffectLimited'
break;
case 'great':
effect_localize = 'BITD.EffectGreat'
break;
case 'standard':
default:
effect_localize = 'BITD.EffectStandard'
}
let effect_localize = '';
switch (effect) {
case 'limited':
effect_localize = 'BITD.EffectLimited'
break;
case 'great':
effect_localize = 'BITD.EffectGreat'
break;
case 'standard':
default:
effect_localize = 'BITD.EffectStandard'
}
let result = await renderTemplate("systems/blades-in-the-dark/templates/blades-roll.html", {rolls: rolls, roll_status: roll_status, attribute_label: attribute_label, position: position, position_localize: position_localize, effect: effect, effect_localize: effect_localize});
result = await renderTemplate("systems/blades-in-the-dark/templates/chat/action-roll.html", {rolls: rolls, roll_status: roll_status, attribute_label: attribute_label, position: position, position_localize: position_localize, effect: effect, effect_localize: effect_localize});
} else {
let stress = getBladesRollStress(rolls, zeromode);
result = await renderTemplate("systems/blades-in-the-dark/templates/chat/resistance-roll.html", {rolls: rolls, roll_status: roll_status, attribute_label: attribute_label, stress: stress});
}
let messageData = {
speaker: speaker,
@ -151,6 +158,57 @@ export function getBladesRollStatus(rolls, zeromode = false) {
return roll_status;
}
/**
* Get stress of the Roll.
* @param {Array} rolls
* @param {Boolean} zeromode
*/
export function getBladesRollStress(rolls, zeromode = false) {
var stress = 6;
// Dice API has changed in 0.7.0 so need to keep that in mind.
let isBelow070 = isNewerVersion('0.7.0', game.data.version);
let sorted_rolls = [];
// Sort roll values from lowest to highest.
if (isBelow070) {
sorted_rolls = rolls.map(i => i.roll).sort();
} else {
sorted_rolls = rolls.map(i => i.result).sort();
}
let roll_status = "failure"
if (sorted_rolls[0] === 6 && zeromode) {
stress = -1;
}
else {
let use_die;
let prev_use_die = false;
if (zeromode) {
use_die = sorted_rolls[0];
}
else {
use_die = sorted_rolls[sorted_rolls.length - 1];
if (sorted_rolls.length - 2 >= 0) {
prev_use_die = sorted_rolls[sorted_rolls.length - 2]
}
}
if (use_die === 6 && prev_use_die && prev_use_die === 6) {
stress = -1;
} else {
stress = 6 - use_die;
}
}
return stress;
}
/**

View file

@ -29,10 +29,6 @@ Hooks.once("init", async function() {
dice: bladesRoll
}
// Define Roll template.
// CONFIG.Dice.template = "systems/blades-in-the-dark/templates/blades-roll.html"
// CONFIG.Dice.tooltip = "systems/blades-in-the-dark/templates/blades-roll-tooltip.html"
CONFIG.Item.entityClass = BladesItem;
CONFIG.Actor.entityClass = BladesActor;

View file

@ -0,0 +1,23 @@
<div class="dice-tooltip blades-die-tooltip">
{{#if attribute_label}}<div class="chat-label label-stripe-chat">{{localize attribute_label}}</div>{{/if}}
{{#if (eq roll_status "critical-success")}}
<div class="die {{roll_status}}">{{localize "BITD.RollCriticalSuccess"}}</div>
<div class="description">
<p>{{{localize "BITD.RollResistanceCritical"}}}</p>
</div>
{{else}}
<div class="die success">{{localize "BITD.RollSuccess"}}</div>
<div class="description"><p>{{{localize "BITD.RollResistance" stress=stress}}}</p></div>
{{/if}}
<ol class="dice-rolls">
{{#each this.rolls}}
{{#if this.result}}
<li class="roll die d6">{{{this.result}}}</li>
{{else}}
<li class="roll die d6">{{{this.roll}}}</li>
{{/if}}
{{/each}}
</ol>
</div>