
Based on the code by J. Ryan Littlefield
This expands the roll detection to include (limited) in-line rolls and GURPS crit detection (always on) and GURPS deceptive attack target numbers.
DA will take a two digit target level between 10 and 16 (inclusive) and if the target expression is above that by at least two it will lower the target number by increments of two until it is equal to or one above the number. This is useful for high skill deceptive/predictive attacks to automatically use their high skill to make defense more difficult.
/roll 3d6 |da##| target expression
Inline:
[[3d6 da## target expression]]
Regular inline rolls can be done two ways:
[[3d6 gr target expression]]
[[dice <= target expression]]
The old roll syntax works as well, although the gurps crit detect is always on.
/roll dice |<=| target expression
I was going to make it only do the GURPS crit detect on a "gr" operator for both, but my group decided to go back to maptools for now. Other operators will work for the /roll x |op| y method, only the GURPS ones and <= work for inline.
/*
Copyright (c) 2013 J. Ryan Littlefield
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Additions and Alterations:
Copyright (c) 2014 Theodore Briggs
*/
on("chat:message", function(msg) {
//log(msg);
var chatMessage = '';
var validRoll = 0;
var rolls = [{expression:"",oper:'<=',total:0}];
if (msg.type == 'general') {
var inlineroll = null;
try {
inlineroll = msg.inlinerolls;
} catch (e) {
log(e);
return;
}
//log(inlineroll);
if(inlineroll) {
for(var i = 0; i < inlineroll.length;i++) {
if(inlineroll[i]) {
var loc = inlineroll[i].expression.indexOf('3d6 gr');
if(rolls[validRoll] == null) {
rolls[validRoll] = {expression:"",oper:'<=',total:0};
}
if(loc !== -1) {
rolls[validRoll].expression = inlineroll[i].expression.substring(loc+6);
rolls[validRoll].total = inlineroll[i].results.total;
rolls[validRoll].oper = '<=';
validRoll++;
}
loc = inlineroll[i].expression.indexOf('3d6 da');
if(loc !== -1) {
rolls[validRoll].expression = inlineroll[i].expression.substring(loc+8);
rolls[validRoll].oper = inlineroll[i].expression.substring(loc+4,loc+8);
rolls[validRoll].total = inlineroll[i].results.total;
validRoll++;
//log(expression);
//log(oper);
}
loc = inlineroll[i].expression.indexOf('<=');
if(loc !== -1) {
rolls[validRoll].expression = inlineroll[i].expression.substring(loc+2);
rolls[validRoll].total = inlineroll[i].results.total;
rolls[validRoll].oper = '<=';
validRoll++;
}
}
}
}
}
if (msg.type == 'rollresult' || msg.type == 'gmrollresult') {
var parts = msg.origRoll.split('|');
if (parts.length < 3) {
return;
}
rolls[validRoll].oper = parts[1];
rolls[validRoll].expression = parts[2];
//log(expression);
var content = JSON.parse(msg.content);
rolls[validRoll].total = content.total;
validRoll++;
}
var character;
var characters;
var expression;
var oper;
var target;
var deceptiveAttack;
var result = null;
var delimit = '';
for(curRoll = 0; curRoll < validRoll;curRoll++) {
expression = rolls[curRoll].expression;
oper = rolls[curRoll].oper;
total = rolls[curRoll].total;
characters = findObjs({
_type: "character",
name: msg.who
});
character = characters.shift();
if (character) {
var attributes = findObjs({
_type: "attribute",
_characterid: character.get('_id')
});
for (var i = 0; i < attributes.length; i++) {
var current_attribute = attributes[i];
//log ('@'+current_attribute.get('name') + '=' + current_attribute.get('current'));
expression = expression.replace('@'+current_attribute.get('name'), current_attribute.get('current'));
}
}
//log(expression);
try {
target = Math.abs(eval(expression));
} catch (e) {
log(e);
}
result = null;
var DAText = '';
if(oper.indexOf('da') == 0) {
deceptiveAttack = parseInt(oper.substring(2,4));
oper = '<=';
if(deceptiveAttack < 10 ) {
deceptiveAttack = 10;
}
if (deceptiveAttack > 16) {
deceptiveAttack = 16;
}
//log('DA'+deceptiveAttack)
var DALevel = Math.floor((target - deceptiveAttack) / 2);
if(DALevel > 0) {
target = target - 2 * DALevel;
DAText = ' with auto DA -' + DALevel + ' to defenses.';
}
}
var new_expression = 'result = (' + total + ' ' + oper + ' ' + target + ');';
//log(new_expression);
try {
eval(new_expression);
} catch (e) {
log(e);
}
var difference = Math.abs(total - target);
if(result) {
if ((difference >= 10) && (total <= 6) || (total <= 4)) {
chatMessage = chatMessage+delimit+'<b>Critical Success by '+difference+DAText+'</b>';
} else {
chatMessage = chatMessage+delimit+'Success by '+difference+DAText;
}
} else {
if ((difference >= 10) || ((difference > 1) && (total == 17)) || (total == 18)) {
chatMessage = chatMessage+delimit+'<b>Critical Failure by '+difference+DAText+'</b>';
} else {
chatMessage = chatMessage+delimit+'Failure by '+difference+DAText;
}
}
delimit = ' : '
}
if(chatMessage != '') {
switch (msg.type) {
case 'gmrollresult':
var whisper_origin = true;
var who;
try {
who = msg.who.split(' ');
who = who[0];
} catch (e) {
whisper_origin = false;
sendChat('RollResult', '/w gm Failure to find player by name "'+msg.who+'". Try making them remove spaces from their name.');
return;
}
if (msg.who.indexOf('(GM)') !== -1) {
whisper_origin = false;
}
if (result) {
sendChat('RollResult', '/w gm '+chatMessage);
if (whisper_origin) {
sendChat('RollResult', '/w ' + who + ' '+chatMessage);
}
} else {
sendChat('RollResult', '/w gm '+chatMessage);
if (whisper_origin) {
sendChat('RollResult', '/w ' + who + ' '+chatMessage);
}
}
break;
default:
if (result) {
sendChat('RollResult', chatMessage);
} else {
sendChat('RollResult', chatMessage);
}
break;
}
}
});
This expands the roll detection to include (limited) in-line rolls and GURPS crit detection (always on) and GURPS deceptive attack target numbers.
DA will take a two digit target level between 10 and 16 (inclusive) and if the target expression is above that by at least two it will lower the target number by increments of two until it is equal to or one above the number. This is useful for high skill deceptive/predictive attacks to automatically use their high skill to make defense more difficult.
/roll 3d6 |da##| target expression
Inline:
[[3d6 da## target expression]]
Regular inline rolls can be done two ways:
[[3d6 gr target expression]]
[[dice <= target expression]]
The old roll syntax works as well, although the gurps crit detect is always on.
/roll dice |<=| target expression
I was going to make it only do the GURPS crit detect on a "gr" operator for both, but my group decided to go back to maptools for now. Other operators will work for the /roll x |op| y method, only the GURPS ones and <= work for inline.
/*
Copyright (c) 2013 J. Ryan Littlefield
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Additions and Alterations:
Copyright (c) 2014 Theodore Briggs
*/
on("chat:message", function(msg) {
//log(msg);
var chatMessage = '';
var validRoll = 0;
var rolls = [{expression:"",oper:'<=',total:0}];
if (msg.type == 'general') {
var inlineroll = null;
try {
inlineroll = msg.inlinerolls;
} catch (e) {
log(e);
return;
}
//log(inlineroll);
if(inlineroll) {
for(var i = 0; i < inlineroll.length;i++) {
if(inlineroll[i]) {
var loc = inlineroll[i].expression.indexOf('3d6 gr');
if(rolls[validRoll] == null) {
rolls[validRoll] = {expression:"",oper:'<=',total:0};
}
if(loc !== -1) {
rolls[validRoll].expression = inlineroll[i].expression.substring(loc+6);
rolls[validRoll].total = inlineroll[i].results.total;
rolls[validRoll].oper = '<=';
validRoll++;
}
loc = inlineroll[i].expression.indexOf('3d6 da');
if(loc !== -1) {
rolls[validRoll].expression = inlineroll[i].expression.substring(loc+8);
rolls[validRoll].oper = inlineroll[i].expression.substring(loc+4,loc+8);
rolls[validRoll].total = inlineroll[i].results.total;
validRoll++;
//log(expression);
//log(oper);
}
loc = inlineroll[i].expression.indexOf('<=');
if(loc !== -1) {
rolls[validRoll].expression = inlineroll[i].expression.substring(loc+2);
rolls[validRoll].total = inlineroll[i].results.total;
rolls[validRoll].oper = '<=';
validRoll++;
}
}
}
}
}
if (msg.type == 'rollresult' || msg.type == 'gmrollresult') {
var parts = msg.origRoll.split('|');
if (parts.length < 3) {
return;
}
rolls[validRoll].oper = parts[1];
rolls[validRoll].expression = parts[2];
//log(expression);
var content = JSON.parse(msg.content);
rolls[validRoll].total = content.total;
validRoll++;
}
var character;
var characters;
var expression;
var oper;
var target;
var deceptiveAttack;
var result = null;
var delimit = '';
for(curRoll = 0; curRoll < validRoll;curRoll++) {
expression = rolls[curRoll].expression;
oper = rolls[curRoll].oper;
total = rolls[curRoll].total;
characters = findObjs({
_type: "character",
name: msg.who
});
character = characters.shift();
if (character) {
var attributes = findObjs({
_type: "attribute",
_characterid: character.get('_id')
});
for (var i = 0; i < attributes.length; i++) {
var current_attribute = attributes[i];
//log ('@'+current_attribute.get('name') + '=' + current_attribute.get('current'));
expression = expression.replace('@'+current_attribute.get('name'), current_attribute.get('current'));
}
}
//log(expression);
try {
target = Math.abs(eval(expression));
} catch (e) {
log(e);
}
result = null;
var DAText = '';
if(oper.indexOf('da') == 0) {
deceptiveAttack = parseInt(oper.substring(2,4));
oper = '<=';
if(deceptiveAttack < 10 ) {
deceptiveAttack = 10;
}
if (deceptiveAttack > 16) {
deceptiveAttack = 16;
}
//log('DA'+deceptiveAttack)
var DALevel = Math.floor((target - deceptiveAttack) / 2);
if(DALevel > 0) {
target = target - 2 * DALevel;
DAText = ' with auto DA -' + DALevel + ' to defenses.';
}
}
var new_expression = 'result = (' + total + ' ' + oper + ' ' + target + ');';
//log(new_expression);
try {
eval(new_expression);
} catch (e) {
log(e);
}
var difference = Math.abs(total - target);
if(result) {
if ((difference >= 10) && (total <= 6) || (total <= 4)) {
chatMessage = chatMessage+delimit+'<b>Critical Success by '+difference+DAText+'</b>';
} else {
chatMessage = chatMessage+delimit+'Success by '+difference+DAText;
}
} else {
if ((difference >= 10) || ((difference > 1) && (total == 17)) || (total == 18)) {
chatMessage = chatMessage+delimit+'<b>Critical Failure by '+difference+DAText+'</b>';
} else {
chatMessage = chatMessage+delimit+'Failure by '+difference+DAText;
}
}
delimit = ' : '
}
if(chatMessage != '') {
switch (msg.type) {
case 'gmrollresult':
var whisper_origin = true;
var who;
try {
who = msg.who.split(' ');
who = who[0];
} catch (e) {
whisper_origin = false;
sendChat('RollResult', '/w gm Failure to find player by name "'+msg.who+'". Try making them remove spaces from their name.');
return;
}
if (msg.who.indexOf('(GM)') !== -1) {
whisper_origin = false;
}
if (result) {
sendChat('RollResult', '/w gm '+chatMessage);
if (whisper_origin) {
sendChat('RollResult', '/w ' + who + ' '+chatMessage);
}
} else {
sendChat('RollResult', '/w gm '+chatMessage);
if (whisper_origin) {
sendChat('RollResult', '/w ' + who + ' '+chatMessage);
}
}
break;
default:
if (result) {
sendChat('RollResult', chatMessage);
} else {
sendChat('RollResult', chatMessage);
}
break;
}
}
});