function processInlinerolls(msg) {
if (_.has(msg, 'inlinerolls')) {
return _.chain(msg.inlinerolls)
.reduce(function(previous, current, index) {
previous['$[[' + index + ']]'] = current.results || 0;
return previous;
},{})
.reduce(function(previous, current, index) {
return previous.replace(index, current);
}, msg.content)
.value();
} else {
return msg.content;
}
}
function Semaphore(callback, initial, context) {
var args = (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments));
this.lock = parseInt(initial, 10) || 0;
this.callback = callback;
this.context = context || callback;
this.args = args.slice(3);
}
Semaphore.prototype = {
v: function() { this.lock++; },
p: function() {
var parameters;
this.lock--;
if (this.lock === 0 && this.callback) {
// allow sem.p(arg1, arg2, ...) to override args passed to Semaphore constructor
if (arguments.length > 0) { parameters = arguments; }
else { parameters = this.args; }
this.callback.apply(this.context, parameters);
}
}
};
function getSenderForName(name, options) {
var character = findObjs({
type: 'character',
name: name
}, options)[0],
player = findObjs({
type: 'player',
displayname: name.lastIndexOf(' (GM)') === name.length - 5 ? name.substring(0, name.length - 5) : name
}, options)[0];
if (player) {
return 'player|' + player.id;
}
if (character) {
return 'character|' + character.id;
}
return name;
}
var ABFRoll = ABFRoll || (function() {
'use strict';
var who;
var rollType = "";
var template = "";
var name = "";
var subname = "";
var arrayCrit = [];
var upperCrit = 90;
var lowerFumble = 3;
var firstResult = 0;
var bonus = 0;
var critique = false;
var fumble = false;
var noCrit = false;;
var mastery = false;
var detailDice = "";
var numberDice = 1;
var double = 0;
var total = 0;
var modFumble = 0;
var arrayAttack = [];
var arrayBlock = [];
var arrayDodge = [];
var arrayProjOff = [];
var arrayProjDef = [];
var arrayProj = [];
var semChat = new Semaphore(function(lastAsync)
{
sendChat(who, rollType+'&{template:'+template+'} '+lastAsync);
total = 0;
double = 0;
critique = false;
fumble = false;
bonus = 0;
numberDice = 1;
detailDice = "";
rollType = "";
name = "";
subname = "";
arrayCrit = [];
});
var sem = new Semaphore(function(lastAsync)
{
var dice = Number(lastAsync);
if(critique == true)
{
numberDice += 1;
detailDice += "+"+dice;
total += dice;
if(double > 0)
{
if(numberDice != 3)
{
if(arrayCrit.indexOf(dice) == double)
{
sendChat('', "/roll 1d100", function(diceResult)
{
sem.v();
var msgContent = JSON.parse(diceResult[0].content);
var result = msgContent.total;
sem.p(result);
});
}
else
{
sendResult();
}
}
else if(numberDice == 3)
{
detailDice = "100";
total = 100;
sendResult();
}
}
else
{
if(dice >= upperCrit)
{
if(upperCrit >= 100)
upperCrit = 100;
else
upperCrit += 1;
sendChat('', "/roll 1d100", function(diceResult)
{
sem.v();
var msgContent = JSON.parse(diceResult[0].content);
var result = msgContent.total;
sem.p(result);
});
}
else
{
sendResult();
}
}
}
else if(fumble == true)
{
if(mastery == true)
{
if(firstResult >= 2)
modFumble = 15;
else if(firstResult == 1)
modFumble = 0;
}
else
{
if(firstResult >= 3)
modFumble = 15;
else if(firstResult == 2)
modFumble = 0;
else if(firstResult == 1)
modFumble = -15;
}
total = modFumble-dice;
detailDice = dice;
sendResult();
}
});
var inlineRolls = function(msg)
{
var index = -1;
for(var i = 0;i < msg.inlinerolls.length;i++)
{
if(msg.inlinerolls[i].expression.match(/1d100[A-z0-9]+/) || msg.inlinerolls[i].expression.match(/0d100[A-z0-9]+/))
{
index = i;
}
}
return index;
};
var turnOrder = function(tot)
{
var aName = "";
var aName = name.toString();
aName = aName.replace("{{name=", "");
aName = aName.replace("}}", "");
var turnorder;
if(Campaign().get("turnorder") == "") turnorder = []; //NOTE: We check to make sure that the turnorder isn't just an empty string first. If it is treat it like an empty array.
else turnorder = JSON.parse(Campaign().get("turnorder"));
var found = false;
for(var i=0; i < turnorder.length; ++i)
{
if(aName === turnorder[i].custom)
{
turnorder[i].pr=tot;
found=true;
break;
}
}
if(!found)
{
//Add a new custom entry to the end of the turn order.
turnorder.push({
id: "-1",
pr: tot,
custom: aName
});
}
turnorder = _.sortBy(turnorder, (t) => -parseInt(t.pr));
//If the initiative window is not displayed, open it.
Campaign().set('initiativepage',true);
Campaign().set("turnorder", JSON.stringify(turnorder));
};
var customCF = function(array)
{
var type;
for(var i = 0;i < array.customCrit.length;i++)
{
type = array.customCrit[i].comp;
if(type == "==")
{
arrayCrit.push(array.customCrit[i].point);
}
if(type == ">=")
{
upperCrit = array.customCrit[i].point;
}
}
for(var i = 0;i < array.customFumble.length;i++)
{
type = array.customFumble[i].comp;
if(type == "<=")
{
lowerFumble = array.customFumble[i].point;
}
}
};
var getMastery = function(msg)
{
var index = -1;
var inCalc = "";
for(var i = 0;i < msg.inlinerolls.length;i++)
{
if(msg.inlinerolls[i].expression.match(/[0-9]+\+[0-9]+\+[0-9]+\-[0-9]+/))
{
index = i;
}
}
if(index != -1)
{
inCalc = msg.inlinerolls[index].expression.split("-");
if(inCalc[1] == "1")
{
mastery = true;
}
}
};
var traitement = function()
{
var nResult = Number(firstResult);
detailDice = firstResult;
if(noCrit != true)
{
if(arrayCrit.indexOf(firstResult) != -1)
{
critique = true;
double = arrayCrit.indexOf(firstResult);
}
else if(nResult >= upperCrit)
{
critique = true;
upperCrit += 1;
}
else if(nResult <= lowerFumble)
fumble = true;
total = nResult;
if(critique == true)
{
sendChat('', "/roll 1d100", function(diceResult)
{
sem.v();
var msgContent = JSON.parse(diceResult[0].content);
var result = msgContent.total;
sem.p(result);
});
}
else if(fumble == true)
{
sendChat('', "/roll 1d100", function(diceResult)
{
sem.v();
var msgContent = JSON.parse(diceResult[0].content);
var result = msgContent.total;
sem.p(result);
});
}
else
{
sendResult();
}
}
else
{
sendResult();
}
};
var sendResult = function()
{
var sendBonus = +bonus;
var sendTotal = total+sendBonus;
var spec = "";
var aName = "";
var aName = name.toString();
aName = aName.replace("{{name=", "");
aName = aName.replace("}}", "");
if(critique == true)
spec = 'style="color:green;"'
else if(fumble == true)
spec = 'style="color:red;"'
if(subname == "{{subname=^{attack}}}")
{
var length = arrayAttack.length;
arrayAttack.push("{{^{attack} ("+length+")=["+aName+"("+sendTotal+")](!ABFCompare;attack;"+aName+";"+sendTotal+";?{Opponent's result|0};?{AT/IP|0})}}");
}
else if(subname == "{{subname=^{block}}}")
{
var length = arrayBlock.length;
arrayBlock.push("{{^{block} ("+length+")=["+aName+"("+sendTotal+")](!ABFCompare;block;"+aName+";"+sendTotal+";?{Opponent's result|0};?{AT/IP|0})}}");
}
else if(subname == "{{subname=^{dodge}}}")
{
var length = arrayDodge.length;
arrayDodge.push("{{^{dodge} ("+length+")=["+aName+"("+sendTotal+")](!ABFCompare;dodge;"+aName+";"+sendTotal+";?{Opponent's result|0};?{AT/IP|0})}}");
}
else if(subname == "{{subname=^{magic-projection} (^{offensive})}}")
{
var length = arrayProjOff.length;
arrayProjOff.push("{{^{magic-projection} (^{offensive}) ("+length+")=["+aName+"("+sendTotal+")](!ABFCompare;projoff;"+aName+";"+sendTotal+";?{Opponent's result|0};?{AT/IP|0})}}");
}
else if(subname == "{{subname=^{magic-projection} (^{defensive})}}")
{
var length = arrayProjDef.length;
arrayProjDef.push("{{^{magic-projection} (^{defensive}) ("+length+")=["+aName+"("+sendTotal+")](!ABFCompare;projdef;"+aName+";"+sendTotal+";?{Opponent's result|0};?{AT/IP|0})}}");
}
else if(subname == "{{subname=^{psychic-projection}}}")
{
var length = arrayProj.length;
arrayProj.push("{{^{psychic-projection} ("+length+")=["+aName+"("+sendTotal+")](!ABFCompare;proj;"+aName+";"+sendTotal+";?{Opponent's result|0};?{AT/IP|0};?{Attack or Defense ?|Attack,att|Defense,def})}}");
}
if(subname == "{{subname=^{initiative}}}")
{
turnOrder(sendTotal);
}
if(noCrit != true)
{
if(fumble == true)
{
sendChat('', name+' '+subname+' {{result='+sendTotal+'}}', function(R)
{
semChat.v();
var msgContent = R[0].content;
semChat.p(msgContent);
});
}
else
{
sendChat('', name+' '+subname+' {{result='+sendTotal+'}}', function(R)
{
semChat.v();
var msgContent = R[0].content;
semChat.p(msgContent);
});
}
}
else
{
sendChat('', name+' '+subname+' {{result='+sendTotal+'}}', function(R)
{
semChat.v();
var msgContent = R[0].content;
semChat.p(msgContent);
});
}
};
var listen = function ()
{
on("chat:message", function (msg) {
/* Exit if not an api command */
if (msg.type != "api") return;
var str = msg.content;
if(str.startsWith("!ABFAPI") == true)
{
who = getSenderForName(msg.who);
total = 0;
bonus = 0;
str = str.replace("!ABFAPI", "");
//TYPE DE JETS
if(str.includes("/w gm ") == true || playerIsGM(msg.playerid))
{
rollType = "/w gm ";
str = str.replace("/w gm ", "");
}
if(str.includes("Public Roll") == true)
{
str = str.replace("Public Roll", "");
}
//NOM PERSONNAGE
name = str.match(/{{name=[\-\'(){}^a-zA-Z0-9ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ_\s]+}}/);
str = str.replace(/{{name=[\-\'(){}^a-zA-Z0-9ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ_\s]+}}/, "");
//TEMPLATE
template = msg.rolltemplate;
//NOM JET
subname = str.match(/{{subname=[\-\'(){}^a-zA-Z0-9ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ_\s]+}}/);
str = str.replace(/{{subname=[\-\'(){}^a-zA-Z0-9ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ_\s]+}}/, "");
//traitement du jet
var roll = msg.inlinerolls[inlineRolls(msg)];
customCF(roll.results.rolls[0].mods);
//Maîtrise ?
getMastery(msg);
if(roll.results.rolls[0].dice > 0)
firstResult = roll.results.rolls[0].results[0].v;
else
{
firstResult = 0;
noCrit = true;
}
var bonusToSplit = 0+roll.results.rolls[1].expr;
var bonusSplit = bonusToSplit.split("+");
for(var i = 0;i < bonusSplit.length;i++)
{
bonus += Number(bonusSplit[i]);
}
//NETTOYAGE
str = str.replace(/{{result=[${}^A-z0-9\s]+}}/, "");
traitement();
}
if(str.startsWith("!ABFCompare") == true)
{
str = processInlinerolls(msg);
var split = str.split(";");
var type = split[1];
var compName = split[2];
var compTotal = Number(split[3]);
var opposed = Number(split[4]);
var IP = Number(split[5]);
var spec = split[6];
var absorption = 2*10;
var marge = 0;
var degats = 0;
var dStr = "";
var contreA = 0;
var CAStr = "";
switch(type)
{
case "attack":
marge = compTotal-opposed;
type = "^{attack}";
break;
case "block":
marge = opposed-compTotal;
type = "^{block}";
break;
case "dodge":
marge = opposed-compTotal;
type = "^{dodge}";
break;
case "projoff":
marge = compTotal-opposed;
type = "^{magic-projection} (^{offensive})";
break;
case "projdef":
marge = opposed-compTotal;
type = "^{magic-projection} (^{defensive})";
break;
case "proj":
if(spec == "att")
marge = compTotal-opposed;
else if(spec == "def")
marge = opposed-compTotal;
type = "^{psychic-projection}";
break;
}
if(marge > 0)
{
degats = marge-absorption-(IP*10);
degats = Math.floor(degats/10)*10;
dStr = "{{dmg="+degats+"%}}";
}
else if(marge == 0)
{
}
else if(marge < 0)
{
contreA = Math.floor((marge/2)/5)*5
contreA = contreA*-1;
if(contreA > 150)
contreA = 150;
CAStr = "{{contreA="+contreA+"}}"
}
var msgSend = "/w gm &{template:APICompare} {{name="+compName+"}} {{subtitle="+type+"}} {{marge="+marge+"}} {{IP="+IP+"}} "+dStr+" "+CAStr;
sendChat("System", msgSend);
}
if(str.startsWith("!ABFList") == true)
{
var list = "";
list = arrayAttack.join(" ");
list = list+" "+arrayBlock.join(" ");
list = list+" "+arrayDodge.join(" ");
list = list+" "+arrayProjOff.join(" ");
list = list+" "+arrayProjDef.join(" ");
list = list+" "+arrayProj.join(" ");
sendChat("System", "/w gm &{template:APIList} "+list);
}
if(str.startsWith("!ABFClean") == true)
{
sendChat("System", "/w gm clean list");
arrayAttack.splice(0,arrayAttack.length);
arrayBlock.splice(0,arrayBlock.length);
arrayDodge.splice(0,arrayDodge.length);
arrayProjOff.splice(0,arrayProjOff.length);
arrayProjDef.splice(0,arrayProjDef.length);
arrayProj.splice(0,arrayProj.length);
}
});
};
return {
Listen: listen
};
}());
on("ready", function()
{
ABFRoll.Listen();
});