Skip to content

Instantly share code, notes, and snippets.

@Lithl
Created December 7, 2016 06:42
Show Gist options
  • Save Lithl/993b9bc4fac029e9dd180d4530635946 to your computer and use it in GitHub Desktop.
Save Lithl/993b9bc4fac029e9dd180d4530635946 to your computer and use it in GitHub Desktop.
Unfinished sample of a Roll20 API script for rolling Armello-style dice. The main takeaway is from the `orderFaces` function, which changes the order of the six die faces (sword, shield, sun, moon, wyld, rot) and sets an explode point based on which of those faces should explode.
var bshields = bshields || {};
bshields.armello = (function() {
'use strict';
var version = 0.1,
commands = {
armello: function(args, msg) {
var flags = processFlags(args);
resolveCombat({pool:flags.pool[0],explodesword:flags.explodesword[0],explodesun:flags.explodesun[0],explodemoon:flags.explodemoon[0]},
{pool:flags.pool[1],explodesword:flags.explodesword[0],explodesun:flags.explodesun[0],explodemoon:flags.explodemoon[0]});
},
armelloattack: function(args, msg) {
var flags = processFlags(args);
},
armellodefend: function(args, msg) {
var flags = processFlags(args);
},
help: function(command, args, msg) {
if (_.isFunction(commands[`help_${command}`])) {
commands[`help_${command}`](args, msg);
}
}
};
function resolveCombat(attack, defend, isDay) {
var attackFaces = orderFaces(attack),
defendFaces = orderFaces(defend),
attackExplodePoint = attackFaces.explodePoint,
defendExplodePoint = defendFaces.explodePoint;
attackFaces = attackFaces.faces;
defendFaces = defendFaces.faces;
sendChat('', `/r ${attack.pool}d6!>${attackExplodePoint}`, function(ops) {
var rollresult = JSON.parse(ops[0].content).rolls[0].results,
attackResult = calcHitsBlocks(rollresult, attackFaces, isDay, attack.corrupted);
log(`Attack hits: ${attackResult.hits}`);
log(`Attack blocks: ${attackResult.blocks}`);
sendChat('', `/r ${defend.pool}d6!>${defendExplodePoint}`, function(ops) {
var rollresult = JSON.parse(ops[0].content).rolls[0].results,
defendResult = calcHitsBlocks(rollresult, defendFaces, isDay, defend.corrupted);
log(`Defend hits: ${defendResult.hits}`);
log(`Defend blocks: ${defendResult.blocks}`);
});
});
}
function calcHitsBlocks(rollresult, faces, isDay, isCorrupted) {
var hits = 0,
blocks = 0;
_.each(rollresult, function(die) {
var face = faces[die.v - 1];
switch (face) {
case 'Sword':
hits++;
break;
case 'Shield':
blocks++;
break;
case 'Sun':
if (isDay) hits++;
break;
case 'Moon':
if (!isDay) hits++;
break;
case 'Wyld':
if (!isCorrupted) hits++;
break;
case 'Rot':
if (isCorrupted) hits++;
break;
}
});
return {
hits: hits,
blocks: blocks
};
}
function orderFaces(flags) {
var faces = ['Shield'],
explodePoint = 3;
if (flags.corrupted) {
faces.push('Rot');
faces.unshift('Wyld');
} else {
faces.push('Wyld');
faces.unshift('Rot');
}
if (flags.ruby || flags.explodesword) {
faces.push('Sword');
} else {
faces.unshift('Sword');
explodePoint++;
}
if (flags.aflame || flags.explodesun) {
faces.push('Sun');
} else {
faces.unshift('Sun');
explodePoint++;
}
if (flags.moonscythe || flags.explodemoon) {
faces.push('Moon');
} else {
faces.unshift('Moon');
explodePoint++;
}
return {
faces: faces,
explodePoint: explodePoint
};
}
function processFlags(args) {
var flags = { noFlag: [] },
tmp = null;
_.each(args, function(arg) {
if (arg.indexOf('--') === 0) {
if (tmp !== null) {
if (flags[tmp]) flags[tmp].push('true');
else flags[tmp] = ['true'];
}
tmp = arg.substring(2).toLowerCase();
} else {
if (tmp === null) {
flags.noFlag.push(arg);
} else {
if (flags[tmp]) flags[tmp].push(arg);
else flags[tmp] = [arg];
}
tmp = null;
}
});
if (tmp !== null) {
if (flags[tmp]) flags[tmp].push('true');
else flags[tmp] = ['true'];
}
_.each(flags, function(f, k, o) {
o[k] = _.map(f, (s) => s.toLowerCase() === 'true' ? true : s.toLowerCase() === 'false' ? false : s);
});
return flags;
}
function processInlinerolls(msg) {
if (_.has(msg, 'inlinerolls')) {
return _.chain(msg.inlinerolls)
.reduce(function(m, v, k) {
var ti = _.reduce(v.results.rolls, function(m2, v2) {
if(_.has(v2, 'table')) {
m2.push(_.reduce(v2.results, function(m3, v3) {
m3.push(v3.tableItem.name);
return m3;
}, []).join(', '));
}
return m2;
}, []).join(', ');
m['$[['+k+']]'] = (ti.length && ti) || v.results.total || 0;
return m;
}, {})
.reduce(function(m, v, k) {
return m.replace(k,v);
}, msg.content)
.value();
} else {
return msg.content;
}
}
function handleInput(msg) {
var isApi = msg.type === 'api',
args = processInlinerolls(msg).trim().splitArgs(),
command, arg0, isHelp;
if (isApi) {
command = args.shift().substring(1).toLowerCase();
arg0 = args.shift() || '';
isHelp = arg0.toLowerCase() === 'help' || arg0.toLowerCase() === 'h' || command === 'help';
if (!isHelp) {
if (arg0 && arg0.length > 0) {
args.unshift(arg0);
}
if (_.isFunction(commands[command])) {
commands[command](args, msg);
}
} else if (_.isFunction(commands.help)) {
commands.help(command === 'help' ? arg0 : command, args, msg);
}
} else if (_.isFunction(commands[`msg_${msg.type}`])) {
commands[`msg_${msg.type}`](args, msg);
}
}
function checkInstall() {
if (!state.bshields ||
!state.bshields.armello ||
!state.bshields.armello.version ||
state.bshields.armello.version !== version) {
state.bshields = state.bshields || {};
state.bshields.armello = {
version: version,
gcUpdated: 0,
config: {}
};
}
checkGlobalConfig();
}
function checkGlobalConfig() {
var gc = globalconfig && globalconfig['armellodice'],
st = state.bshields.armello;
if (gc && gc.lastsaved && gc.lastsaved > st.gcUpdated) {
st.gcUpdated = gc.lastsaved;
}
}
function registerEventHandlers() {
on('chat:message', handleInput);
}
return {
registerEventHandlers: registerEventHandlers,
checkInstall: checkInstall
};
}());
on('ready', function() {
'use strict';
bshields.armello.checkInstall();
bshields.armello.registerEventHandlers();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment