Okay, this is quickly copy&pasted together from one of my other scripts, but this should be a roll listener that listens to any roll starting with !modattr --sel --training_progress and gives you the dice results. on('chat:message', msg => {
let makeInlineroll = function(roll) {
let boundary = '';
switch (detectCritical(roll.results)) {
case 'crit':
boundary = ';border:2px solid #3FB315';
break;
case 'mixed':
boundary = ';border:2px solid #4A57ED';
break;
case 'fumble':
boundary = ';border:2px solid #B31515';
}
return '<div class="showtip tipsy" title="' +
'Rolling ' + htmlReplace(roll.expression) + ' = ' + rollToText(roll.results) +
'"style="display:inline-block;min-width:1em;font-size:1.2em;' +
'font-weight:bold;padding:0px 3px;cursor:help' + boundary + '">' +
(roll.results.total || 0) + '</div>';
},
rollToText = function(roll) {
switch (roll.type) {
case 'R':
let c = (roll.mods && roll.mods.customCrit) || [{
comp: '==',
point: roll.sides
}],
f = (roll.mods && roll.mods.customFumble) || [{
comp: '==',
point: 1
}],
styledRolls = _.map(roll.results, function(r) {
let style = rollIsCrit(r.v, c[0].comp, c[0].point) ?
' critsuccess' :
(rollIsCrit(r.v, f[0].comp, f[0].point) ?
' critfail' : '')
return `<span class='basicdiceroll${style}'>${r.v}</span>`;
});
return `(${styledRolls.join('+')})`;
break;
case 'M':
return roll.expr.toString().replace(/(\+|-)/g, '$1 ').replace(/\*/g, '&' + 'ast' + ';');
break;
case 'V':
return _.map(roll.rolls, rollToText).join(' ');
break;
case 'G':
return '(' + _.map(roll.rolls, a => _.map(a, rollToText).join(' '))
.join(' ') + ')';
break;
default:
return '';
}
},
detectCritical = function(roll) {
let s = [];
if (roll.type === 'V' && _.has(roll, 'rolls')) {
s = _.map(roll.rolls, detectCritical);
} else if (roll.type === 'G' && _.has(roll, 'rolls')) {
s = _.chain(roll.rolls)
.map(a => _.map(a, detectCritical))
.flatten()
.value();
} else if (roll.type === 'R' && _.has(roll, 'sides')) {
let crit = (roll.mods && roll.mods.customCrit) || [{
comp: '==',
point: roll.sides
}];
let fumble = (roll.mods && roll.mods.customFumble) || [{
comp: '==',
point: 1
}];
if (_.some(roll.results, r => rollIsCrit(r.v, crit[0].comp, crit[0].point))) {
s.push('crit');
}
if (_.some(roll.results, r => rollIsCrit(r.v, fumble[0].comp, fumble[0].point))) {
s.push('fumble');
}
}
let c = _.contains(s, 'crit');
let f = _.contains(s, 'fumble');
let m = _.contains(s, 'mixed') || (c && f);
return (m ? 'mixed' : (c ? 'crit' : (f ? 'fumble' : (false))));
},
rollIsCrit = function(value, comp, point) {
switch (comp) {
case '==':
return value == point;
break;
case '<=':
return value <= point;
break;
case '>=':
return value >= point;
}
},
htmlReplace = function(str) {
let entities = {
'<': 'lt',
'>': 'gt',
"'": '#39',
'@': '#64',
'{': '#123',
'|': '#124',
'}': '#125',
'[': '#91',
'"': 'quot',
']': '#93',
'*': '#42'
};
return _.map(str.split(''), c => (_.has(entities, c)) ? ('&' + entities[c] + ';') : c)
.join('');
};
if (msg.content && msg.content.indexOf('!modattr --sel --training_progress') === 0 && msg.inlinerolls) {
let output = '/w GM Dice rolls were ' + msg.inlinerolls.map(roll => makeInlineroll(roll)).join(', ');
sendChat('API', output);
}
});