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 .
×
Create a free account

crash when two api running

1552328152

Edited 1552329092
Sad
Sheet Author
API Scripter
[help] timer.js on("ready", function () { let lastTime = Date.now(); let lastSecond = Math.floor(lastTime / 1000) * 1000; let rotPerSec = 360 / 60; const updateSpeed = 250; let bar2Splitor = /^(\w|)(\w|)(\w|)(\w|)([.]|)(\w+|)/i; let bar2numSplitor = [/[-][-](\d+)/i]; let bar2num2Splitor = /[.](\d+)/i; let bar1max2Splitor = [/[:]([\s\S]+)/i]; const statusLookup = [ "red", "red,blue", "red,blue,green", "red,blue,green,brown", "red,blue,green,brown,purple", "red,blue,green,brown,purple,yellow", "red,blue,green,brown,purple", "red,blue,green,brown", "red,blue,green", "red,blue" ]; const aura1_colorLookup = [ "#ff0000", "#ffff00", "#00ff00", "#0000ff", "#ff00ff" ]; const aura1_radiusLookup = [ "0.7", "0.8", "0.9", "1", "1.1" ]; const doUpdates = () => { try { let time = Date.now(); let deltaS = time - lastSecond; lastTime = time; findObjs({ type: 'graphic', bar1_value: 'game.clock' }, { caseInsensitive: true }) .forEach((obj) => { let key = bar2Splitor.exec(obj.get('bar2_value')); if (key.indexOf("o") === -1) { let c = { bar3_value: obj.get('bar3_value') || "0", bar2_value: obj.get('bar2_value') || "", name: obj.get('name') || '00:00:00', showname: true }; let sec = parseInt(c.bar3_value); if (key.indexOf("r") === -1) { c.rotation = (((((parseInt(obj.get('bar3_value')) || 0) % 60) * rotPerSec) + (rotPerSec * (deltaS / 1000)) % 360 + 360) % 360) + parseInt(key[6] || 0) } else { c.rotation = parseInt(key[6] || 0); } if (key.indexOf("s") === -1) { let phase = (sec % (statusLookup.length)); c.statusmarkers = statusLookup[phase]; } else { c.statusmarkers = "" } if (key.indexOf("a") === -1) { let phase = (sec % (aura1_colorLookup.length)); c.aura1_color = aura1_colorLookup[phase]; c.aura1_radius = aura1_radiusLookup[phase]; } else { c.aura1_radius = "" } if (deltaS > 1000) { ++sec; let h = Math.floor(sec / 3600); if (h < 10) h = '0' + h; let m = Math.floor((sec - (h * 60)) / 60); let s = Math.floor(sec % 60); c.bar3_value = `${sec}`; c.name = obj.get('bar1_max') + `${`${h}`}:${`00${m}`.slice(-2)}:${`00${s}`.slice(-2)}`; } obj.set(c); }; }); if (deltaS > 1000) { lastSecond += 1000; } } catch (e) { } }; setInterval( doUpdates, updateSpeed ); on('chat:message', (msg) => { if ('api' === msg.type && /^!game.clock\b/i.test(msg.content)) { let cmd = msg.content.toLowerCase().split(/\s+/); let create = cmd.includes('--create') || cmd.includes('-c'); let toggle = cmd.includes('--toggle') || cmd.includes('-t'); let reset = cmd.includes('--reset') || cmd.includes('-re'); let rotation = cmd.includes('--rotation') || cmd.includes('-ro'); let marker = cmd.includes('--marker') || cmd.includes('-m'); let aura = cmd.includes('--aura') || cmd.includes('-a'); let angle = bar2numSplitor.some(check => check.test(cmd)); let name = bar1max2Splitor.some(check => check.test(cmd)); (msg.selected || []) .map((o) => getObj('graphic', o._id)) .filter(o => undefined !== o) .filter((o) => create || 'game.clock' === o.get('bar1_value')) .forEach((o) => { let c = {}; c.bar2_value = o.get('bar2_value'); if (create) { c.bar1_value = 'game.clock'; c.showname = true; //c.bar2_value = 1; //c.rotation = 0; //c.statusmarkers = ''; //c.name = '00:00:00'; } if (reset) { c.bar3_value = 0; c.bar2_value = ""; c.rotation = 0; c.statusmarkers = ''; c.name = '00:00:00'; } if (toggle) { c.bar2_value = (c.bar2_value.indexOf("o") === -1 ? 'o' + c.bar2_value : c.bar2_value.replace("o", "")); } if (rotation) { c.bar2_value = (c.bar2_value.indexOf("r") === -1 ? 'r' + c.bar2_value : c.bar2_value.replace("r", "")); } if (marker) { c.bar2_value = (c.bar2_value.indexOf("s") === -1 ? 's' + c.bar2_value : c.bar2_value.replace("s", "")); } if (aura) { c.bar2_value = (c.bar2_value.indexOf("a") === -1 ? 'a' + c.bar2_value : c.bar2_value.replace("a", "")); } if (angle) { c.bar2_value = (c.bar2_value.match(/[.](\d+)/i) ? (c.bar2_value.replace(bar2num2Splitor, "." + msg.content.match(/[-][-](\d+)/i)[1])) : c.bar2_value + "." + msg.content.match(/[-][-](\d+)/i)[1]); } if (name) { c.bar1_max = (msg.content.match(/[:]([\s\S]+)/i)[1]); } o.set(c); }); } }); }); highlight.js // VARIABLE & FUNCTION DECLARATION var TurnOrderAgent = TurnOrderAgent || {}; // AnnounceNewRound - Set to TRUE if you want the script to announce // the beginning of each new round. var AnnounceNewRound = true; on("chat:message", function (msg) { // Exit if not an api command if (msg.type != "api") return; // Get the API Chat Command msg.who = msg.who.replace(" (GM)", ""); msg.content = msg.content.replace("(GM) ", ""); var command = msg.content.split(" ", 1); if (command == "!eot") { if (!Campaign().get('turnorder')) return; // Exit if the turn order tracker is not open var turn_order = JSON.parse(Campaign().get('turnorder')); // Parse the turn order information into JSON if (!turn_order.length) return; // Exit if there are no tokens on the tracker var turn = turn_order.shift(); // Grab the info for the top of initiative turn_order.push({ // Add the info to the bottom of initiative id: turn.id, pr: turn.pr, custom: turn.custom }); Campaign().set("turnorder", JSON.stringify(turn_order)); // Send the turn order back to the tracker TurnOrderAgent(); } }); on("change:campaign:turnorder", function () { TurnOrderAgent(); }); on("change:graphic:left", function () { TurnOrderAgent(); }); on("change:graphic:top", function () { TurnOrderAgent(); }); function TurnOrderAgent() { try { if (!Campaign().get("turnorder")) return; var turn_order = JSON.parse(Campaign().get("turnorder")); if (!turn_order.length) return; if (typeof turn_order[0].pr == "string") { if (turn_order[0].pr.substring(0, 5) == "Round") { var RoundTracker = turn_order[0].pr; var CurrentRound = parseInt(RoundTracker.substring(5)); turn_order[0].pr = "Round " + (CurrentRound + 1); Campaign().set({ turnorder: JSON.stringify(turn_order) }); if (AnnounceNewRound == true) { sendChat("", "/desc "); sendChat("", "/direct <div style='width: 100%; color: #C8DE84; border: 1px solid #91bd09; background-color: #749a02; box-shadow: 0 0 15px #91bd09; display: block; text-align: center; font-size: 20px; padding: 5px 0; margin-bottom: 0.25em; font-family: Garamond;'>" + turn_order[0].pr + "<>"); } } } // Exit script if custom item on turn order tracker instead of a token... if (turn_order[0].id == -1) return; var current_token = getObj("graphic", turn_order[0].id); var initiative_highlighter = findObjs({ name: "InitiativeHighlight", pageid: current_token.get("pageid") }, { caseInsensitive: true })[0]; if (initiative_highlighter == undefined) { // sendChat("ERROR", "/w gm Cannot find an initiative highlight token on this page."); return; } if (initiative_highlighter.get("layer") == "gmlayer" && current_token.get("layer") != "gmlayer") { initiative_highlighter.set({ "top": current_token.get("top"), "left": current_token.get("left"), "height": current_token.get("height") + 20, "width": current_token.get("width") + 20 }); setTimeout(function () { initiative_highlighter.set({ "layer": current_token.get("layer") }); }, 500); } else { initiative_highlighter.set({ "layer": current_token.get("layer"), "top": current_token.get("top"), "left": current_token.get("left"), "height": current_token.get("height") + 20, "width": current_token.get("width") + 20 }); } toFront(current_token); } catch (e) { }}; error message TypeError: Cannot read property 'substring' of undefined TypeError: Cannot read property 'substring' of undefined at TrackedObj._validateAttrs (/home/node/d20-api-server/api.js:878:26) at createObj (/home/node/d20-api-server/api.js:2670:23) at apiscript.js:82:23 at Timeout._onTimeout (apiscript.js:55:12) at ontimeout (timers.js:386:14) at tryOnTimeout (timers.js:250:5) at Timer.listOnTimeout (timers.js:214:5)
1552332931

Edited 1552333037
GiGs
Pro
Sheet Author
API Scripter
Some questions: Under what conditions does the error occur? what causes it, when does it happen? No-one has any chance of figuring out the problem without at least that information. Do you only  get the error with both scripts active? does the error vanish one is disabled? Try disabling highlight.js, see if the error vanishes. then reactivate it, and disable the other one, and see if the error vanishes. The reported error does seem to be timer related, which points to the timer.js script, but the entire TurnOrderAgent function code being inside a try/catch block looks very suspicious to me, especially with nothing in the catch block. My guess is the error is in that script somewhere. I'd remove the try/catch block and see what errors you get.
that error message does not match these two scripts being the only things loaded.  What other scripts are loaded, presumably ahead of these two?
1552361181
The Aaron
Roll20 Production Team
API Scripter
Neither of those scripts call createObj(). It seems likely the culprit is another script. 
1552369155
Sad
Sheet Author
API Scripter
It would crash when i move multi token include   named InitiativeHighlight.
1552395066
GiGs
Pro
Sheet Author
API Scripter
Do you have any other scripts running?
1552404960
Sad
Sheet Author
API Scripter
I use tokenmod,&nbsp;BloodAndHonor and&nbsp;&nbsp;Audio Master also. Maybe i crash after use BloodAndHonor? <a href="https://app.roll20.net/forum/post/1477230/script-blood-and-honor-automatic-blood-spatter-pooling-and-trail-effects-lightweight" rel="nofollow">https://app.roll20.net/forum/post/1477230/script-blood-and-honor-automatic-blood-spatter-pooling-and-trail-effects-lightweight</a>
1552405325
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Yep, I would guess that it is blood and honor causing the problem, tokenmod doesn't use createObj at all AFAIK and Audio Master only uses it to generate the help handout.
1552534076
Sad
Sheet Author
API Scripter
Sadly BloodAndHonor is useful api
BloodAndHonor doesn't validate any of the arguments it passes to createObj. &nbsp; Then createObj errors out when it tries to check the arguments. &nbsp;Show this crash to the author of BloodAndHonor and they can fix it for you, or at least have it not crash.
1552579238
Ziechael
Forum Champion
Sheet Author
API Scripter
Paging Dr Aaron... he has an updated version of this script that may address that issue... fingers crossed he can confirm/deny :)
1552579836

Edited 1552579847
The Aaron
Roll20 Production Team
API Scripter
Could be.&nbsp; I see in the notes I added that I fixed something with createObj() and randomInteger() crashes: ///////////////////////////////////////////////// /***********************************************/ var BloodAndHonor = { author: { name: "John C." || "Echo" || "SplenectomY", company: "Team Asshat" || "The Alehounds", contact: "<a href="mailto:echo@TeamAsshat.com" rel="nofollow">echo@TeamAsshat.com</a>" }, version: "0.8.2", // The Aaron - Patched for playerIsGM(), createObj(), and randomInteger() crash. gist: "<a href="https://gist.github.com/SplenectomY/097dac3e427ec50f32c9" rel="nofollow">https://gist.github.com/SplenectomY/097dac3e427ec50f32c9</a>", forum: "<a href="https://app.roll20.net/forum/post/1477230/" rel="nofollow">https://app.roll20.net/forum/post/1477230/</a>", wiki: "<a href="https://wiki.roll20.net/Script:Blood_And_Honor:_Automatic_blood_spatter,_pooling_and_trail_effects" rel="nofollow">https://wiki.roll20.net/Script:Blood_And_Honor:_Automatic_blood_spatter,_pooling_and_trail_effects</a>", /***********************************************/ ///////////////////////////////////////////////// // This value should match the size of a standard grid in your campaign // Default is 70 px x 70 px square, Roll20's default. tokenSize: 70, bar: 1, // YOU MUST ADD YOUR OWN SPATTERS AND POOLS TO YOUR LIBRARY // AND GET THE IMAGE LINK VIA YOUR WEB BROWSER. // FOLLOW THE INSTRUCTIONS HERE: // <a href="https://wiki.roll20.net/API:Objects#imgsrc_and_avatar_property_restrictions" rel="nofollow">https://wiki.roll20.net/API:Objects#imgsrc_and_avatar_property_restrictions</a> // You can add as many as you'd like to either category. // Spatters are also used for blood trails. spatters: [ "<a href="https://s3.amazonaws.com/files.d20.io/images/7029414/3MoaSCA5oJn-KFQOrJlb_g/thumb.png?1420637338" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7029414/3MoaSCA5oJn-KFQOrJlb_g/thumb.png?1420637338</a>", "<a href="https://s3.amazonaws.com/files.d20.io/images/7029416/E1Ltkjvnl2vRpTy8tEzizw/thumb.png?1420637338" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7029416/E1Ltkjvnl2vRpTy8tEzizw/thumb.png?1420637338</a>", "<a href="https://s3.amazonaws.com/files.d20.io/images/7029417/M6y2P0exUcLHrQPOlEd71g/thumb.png?1420637339" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7029417/M6y2P0exUcLHrQPOlEd71g/thumb.png?1420637339</a>", "<a href="https://s3.amazonaws.com/files.d20.io/images/7029420/NgEX0Bg3WQ9y7XgKTEpZdQ/thumb.png?1420637342" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7029420/NgEX0Bg3WQ9y7XgKTEpZdQ/thumb.png?1420637342</a>", "<a href="https://s3.amazonaws.com/files.d20.io/images/7029422/AGMNRwd_BvGFLjgjBGhaFA/thumb.png?1420637343" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7029422/AGMNRwd_BvGFLjgjBGhaFA/thumb.png?1420637343</a>", "<a href="https://s3.amazonaws.com/files.d20.io/images/7029421/x8RnxTkCbU-eqbo4MqV0mw/thumb.png?1420637342" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7029421/x8RnxTkCbU-eqbo4MqV0mw/thumb.png?1420637342</a>", "<a href="https://s3.amazonaws.com/files.d20.io/images/7029423/qTAdlint-YlNDfqU9eVUeQ/thumb.png?1420637343" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7029423/qTAdlint-YlNDfqU9eVUeQ/thumb.png?1420637343</a>", "<a href="https://s3.amazonaws.com/files.d20.io/images/7029424/icwaJtDz4RlBArCKZ436Kg/thumb.png?1420637356" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7029424/icwaJtDz4RlBArCKZ436Kg/thumb.png?1420637356</a>", "<a href="https://s3.amazonaws.com/files.d20.io/images/7029466/_Dj9KCZTwQYK08viNGVZ0g/thumb.png?1420637808" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7029466/_Dj9KCZTwQYK08viNGVZ0g/thumb.png?1420637808</a>", "<a href="https://s3.amazonaws.com/files.d20.io/images/7688454/xUGIH-sKf-YS0DBd-ZFvxA/thumb.PNG?1423835353" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7688454/xUGIH-sKf-YS0DBd-ZFvxA/thumb.PNG?1423835353</a>", "<a href="https://s3.amazonaws.com/files.d20.io/images/7688450/HlLXGJqt6ZCxSiGyY5f1QQ/thumb.PNG?1423835351" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7688450/HlLXGJqt6ZCxSiGyY5f1QQ/thumb.PNG?1423835351</a>", ], pools: [ "<a href="https://s3.amazonaws.com/files.d20.io/images/7029415/MLsoOwvMDa1JVYgUvW6B9w/thumb.png?1420637338" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7029415/MLsoOwvMDa1JVYgUvW6B9w/thumb.png?1420637338</a>", "<a href="https://s3.amazonaws.com/files.d20.io/images/7029418/1O_RWFB-xkPaElbaM6JitA/thumb.png?1420637339" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7029418/1O_RWFB-xkPaElbaM6JitA/thumb.png?1420637339</a>", "<a href="https://s3.amazonaws.com/files.d20.io/images/7029425/WA8d9mQEUCv6bzSdqKcydA/thumb.png?1420637356" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/7029425/WA8d9mQEUCv6bzSdqKcydA/thumb.png?1420637356</a>", ], chooseBlood: function chooseBlood(type) { if (type == "spatter") return BloodAndHonor.spatters[randomInteger(BloodAndHonor.spatters.length) - 1]; if (type == "pool") return BloodAndHonor.pools[randomInteger(BloodAndHonor.pools.length) - 1]; }, getOffset: function getOffset() { if (randomInteger(2) == 1) return 1; else return -1; }, bloodColor: function bloodColor(gmnotes) { if (gmnotes.indexOf("bloodcolor_purple") !== -1) return "#0000ff"; if (gmnotes.indexOf("bloodcolor_blue") !== -1) return "#00ffff"; if (gmnotes.indexOf("bloodcolor_orange") !== -1) return "#ffff00"; else return "transparent"; }, createBlood: function createBlood(gPage_id,gLeft,gTop,gWidth,gType,gColor) { gLeft = gLeft + (randomInteger(Math.floor(gWidth / 2)) * BloodAndHonor.getOffset()); gTop = gTop + (randomInteger(Math.floor(gWidth / 2)) * BloodAndHonor.getOffset()); setTimeout(function(){ toFront(createObj("graphic",{ imgsrc: gType, gmnotes: "blood", pageid: gPage_id, left: gLeft, tint_color: gColor, top: gTop, rotation: randomInteger(360) - 1, width: gWidth, height: gWidth, layer: "map" })); },50); }, timeout: 0, onTimeout: function theFinalCountdown() { if (BloodAndHonor.timeout &gt; 0) { BloodAndHonor.timeout--; } else { return; } } }; on("ready", function() { setInterval(function(){BloodAndHonor.onTimeout();},1000); on(`change:graphic:bar${BloodAndHonor.bar}_value`, function(obj, prev) { if (obj.get(`bar${BloodAndHonor.bar}_max`) === "" || obj.get("layer") != "objects" || (obj.get("gmnotes")).indexOf("noblood") !== -1) return; // Create spatter near token if "bloodied". // Chance of spatter depends on severity of damage else if (obj.get(`bar${BloodAndHonor.bar}_value`) &lt;= obj.get(`bar${BloodAndHonor.bar}_max`) / 2 &amp;&amp; prev[`bar${BloodAndHonor.bar}_value`] &gt; obj.get(`bar${BloodAndHonor.bar}_value`) &amp;&amp; obj.get(`bar${BloodAndHonor.bar}_value`) &gt; 0) { var m=parseInt(obj.get('bar${BloodAndHonor.bar}_max'),10)||1, v=parseInt(obj.get('bar${BloodAndHonor.bar}_value'),10)||1, r=randomInteger(m); if (r&gt;v) { var bloodMult = 1 + ((obj.get(`bar${BloodAndHonor.bar}_value`) - prev[`bar${BloodAndHonor.bar}_value`]) / obj.get(`bar${BloodAndHonor.bar}_max`)); BloodAndHonor.createBlood(obj.get("_pageid"), obj.get("left"), obj.get("top"), Math.floor(BloodAndHonor.tokenSize * bloodMult), BloodAndHonor.chooseBlood("spatter"), BloodAndHonor.bloodColor(obj.get("gmnotes"))); } } // Create pool near token if health drops below 1. else if (obj.get(`bar${BloodAndHonor.bar}_value`) &lt;= 0) { BloodAndHonor.createBlood(obj.get("_pageid"), obj.get("left"), obj.get("top"), Math.floor(BloodAndHonor.tokenSize * 1.5), BloodAndHonor.chooseBlood("pool"), BloodAndHonor.bloodColor(obj.get("gmnotes"))); } }); //Make blood trails, chance goes up depending on how injured a token is on("change:graphic:lastmove", function(obj) { if (BloodAndHonor.timeout == 0) { if (obj.get(`bar${BloodAndHonor.bar}_value`) &lt;= obj.get(`bar${BloodAndHonor.bar}_max`) / 2 &amp;&amp; (obj.get(`gmnotes`)).indexOf(`noblood`) == -1) { var m=parseInt(obj.get(`bar${BloodAndHonor.bar}_max`),10)||1, v=parseInt(obj.get(`bar${BloodAndHonor.bar}_value`),10)||1, r=randomInteger(m); if (r&gt;v) { BloodAndHonor.createBlood(obj.get("_pageid"), obj.get("left"), obj.get("top"), Math.floor(BloodAndHonor.tokenSize / 2), BloodAndHonor.chooseBlood("spatter"), BloodAndHonor.bloodColor(obj.get("gmnotes"))); BloodAndHonor.timeout += 2; } } } }); on("chat:message", function(msg) { if (msg.type == "api" &amp;&amp; msg.content.indexOf("!clearblood") !== -1) { if (!playerIsGM(msg.playerid)) { sendChat(msg.who,"/w " + msg.who + " You are not authorized to use that command!"); return; } else { let objects = filterObjs(function(obj) { if(obj.get("type") == "graphic" &amp;&amp; obj.get("gmnotes") == "blood") return true; else return false; }); _.each(objects, function(obj) { obj.remove(); }); } } }); });