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

[Help] Blood and Honor error

Hello all, I'm currently working with Blood and Honor to try and get it working for my Warhammer campaign. I've been persistently receiving the following error: Error: toFront() must be given an object either from an event or getObj() or similar. undefined Here's what I've tried: 1. Disabling all other scripts 2. Double and triple-checking my blood pool and spatter links 3. Making minor adjustments such as commenting out the useisGM line I've&nbsp; checked the previous topics on Blood and Honor errors and none of the proposed solutions (which essentially amounted to the above changes) worked for me; I still get the same error. Here's my code: ///////////////////////////////////////////////// /***********************************************/ var BloodAndHonor = { author: { name: "John C." || "Echo" || "SplenectomY", company: "Team Asshat" || "The Alehounds", contact: "<a href="" rel="nofollow"></a>" }, version: "0.8.2", // The Aaron - Patched for playerIsGM(), createObj(), and randomInteger() crash. gist: "<a href="" rel="nofollow"></a>", forum: "<a href="" rel="nofollow"></a>", wiki: "<a href=",_pooling_and_trail_effects" rel="nofollow">,_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, // If you have it installed, this will plug in TheAaron's isGM auth module, // which will make it so only the GM can use the !clearblood command // Change to "true" if you want to check for authorization &nbsp; &nbsp; &nbsp; &nbsp; // NOTE: Changed this to use the now built in playerIsGM() //useIsGM: false, // 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="" rel="nofollow"></a>... // You can add as many as you'd like to either category. // Spatters are also used for blood trails. spatters: [ "<a href="" rel="nofollow"></a>", "<a href="" rel="nofollow"></a>", "<a href="" rel="nofollow"></a>" ], pools: [ "<a href="" rel="nofollow"></a>", "<a href="" rel="nofollow"></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(obj) { setInterval(function(){BloodAndHonor.onTimeout()},1000); on("change:graphic:bar3_value", function(obj, prev) { if (obj.get("bar3_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("bar3_value") &lt;= obj.get("bar3_max") / 2 && prev["bar3_value"] &gt; obj.get("bar3_value") && obj.get("bar3_value") &gt; 0) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var m=parseInt(obj.get('bar3_max'),10)||1, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; v=parseInt(obj.get('bar3_value'),10)||1, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r=randomInteger(m); if (r&gt;v) { var bloodMult = 1 + ((obj.get("bar3_value") - prev["bar3_value"]) / obj.get("bar3_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("bar3_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("bar3_value") &lt;= obj.get("bar3_max") / 2 && (obj.get("gmnotes")).indexOf("noblood") == -1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var m=parseInt(obj.get('bar3_max'),10)||1, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; v=parseInt(obj.get('bar3_value'),10)||1, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 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" && msg.content.indexOf("!clearblood") !== -1) { if (BloodAndHonor.useIsGM && !playerIsGM(msg.playerid)) { sendChat(msg.who,"/w " + msg.who + " You are not authorized to use that command!"); return; } else { objects = filterObjs(function(obj) { if(obj.get("type") == "graphic" && obj.get("gmnotes") == "blood") return true; else return false; }); _.each(objects, function(obj) { obj.set("left",0); obj.set("top",0); }); } } }); }); Any ideas what my issue is? Thanks!
Victor B.
Sheet Author
API Scripter
The toFront is happening too early.&nbsp; It's creating an object at the time the toFront is trying to do whatever that function does.&nbsp;&nbsp; The toFront needs to move after the createObj but within the timeout function.&nbsp; Then a toFront(getObj('graphic')) should work.&nbsp;&nbsp;
The Aaron
Forum Champion
API Scripter
Specifically what Victor is saying, this is causing the error: 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); toFront() expects to be passed a valid Roll20 Object.&nbsp; The createObj() function returns the object it creates, but for some reason it is failing to to create a valid object.&nbsp; likely on of the required parameters is invalid, like one of left, top, width, height are NaN.&nbsp; You can resolve the issue and possibly expose the really problem by capturing the return of createObj() and inspecting it before passing it to toFront: &nbsp; &nbsp; &nbsp; &nbsp; setTimeout(function(){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let obj = createObj("graphic",{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; imgsrc: gType, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gmnotes: "blood", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pageid: gPage_id, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; left: gLeft, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tint_color: gColor, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; top: gTop, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rotation: randomInteger(360) - 1, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width: gWidth, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height: gWidth, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; layer: "map" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(obj){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; toFront(obj); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log(`BloodAndHonor: ERROR: Failed to create object with parameters: imgsrc=[${gType}] pageid=[${gPage_id}] left=[${gLeft}] tint_color=[${gColor}] top=[${gTop}] width=[${gWidth}] height=[${gWidth}]`); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; },50);
Ok, thanks guys; I'll give that a try!
So it looks like my issue was that the images I was trying to use were in my marketplace (they were purchased assets), but not in my uploaded library. After rectifying that, things work fine. Thanks!
The Aaron
Forum Champion
API Scripter
That makes sense, glad you got it working!