Oh, didn't notice you're pro. This script probably isn't worth it, but maybe. //TravelerGun //macro to use is of form: !TravelerSAW <charName> <dexBonus> <skillBonus> //So, if John wants to shoot, has a 1 dex bonus to hit, and a 2 skill bonus, !TravelerSAW John 1 2 on ( "ready" , function () { on ( "chat:message" , function ( msg ) { if ( msg . type === "api" && msg . content . split ( ' ' )[ 0 ] === "!TravelerSAW" ) { SAW ( msg ); } }); }); function SAW ( msg ) { let parts = msg . content . split ( ' ' ); if (! parts [ 1 ] || ! parts [ 2 ] || ! parts [ 3 ]) { return ;} let dexBonus = parseInt ( parts [ 2 ]); let skillBonus = parseInt ( parts [ 3 ]); let aHitRolls = [ 0 , 0 , 0 ]; let aAttStrings = [ "" , "" , "" ]; for ( let i = 0 ; i < aHitRolls . length ; i ++) { aHitRolls [ i ] = randomInteger ( 6 ) + randomInteger ( 6 ) + dexBonus + skillBonus ; if ( aHitRolls [ i ] < 8 ) { aAttStrings [ i ] = " {{Attack " + i + "=Miss: " + String ( aHitRolls [ i ]) + "}}" ; } else { aAttStrings [ i ] = " {{Attack " + i + "=Hit: " + String ( aHitRolls [ i ]) + ", Damage: " + String ( randomInteger ( 6 ) + randomInteger ( 6 ) + randomInteger ( 6 ) + 5 + ( aHitRolls [ i ] - 8 )) + "}}" ; } } let resultString = "&{template:default} {{" + parts [ 1 ] + " fires his SAW}}" ; for ( let i = 0 ; i < aAttStrings . length ; i ++) { resultString += aAttStrings [ i ]; } sendChat ( msg . who , resultString ); }