Many thanks to TheAaron for taking to time to fix up this. For more info on how it works, please refer to the original forum post about it; <a href="https://app.roll20.net/forum/permalink/7323238/" rel="nofollow">https://app.roll20.net/forum/permalink/7323238/</a> This fixed script works perfectly with the character sheet created for FFRPG 4e on('ready',()=&gt;{ &nbsp; &nbsp; const DIE_SIZE = 10; &nbsp; &nbsp; const DEFAULT_NUM_DICE = 3; &nbsp; &nbsp; const END_LABEL = '--- END ---'; &nbsp; &nbsp; const styles = { &nbsp; &nbsp; &nbsp; &nbsp; entry: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "font-size": ".8em" &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; name: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "font-weight": "bold" &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; roll: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "background-color": "#fff", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "border": "1px solid #ddd", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "border-radius": ".5em", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "color": "#966", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "font-family": "monospace", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "line-height": "2em", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "font-weight": "bold", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "width": "2em", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "height": "2em", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "overflow": "auto", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "text-align": "center", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "display": "inline-block" &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }; &nbsp; &nbsp; const playerCanControl = (obj, playerid='any') =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; const playerInControlledByList = (list, playerid) =&gt; list.includes('all') || list.includes(playerid) || ('any'===playerid &amp;&amp; list.length); &nbsp; &nbsp; &nbsp; &nbsp; let players = obj.get('controlledby') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .split(/,/) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(s=&gt;s.length); &nbsp; &nbsp; &nbsp; &nbsp; if(playerInControlledByList(players,playerid)){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; if('' !== obj.get('represents') ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; players = (getObj('character',obj.get('represents')) || {get: function(){return '';} } ) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .get('controlledby').split(/,/) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(s=&gt;s.length); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return playerInControlledByList(players,playerid); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; return false; &nbsp; &nbsp; }; &nbsp; &nbsp; const processInlinerolls = (msg) =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; if(_.has(msg,'inlinerolls')){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return _.chain(msg.inlinerolls) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .reduce(function(m,v,k){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let ti=_.reduce(v.results.rolls,function(m2,v2){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(_.has(v2,'table')){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m2.push(_.reduce(v2.results,function(m3,v3){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m3.push(v3.tableItem.name); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return m3; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },[]).join(', ')); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return m2; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },[]).join(', '); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m['$[['+k+']]']= (ti.length &amp;&amp; ti) || v.results.total || 0; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return m; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },{}) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .reduce(function(m,v,k){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return m.replace(k,v); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },msg.content) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .value(); &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return msg.content; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }; &nbsp; &nbsp; const s = (name) =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; if(styles.hasOwnProperty(name)){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return `style="${Object.keys(styles[name]).reduce((m,k)=&gt;`${m}${k}:${styles[name][k]};`,'')}"`; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; return ''; &nbsp; &nbsp; }; &nbsp;const getTurnArray = () =&gt; ( '' === Campaign().get('turnorder') ? [] : JSON.parse(Campaign().get('turnorder'))); &nbsp;const setTurnArray = (ta) =&gt; Campaign().set({turnorder: JSON.stringify(ta)}); &nbsp; const addTokenTurn = (id, pr, pageid) =&gt; setTurnArray([...getTurnArray(), {id,pr,_pageid:(pageid||(getObj('graphic',id)||{get:''}).get('pageid'))}]); &nbsp;const addCustomTurn = (custom, pr) =&gt; Campaign().set({ turnorder: JSON.stringify( [...getTurnArray(), {id:'-1',custom,pr}]) }); &nbsp;const removeTokenTurn = (tid) =&gt; Campaign().set({ turnorder: JSON.stringify( getTurnArray().filter( (to) =&gt; to.id !== tid)) }); &nbsp;const clearTurnOrder = () =&gt; Campaign().set({turnorder:'[]'}); &nbsp;const sorter_asc = (a, b) =&gt; b.pr - a.pr; &nbsp;const sorter_desc = (a, b) =&gt; a.pr - b.pr; &nbsp;const sortTurnOrder = (sortBy = sorter_desc) =&gt; Campaign().set({turnorder: JSON.stringify(getTurnArray().sort(sortBy))}); &nbsp; &nbsp; const sorter_ascFF4 = (lookup) =&gt; (a, b) =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; if(a.custom===END_LABEL){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 1; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; if(b.custom===END_LABEL){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return -1; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; let dir = a.pr - b.pr; &nbsp; &nbsp; &nbsp; &nbsp; if( 0 === dir) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dir = lookup[b.id] - lookup[a.id]; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; return dir; &nbsp; &nbsp; }; &nbsp; &nbsp; const buildFF4Lookup = (ta) =&gt; ta.reduce((m,o)=&gt;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m[o.id]=(m[o.id]||0)+o.pr; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return m; &nbsp; &nbsp; &nbsp; &nbsp; },{}); &nbsp; &nbsp; const doRolls = (num=DEFAULT_NUM_DICE) =&gt; [...Array(num)].map(()=&gt;randomInteger(DIE_SIZE)); &nbsp; &nbsp; on('change:campaign:turnorder', (obj,prev) =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; let to = getTurnArray(); &nbsp; &nbsp; &nbsp; &nbsp; let told = (( '' === prev.turnorder) ? [] : JSON.parse(prev.turnorder)); &nbsp; &nbsp; &nbsp; &nbsp; let l = to.pop(); &nbsp; &nbsp; &nbsp; &nbsp; let f = told.shift(); &nbsp; &nbsp; &nbsp; &nbsp; if(f &amp;&amp; l &amp;&amp; f.id === l.id &amp;&amp; f.pr === l.pr){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setTurnArray(to); &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; assureEndLabel(); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; to = getTurnArray(); &nbsp; &nbsp; &nbsp; &nbsp; let lookup = buildFF4Lookup(to); &nbsp; &nbsp; &nbsp; &nbsp; sortTurnOrder(sorter_ascFF4(lookup)); &nbsp; &nbsp; }); &nbsp; &nbsp; const assureEndLabel = () =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; let to = getTurnArray(); &nbsp; &nbsp; &nbsp; &nbsp; let f = to.find((e)=&gt;END_LABEL===e.custom); &nbsp; &nbsp; &nbsp; &nbsp; if(!f){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addCustomTurn(END_LABEL,''); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; to = getTurnArray(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let lookup = buildFF4Lookup(to); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sortTurnOrder(sorter_ascFF4(lookup)); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }; &nbsp; &nbsp; on('chat:message',(msg)=&gt;{ &nbsp; &nbsp; &nbsp; &nbsp; if('api'===msg.type) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(/^!ffi\b/i.test(msg.content)){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let c = processInlinerolls(msg); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // !ffi &lt;NumRolls&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let args = c.split(/\s+/); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let output = []; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let outputPrivate = []; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(msg.selected){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msg.selected &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map(o=&gt;getObj('graphic',o._id)) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(g=&gt;undefined !== g) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map(t =&gt; ({token:t,rolls:doRolls(parseInt(args[1],10)||undefined)})) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(o=&gt;removeTokenTurn(o.token.id) || true) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(o=&gt;o.rolls.forEach(r=&gt;addTokenTurn(o.token.id,r,o.token.get('pageid')))||true) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .forEach(o=&gt;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let m=`&lt;div ${s('entry')}&gt;&lt;span ${s('name')}&gt;${o.token.get('name')}&lt;/span&gt; rolled: ${ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; o.rolls.map(r=&gt;`&lt;span ${s('roll')}&gt;${r}&lt;/span&gt;`).join(' ') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&lt;/div&gt;`; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if('objects' === o.token.get('layer')){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output.push(m); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; outputPrivate.push(m); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let to = getTurnArray(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let lookup = buildFF4Lookup(to); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sortTurnOrder(sorter_ascFF4(lookup)); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(output.length){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log(output.join('')); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('FF4 Init', output.join('')); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(outputPrivate.length){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('FF4 Init', `/w "gm" ${outputPrivate.join('')}`); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if( /^!f?eot\b/i.test(msg.content)){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let to = getTurnArray(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let token = getObj('graphic',(to[0]||{id:-1}).id); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(token &amp;&amp; (playerIsGM(msg.playerid) || playerCanControl(token,msg.playerid))){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; to.shift(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setTurnArray(to); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let lookup = buildFF4Lookup(to); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sortTurnOrder(sorter_ascFF4(lookup)); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let who = getObj('player',msg.playerid).get('_displayname'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('FF4 Init', `/w "${who}" &lt;div ${s('entry')}&gt;It is not one of your character's turns right now.&lt;/div&gt;`); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }); &nbsp; &nbsp; assureEndLabel(); });