I wrote up a very simple version of what could be possible. If reroll of 1's don't always happen then I will have to rework the script so you can give it the option. This is to show you what can be done with scripts fairly easily. Later I could make it have fancy output and more options if needed. Or someone else could improve it even more like being able to take the rolls and pass them to Roll20 properly so you get a consistant look and feel to all the rolls, but thats beyond me at the moment. I'll try and add the option to turn reroll of 1's on/off tomorrow. Gotta go to bed now. :) I'll add who rolled it as well of course. This was just a quick test. // Legend of the Five Rings 4e Dice Mechanic // // copyright pug games 2014 // please feel free to use this script, change it, add to it in any way you feel // Script created by Roll20 user Konrad J. var fwCONSTANTS = { COMMANDSEPERATOR : " ", GMIDS : ["all"], //put your Roll20 UserID# here "77736" l5r4eSCRIPTCOMMAND : "!!" }; var fwGlobal = { logToConsoleOn : false }; function fwLtC(logMsg){ if (fwGlobal.logToConsoleOn === true) { log(logMsg); } } function fwIsGM(playerid) { var player = getObj('player', playerid); var d20userid = player.get('_d20userid'); var IsGM = false; if (fwCONSTANTS.GMIDS.indexOf(d20userid) >= 0 || fwCONSTANTS.GMIDS.indexOf("all") >= 0) { IsGM = true; } fwLtC("Is GM: " + IsGM); return IsGM; } on("chat:message", function(msg) { // returns the chat window command entered if (msg.type != 'api') { return; } fwLtC("Chat Msg: " + msg); var chatCommand = msg.content; var script = chatCommand.substr(0, chatCommand.indexOf(fwCONSTANTS.COMMANDSEPERATOR)); chatCommand = chatCommand.replace(script + fwCONSTANTS.COMMANDSEPERATOR, ""); fwLtC("Script: " + script); fwLtC("Chat Command: " + chatCommand); switch(script) { case fwCONSTANTS.l5r4eSCRIPTCOMMAND: if (fwIsGM(msg.playerid) === true) { processL5r4eDice(chatCommand); } break; } }); function processL5r4eDice(chatCommand){ var diceToRoll = { diceQty : 0, diceKeep : 0 }; var x = chatCommand.indexOf("k"); var diceRolled = new Array(); var i = 0; var diceResult = 0; var diceRolledFull = ""; if (x >= 0) { diceToRoll.diceQty = parseInt(chatCommand.slice(0,x),10); diceToRoll.diceKeep = parseInt(chatCommand.slice(x+1),10); fwLtC(diceToRoll.diceQty + "," + diceToRoll.diceKeep); } fwLtC("DiceQty", diceToRoll.diceQty.toString()); fwLtC("DiceKeep", diceToRoll.diceKeep.toString()); for (i=0, diceToRoll.diceQty;i<diceToRoll.diceQty;i++){ diceRolled[i] = randomInteger(10); diceRolledFull = diceRolledFull + diceRolled[i].toString(); if (diceRolled[i] === 1) { diceRolled[i] = randomInteger(10); diceRolledFull = diceRolledFull + "(" + diceRolled[i].toString() + ")"; } if (i < (diceToRoll.diceQty - 1)) { diceRolledFull = diceRolledFull + ","; } } diceRolled.sort(function(a,b){return b-a}); fwLtC(diceRolled.toString()); for (i=0, diceToRoll.diceKeep;i<diceToRoll.diceKeep;i++){ diceResult = diceResult + diceRolled[i]; } sendChat(chatCommand, diceRolledFull + " = " + diceResult.toString()); }