Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×

Hero Tracker API script not adding tokens to initiative order

I run  a Hero System game. I use Hero Tracker API (along with HeroSystem6e and Hero Roller) Ever since last couple of updates, I cannot get tokens to appear on turn tracker. Whenever i attempt to use initiative (in Hero System there is no roll, goes by DEX) the 12 segment Turn chart appears, but I cannot get tokens to appear on it. Please help!
1643927742
Andreas J.
Forum Champion
Sheet Author
Translator
This is a recent bug on Roll20's side, that have caused bugs on several similar API, like <a href="https://app.roll20.net/forum/post/10666973/group-initiative-bug" rel="nofollow">https://app.roll20.net/forum/post/10666973/group-initiative-bug</a>
1643936739
Victor B.
Pro
Sheet Author
API Scripter
You'll need to reach out to the dev of hero tracker API.&nbsp; A small change is needed to get the turnorder to populate.&nbsp;&nbsp;
I noticed the same problem. I am hoping for a fix soon.
Any news?&nbsp; Been having this issue and it's been making my Star Hero System evenings rather difficult
1646009264
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
HeroTracker is a community script and not maintained by Roll20. The author is "Darren", but I don't see any contact info and the script has not been touched in 4 years. I would suggest appealing here in the announcement thread , and hopefully someone with scripting chops will jump in and lend a hand. I'll see if I can ping anyone who might be able to help.
1646011028
The Aaron
Roll20 Production Team
API Scripter
Here is HeroTracker 1.1 with the pageid issue fixed.&nbsp; Try it out and let me know if it works, and I'll send a pull request for it to the repo: // Name: HeroTracker, version 1.1 // Author: Darren // Last Updated: 4/30/2018 // // Purpse: // // HeroTracker implements the turn sequence of the Hero Games system. The Hero Games system // utilizes a segment chart with 12 'phases'. A character's speed determines how many and on // which phases he/she gets to act. HeroTracker will add a token to the Roll20 tracker // multiple times to simulate this mechanic. // // // Usage: // // !herotracker &lt;parms&gt; // // Parameters: // // --help // --add // --remove // --id &lt;token_id&gt; // --tag &lt;label&gt; // --speed &lt;number&gt; // --dex &lt;number&gt; // --segment &lt;number&gt; // --speed_field &lt;name&gt; // --dex_field &lt;name&gt; // --back // --start var HeroTracker = HeroTracker || { TURN: [ //segment 0 1 2 3 4 5 6 7 8 9 10 11 12 speed [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // 0 [ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], // 1 [ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1], // 2 [ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1], // 3 [ 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], // 4 [ 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1], // 5 [ 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], // 6 [ 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1], // 7 [ 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1], // 8 [ 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1], // 9 [ 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1], // 10 [ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // 11 [ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], // 12 write: function(s, who, style, from){ "use strict"; if (who){ who = "/w " + who.split(" ", 1)[0] + " "; } sendChat(from, who + s.replace(/&lt;/g, "&amp;" + "lt;").replace(/&gt;/g, "&amp;" + "gt;").replace(/\n/g, "&lt;br&gt;")); }, handleTrackerMessage: function(argv, msg){ "use strict"; var gm; var pageid = Campaign().get("playerpageid"); var who = msg.who; var token_id = ""; var tokens; var add = 0; var remove = 0; var back = 0; var tag = ""; var speed_field = "SPD"; var dex_field = "DEX"; var speed; // if undefined, get value from the token var dex; // if undefined, get value from the token var segment; var start; var random; gm = playerIsGM(msg.playerid); // parse command parameters if (msg.selected) { tokens = _.reject(msg.selected, (o) =&gt; o._type !== 'graphic'); } // tokens = msg.selected; msg = msg.content; argv.splice(0, 1); // remove !HeroTracker if (argv.length === 0) { return HeroTracker.showTrackerHelp(who); } while (argv.length &gt; 0) { switch (argv[0]){ case "--id": if(argv.length&lt;2) { return HeroTracker.write("--id parameter must be followed by a token_id", who, "", "HeroTracker" ); } token_id = argv[1]; argv.splice(0, 2); break; case "--add": add = 1; argv.splice(0, 1); break; case "--remove": if(gm) { remove = 1; } else { return HeroTracker.write( "Only the GM can use the --remove parameter.", who, "", "HeroTracker" ); } argv.splice(0, 1); break; case "--tag": if(argv.length&lt;2) { return HeroTracker.write("--tag parameter must be followed by a string", who, "", "HeroTracker" ); } tag = argv[1]; argv.splice(0, 2); break; case "--speed": if(argv.length&lt;2) { return HeroTracker.write("--speed parameter must be followed by a number", who, "", "HeroTracker" ); } speed = argv[1]; if(isNaN(parseInt(speed))) { return HeroTracker.write("speed was not a number", who, "", "HeroTracker" ); } argv.splice(0, 2); break; case "--dex": if(argv.length&lt;2) { return HeroTracker.write("--dex parameter must be followed by a number", who, "", "HeroTracker" ); } dex = argv[1]; if(isNaN(parseInt(dex))) { return HeroTracker.write("dex was not a number", who, "", "HeroTracker" ); } argv.splice(0, 2); break; case "--segment": if(argv.length&lt;2) { return HeroTracker.write("--segment parameter must be followed by a number", who, "", "HeroTracker" ); } segment = argv[1]; if(isNaN(parseInt(segment))) { return HeroTracker.write("segment was not a number", who, "", "HeroTracker" ); } argv.splice(0, 2); break; case "--back": back = 1; argv.splice(0, 1); break; case "--speed_field": if(argv.length&lt;2) { return HeroTracker.write("--speed_field parameter requires an attribute name", who, "", "HeroTracker" ); } speed_field = argv[1]; argv.splice(0, 2); break; case "--dex_field": if(argv.length&lt;2) { return HeroTracker.write("--dex_field parameter requires an attribute name", who, "", "HeroTracker" ); } dex_field = argv[1]; argv.splice(0, 2); break; case "--help": return HeroTracker.showTrackerHelp(who); break; case "--start": start = 1; argv.splice(0, 1); break; // hidden option used for testing case "--random": random = 1; argv.splice(0, 1); break; default: return HeroTracker.write("unknown parameter", who, "", "HeroTracker" ); break; } } // we have parsed all chat parameters // only the gm can to a 'back' action if( back === 1 &amp;&amp; !gm ) { return HeroTracker.write("only a gm can do the 'back' action", who, "", "HeroTracker"); } // can't do more than one action: add, remove, back if( ( add + remove + back ) &gt; 1 ) { return HeroTracker.write("can't do more than one action: 'add', 'remove', 'back'", who, "", "HeroTracker"); } // must have a token or tag to add or remove or what are we even doing here? if( ( add + remove === 1 ) &amp;&amp; token_id === "" &amp;&amp; tag === "" &amp;&amp; ( tokens === undefined || tokens.length === 0 ) ) { return HeroTracker.write("nothing selected", who, "", "HeroTracker" ); } // cannot specify both a token id and a tag if( ! token_id == "" &amp;&amp; tag == "" ) { return HeroTracker.write("can't specify both a token id and a tag", who, "", "HeroTracker" ); } // if we are doing an "add", we must have a speed or a segment. // if we have selected tokens, we can get the token's speed attribute. // but if we have no selected tokens, a speed or segment must have // been provided as part of the command parameters (--speed / --segment). if( add == 1 &amp;&amp; (!speed) &amp;&amp; (!segment) &amp;&amp; ( tokens == undefined || tokens.length == 0 ) ) { return HeroTracker.write("no speed or segment specified", who, "", "HeroTracker" ); } // cannot specify both a specified token id and a tag if( token_id !== "" &amp;&amp; tag !== "" ) { return HeroTracker.write("can't specify both a token id and a tag", who, "", "HeroTracker" ); } // cannot specify both a speed and a segment if( speed &amp;&amp; segment ) { return HeroTracker.write("can't specify both a speed and a segment", who, "", "HeroTracker" ); } // ok. error checking done. if( add === 1 ) { if(!gm) sendChat("HeroTracker", "/w gm " + who + " add"); Campaign().set("initiativepage", true); // display initiative tracker if( tag !== "" ) { // add custom tag to tracker HeroTracker.addToTracker("-1", (speed ? speed : 0), (dex ? dex : 0), segment, tag, who); } else if( token_id !== "" ) { // add a token specified with the --id parameter var t; // individual token var c; // character_id var s; // speed attribute var d; // dex attribute t = getObj('graphic', token_id); if( t ) { if( t.get('pageid') !== pageid ) return HeroTracker.write("token is not on the player page", who, "", "HeroTracker") c = t.get("represents") } if( c ) { s = ( speed ? speed : getAttrByName(c, speed_field) ); d = ( dex ? dex : getAttrByName(c, dex_field) ); HeroTracker.removeFromTracker(token_id); HeroTracker.addToTracker(token_id, (s ? s : 0), (d ? d : 0), segment, tag, who, t.get('pageid')); } } else { // add tokens based on current selection _.each(tokens, function(obj) { var t; // individual token var c; // character_id var s; // speed attribute var d; // dex attribute t = getObj('graphic', obj._id); if( t ) { if( t.get('pageid') !== pageid ) return HeroTracker.write("token is not on the player page", who, "", "HeroTracker") c = t.get("represents") } if( c ) { s = ( speed ? speed : getAttrByName(c, speed_field) ); if(!s) return HeroTracker.write("could not find attribute: " + speed_field, who, "", "HeroTracker" ); d = ( dex ? dex : getAttrByName(c, dex_field) ); if(!d) return HeroTracker.write("could not find attribute: " + dex_field, who, "", "HeroTracker" ); HeroTracker.removeFromTracker(obj._id); HeroTracker.addToTracker(obj._id, (s ? s : 0), (d ? d : 0), segment, tag, who,t.get('pageid')); } }); } } if( remove === 1 ) { if(!gm) sendChat("HeroTracker", "/w gm " + who + " remove"); if( token_id === "" ) { // remove a token specified with the --id parameter HeroTracker.removeFromTracker(token_id); } else { // remove multiple tokens based on current selection _.each(tokens, function(obj) { HeroTracker.removeFromTracker(obj._id); }); } } if( back === 1 ) { HeroTracker.backTrack(who); } if( random === 1 ) { HeroTracker.randomize(); } if( start === 1 ) { HeroTracker.startTurn(); } }, showTrackerHelp: function(who){ "use strict"; if (who){ who = "/w " + who.split(" ", 1)[0] + " "; } sendChat( 'HeroTracker', who + ' ' + '&lt;div style="border: 1px solid black; background-color: white; padding: 3px 3px;"&gt;'+ '&lt;div style="font-weight: bold; border-bottom: 1px solid black;font-size: 130%;"&gt;'+ 'HeroTracker'+ '&lt;/div&gt;'+ '&lt;div style="padding-left:10px;padding-right:10px;margin-top:10px;margin-bottom:3px"&gt;'+ '&lt;p style="padding-top: 5px;"&gt;HeroTracker implements the turn sequence of the Hero Games system. '+ 'The Hero Games system utilizes a segment chart with 12 phases. A character &amp;'+'apos;s speed '+ 'determines how many and on which phases he/she gets to act. HeroTracker will add a token to the '+ 'Roll20 tracker multiple times to simulate this mechanic.&lt;/p&gt;'+ '&lt;/div&gt;'+ '&lt;p style="font-size: 120%;margin-top:20px"&gt;&lt;b&gt;Syntax&lt;/b&gt;&lt;/p&gt;'+ '&lt;div style="padding-left:10px;"&gt;'+ '&lt;p&gt;&lt;b&gt;!herotracker&lt;/b&gt; &amp;' + 'lt;parms&amp;' + 'gt;&lt;/p&gt;' + '&lt;p&gt;&lt;b&gt;!ht&lt;/b&gt; &amp;' + 'lt;parms&amp;' + 'gt;&lt;/p&gt;' + '&lt;/div&gt;'+ '&lt;p style="font-size: 120%;margin-top:20px"&gt;&lt;b&gt;Parameters&lt;/b&gt;&lt;/p&gt;'+ '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ '&lt;ul&gt;'+ '&lt;li&gt;'+ '&lt;b&gt;--help&lt;/b&gt;'+ '&lt;/li&gt; '+ '&lt;li style="border-top: 1px solid #ccc;"&gt;'+ '&lt;b&gt;--add&lt;/b&gt;'+ '&lt;/li&gt; '+ '&lt;li style="border-top: 1px solid #ccc;"&gt;'+ '&lt;b&gt;--remove&lt;/b&gt;'+ '&lt;/li&gt; '+ '&lt;li style="border-top: 1px solid #ccc;"&gt;'+ '&lt;b&gt;--id&lt;/b&gt; &amp;' + 'lt;token_id&amp;' + 'gt;'+ '&lt;/li&gt; '+ '&lt;li style="border-top: 1px solid #ccc;"&gt;'+ '&lt;b&gt;--tag&lt;/b&gt; &amp;' + 'lt;label&amp;' + 'gt;'+ '&lt;/li&gt; '+ '&lt;li style="border-top: 1px solid #ccc;"&gt;'+ '&lt;b&gt;--speed&lt;/b&gt; &amp;' + 'lt;number&amp;' + 'gt;'+ '&lt;/li&gt; '+ '&lt;li style="border-top: 1px solid #ccc;"&gt;'+ '&lt;b&gt;--dex&lt;/b&gt; &amp;' + 'lt;number&amp;' + 'gt;'+ '&lt;/li&gt; '+ '&lt;li style="border-top: 1px solid #ccc;"&gt;'+ '&lt;b&gt;--segment&lt;/b&gt; &amp;' + 'lt;number&amp;' + 'gt;'+ '&lt;/li&gt; '+ '&lt;li style="border-top: 1px solid #ccc;"&gt;'+ '&lt;b&gt;--speed_field&lt;/b&gt; &amp;' + 'lt;name&amp;' + 'gt;'+ '&lt;/li&gt; '+ '&lt;li style="border-top: 1px solid #ccc;"&gt;'+ '&lt;b&gt;--dex_field&lt;/b&gt; &amp;' + 'lt;name&amp;' + 'gt;'+ '&lt;/li&gt; '+ '&lt;li style="border-top: 1px solid #ccc;"&gt;'+ '&lt;b&gt;--back&lt;/b&gt;'+ '&lt;/li&gt; '+ '&lt;li style="border-top: 1px solid #ccc"&gt;'+ '&lt;b&gt;--start&lt;/b&gt;'+ '&lt;/li&gt; '+ '&lt;/ul&gt;'+ '&lt;/div&gt;'+ '&lt;div style="padding-left: 10px; padding-right: 10px"&gt;'+ '&lt;p style="padding-top: 5px"&gt;To add tokens to the initiative tracker, select one or more tokens and then enter the chat command:&lt;/p&gt;'+ '&lt;p&gt;&lt;b&gt;!ht --add&lt;/b&gt;&lt;/p&gt;'+ '&lt;p style="padding-top: 5px; border-top: 1px solid #ccc;"&gt;To remove entries, select one or more tokens and enter the chat command: &lt;/p&gt;'+ '&lt;p&gt;&lt;b&gt;!ht --remove&lt;/b&gt;&lt;/p&gt;'+ '&lt;p style="padding-top: 5px; border-top: 1px solid #ccc;"&gt;Alternately, you can specify a single token by its ID rather than selecting it. '+ 'For example, to add a specific token, selected or not, enter this chat command: &lt;/p&gt;'+ '&lt;p&gt;&lt;b&gt;!ht --add --id -L9sBx-soK0CQzQYCiFA --speed 5&lt;/b&gt;&lt;/p&gt;'+ '&lt;p style="padding-top: 5px; border-top: 1px solid #ccc;"&gt;You can also add a static label to the tracker by entering this chat command: &lt;/p&gt;'+ '&lt;p&gt;&lt;b&gt;!ht --tag GAS-EFFECT --speed 4&lt;/b&gt;&lt;/p&gt;'+ '&lt;p style="padding-top: 5px; border-top: 1px solid #ccc;"&gt;When adding a token, the speed and dex will be automatically derived from the '+ 'token&amp;' + 'apos;s attributes. However, you can override this by specifying your own speed and dex: &lt;/p&gt;'+ '&lt;p&gt;&lt;b&gt;!ht --add --speed 6 --dex 18&lt;/b&gt;&lt;/p&gt;'+ '&lt;p style="padding-top: 5px; border-top: 1px solid #ccc;"&gt;You can add a token or label to just one segment by using this chat command:&lt;/p&gt;'+ '&lt;p&gt;&lt;b&gt;!ht --add --tag POST --segment 13&lt;/b&gt;&lt;/p&gt;'+ '&lt;p style="padding-top: 5px; border-top: 1px solid #ccc;"&gt;Because the tracker can end up with a great many entries, it would normally create '+ 'a cumbersome problem to cycle through the entire list should you accidentally move past a turn that isn&amp;' + 'apos;t complete. As such, HeroTracker '+ 'includes an option to rollback the tracker one turn: &lt;/p&gt;'+ '&lt;p&gt;&lt;b&gt;!ht --back&lt;/b&gt;&lt;/p&gt;'+ '&lt;p style="padding-top: 5px; border-top: 1px solid #ccc;"&gt;Hero System begins a turn at segment 12. You can sort the tracker, '+ 'with segment 12 at the top of the order, by using this command: &lt;/p&gt;'+ '&lt;p&gt;&lt;b&gt;!ht --start&lt;/b&gt;&lt;/p&gt;'+ '&lt;p style="padding-top: 5px; border-top: 1px solid #ccc;"&gt;HeroTracker uses dex to break ties by appending a decimal value to the '+ 'token&amp;' + 'apos;s speed. The value is just the dex subtracted from 100. If you do not want to use this feature, you can specify a dex '+ 'of zero using this command:&lt;/p&gt;'+ '&lt;p&gt;&lt;b&gt;!ht --add --dex 0&lt;/b&gt;&lt;/p&gt;'+ '&lt;p style="padding-top: 5px; border-top: 1px solid #ccc;"&gt;By default, HeroTracker uses the character sheet fields &lt;b&gt;SPD&lt;/b&gt; and &lt;b&gt;DEX&lt;/b&gt; '+ 'to derive the speed and dex values. You can override and choose your own field names using the parameters &lt;b&gt;--speed_field&lt;/b&gt; and &lt;b&gt;--dex_field&lt;/b&gt;. '+ 'This can also be used for characters that use a different attribute to break ties, such as ego based characters. The command would look like this:&lt;/p&gt;'+ '&lt;p&gt;&lt;b&gt;!ht --add --dex_field EGO&lt;/b&gt;&lt;/p&gt;'+ '&lt;/div&gt;'+ '&lt;p style="font-size: 120%;margin-top:20px"&gt;&lt;b&gt;Notes&lt;/b&gt;&lt;/p&gt;'+ '&lt;div style="padding-left: 15px; padding-right: 10px"&lt;/div&gt;'+ '&lt;p&gt;The speed and dex of a selected token will be derived from the '+ 'token&amp;'+'apos;s attributes &lt;b&gt;SPD&lt;/b&gt; and &lt;b&gt;DEX&lt;/b&gt; respectively.&lt;/p&gt;'+ '&lt;p&gt;If you specify a single token using the &lt;b&gt;--id&lt;/b&gt; parameter, or create a custom label using '+ 'the &lt;b&gt;--tag&lt;/b&gt; parameter, you must also provide a speed or segment, and optionally a dex.&lt;/p&gt;'+ '&lt;/div&gt;'+ '&lt;/div&gt;' ); }, addToTracker: function(token_id, speed, dex, segment, custom, who, pageid) { "use strict"; var turnorder; var tiebreaker = 0; /* HeroTracker.write("token_id: " + token_id, who, "", "HeroTracker" ); HeroTracker.write("speed: " + speed, who, "", "HeroTracker" ); HeroTracker.write("dex: " + dex, who, "", "HeroTracker" ); HeroTracker.write("segment: " + segment, who, "", "HeroTracker" ); HeroTracker.write("custom: " + custom, who, "", "HeroTracker" ); */ if(speed) speed = parseInt(speed); if(dex) dex = parseInt(dex); // compute the tiebreaker value if (dex &gt; 0) tiebreaker = 1 - ( dex / 100 ); turnorder = JSON.parse(Campaign().get('turnorder')||'[]'); if (token_id === "") { token_id = "-1"; } // if no token id is present, set to -1 to use the custom arg let pageidExtra = {}; if(pageid){ pageidExtra._pageid=pageid; } // if a segment was provided, we skip speed and dex entirely if( segment ) { var i = HeroTracker.getSortIndex(turnorder, segment); turnorder.splice(i, 0, {id:token_id,pr:segment,custom:custom, ...pageidExtra}); Campaign().set("turnorder", JSON.stringify(turnorder)); return; } // handle speeds greater than 12 while (speed&gt;12) { var i; for (var s=1;s&lt;=12;s++) { var p = Math.round( (s + tiebreaker + 0.00001) * 100 ) / 100; i = HeroTracker.getSortIndex(turnorder, p); turnorder.splice(i, 0, {id:token_id,pr:p,custom:custom, ...pageidExtra}); } speed = speed - 12; } for (var s=1;s&lt;=12;s++) { var i; var p = Math.round( (s + tiebreaker + 0.00001) * 100 ) / 100; if(HeroTracker.TURN[speed][s] == 1) { i = HeroTracker.getSortIndex(turnorder, p); turnorder.splice(i, 0, {id:token_id,pr:p,custom:custom, ...pageidExtra}); } } Campaign().set("turnorder", JSON.stringify(turnorder)); }, getSortIndex: function(turnorder, pr) { "use strict"; // if the current turnorder is zero or one entry, we always // add to the end of the array. if(turnorder.length &lt;= 1) { return turnorder.length; } // new entries are NEVER added to the top of the list var a = 1; // start the second entry // if the current top of the list is greater than the entry // we're trying to add, we will want to skip down to the // turn break. if( turnorder[0].pr &gt;= pr ) { // scan down to find the turn 'break' do { if( turnorder[a].pr &lt; turnorder[a-1].pr ) break; else a++; } while ( turnorder.length &gt; a ); // if we're at the end of the list, append the entry to the end if( turnorder.length === a ) return a; } // we should be sitting at the top of the turn break. // now we scan down to find our insert point. do { if (turnorder[a].pr &gt; pr) break; else a++; } while ( turnorder.length &gt; a ); return a; }, removeFromTracker: function(token_id) { "use strict"; var turnorder; if(Campaign().get("turnorder") == "") return; else turnorder = JSON.parse(Campaign().get("turnorder")); for(var i=0;i&lt;turnorder.length;) { if(turnorder[i]['id'] === token_id) { turnorder.splice(i, 1); } else { i++; } }; Campaign().set("turnorder", JSON.stringify(turnorder)); }, backTrack: function() { "use strict"; var turnorder; var turn; turnorder = JSON.parse(Campaign().get('turnorder')||'[]'); if( turnorder.length &lt;= 1) return; turnorder.splice( 0, 0, turnorder.pop() ); Campaign().set("turnorder", JSON.stringify(turnorder)); }, newTurnSort: function(a,b) { "use strict"; const aFloat = (parseFloat(a.pr)||0); const bFloat = (parseFloat(b.pr)||0); const cFloat = Math.round(((aFloat-bFloat) + 0.00001) * 100 ) / 100; if (cFloat === 0.0) return -1; if( 12.0 &lt;= aFloat &amp;&amp; 12.0 &gt; bFloat) return -1; if( 12.0 &gt; aFloat &amp;&amp; 12.0 &lt;= bFloat) return 1; return (cFloat); }, startTurn: function() { let turns = JSON.parse(Campaign().get('turnorder')||'[]'); turns.sort( HeroTracker.newTurnSort ); Campaign().set('turnorder', JSON.stringify(turns)); }, sortRandom: function(a,b) { return 0.5 - Math.random(); }, randomize: function() { let turns = JSON.parse(Campaign().get('turnorder')||'[]'); turns.sort( HeroTracker.sortRandom ); Campaign().set('turnorder', JSON.stringify(turns)); }, handleChatMessage: function(msg){ "use strict" if (msg.type !== "api"){ return; } if ((msg.content === "!herotracker") || (msg.content.indexOf("!herotracker ") === 0) || (msg.content === "!ht") || (msg.content.indexOf("!ht ") === 0)){ return HeroTracker.handleTrackerMessage(msg.content.split(" "), msg); } }, registerHeroTracker: function(){ "use strict" // HeroTracker.initConfig(); on("chat:message", HeroTracker.handleChatMessage); } } on("ready", function(){ HeroTracker.registerHeroTracker(); })
It works! Thank you!
1646085836
The Aaron
Roll20 Production Team
API Scripter
Great!&nbsp; I've sent a pull request to update 1.1 in the 1-click to have the above fix.&nbsp; There's a 1.2 version with the fix that has some merge issues that should be getting cleared up at some point, but this 1.1 change should at least get everyone moving again. BTW, if you have turn orders that you need to preserve but can't see, there's a script here that will fix the invisible entries:&nbsp; <a href="https://app.roll20.net/forum/permalink/10667246/" rel="nofollow">https://app.roll20.net/forum/permalink/10667246/</a>
I can confirm this script update works!&nbsp; :D&nbsp; It seems like i have to re-paste it in from time to time...&nbsp; I guess roll20 is not yet updated with the patch.&nbsp; But thanks a million, i use this script a lot!&nbsp; :D