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

[Script] Blood Spatter and Status Markers

1439511981

Edited 1526107256
Kryx
Pro
Sheet Author
API Scripter
Code I have been consistently having script failures during my sessions - I'd have to restart my scripts every few minutes without any error. I saw that  BloodiedAndDeadStatusMarkers had a listed conflict with  BloodAndHonor likely due to them both watching the same bar on the token. So I combined these 2 scripts to hopefully prevent any conflict. I've also removed isGM in favor if playerIsGM. I have also re-written the interval for BloodAndHonor so that it only runs the interval when it needs to decrement the timeout - it then clears the interval. This should help clear up resources and maybe fix the issue. It seems to be good so far, but I'll report back after using it for the weekend. I'm terrible at creating documentation, but maybe if people find this useful I can copy the documentation from blood and honor to my own script wiki. Code
1439556290
DK Heinrich
Marketplace Creator
Sheet Author
Will try to plug it in (and reverse the values for my system) and see what I can break on it today. I had an error that I could not find when I modified Blood and Honor  here . 
Mixing scripts is like mixing drinks.  You do so carefully.
1439557776

Edited 1439558131
DK Heinrich
Marketplace Creator
Sheet Author
installing causes !powercards to not report (no crash, just nothing in chat) while !powercards is disabled it works fine (even after I flipped the < > as needed for my system). I still need to look at the conditions and when they tag - but blood is a go.  If you have any ideas on what conflict with !powercards is let me know and I will test away.
1439558066

Edited 1439572618
Kryx
Pro
Sheet Author
API Scripter
DK Heinrich said: installing causes !powercards to not report (no crash, just nothing in chat) And yet Blood and Honor and Status markers worked fine for you with powercards? I can't imagine why powercards would break. All my other scripts work. Make sure you replaced the pool and spatter images with your own.
1439558185

Edited 1439558211
DK Heinrich
Marketplace Creator
Sheet Author
did not ever use status markers, blood and honor did. yes, all my own images - and they pop fine once powercards is disabled 
1439558421
DK Heinrich
Marketplace Creator
Sheet Author
also when adjusting health on a token larger than 1 unit (say a large creature) the script crashes (as did original blood and honor)  Your scripts are currently disabled due to an error that was detected. Please make appropriate changes to your scripts and click the "Save Script" button and we'll attempt to start running them again. More info... For reference, the error message generated was:  /home/symbly/www/d20-api-server/node_modules/firebase/lib/firebase-node.js:1 orts, require, module, __filename, __dirname) { function g(a){throw a;}var j=v ^ TypeError: Cannot call method 'set' of undefined at handleTokenChange (evalmachine.<anonymous>:601:68) at eval (
1439558670
Ziechael
Forum Champion
Sheet Author
API Scripter
Since it is being generally overhauled i have made some customisations (with a little help from a certain scriptomancer in all honesty) to my blood and honour script that might be worth incorporating (in bold below): The script will only create spatters and trails on active pages (either the ribbon or other pages with players on them) !clearblood will delete the spatters and trails rather than group them top and left. ///////////////////////////////////////////////// /***********************************************/ var BloodAndHonor = { &nbsp; &nbsp; author: { &nbsp; &nbsp; &nbsp; &nbsp; 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", 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, // 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 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="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>", &nbsp; &nbsp; &nbsp; &nbsp; "<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>", &nbsp; &nbsp; &nbsp; &nbsp; "<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>", &nbsp; &nbsp; &nbsp; &nbsp; "<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>", &nbsp; &nbsp; &nbsp; &nbsp; "<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>", &nbsp; &nbsp; &nbsp; &nbsp; "<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>", &nbsp; &nbsp; &nbsp; &nbsp; "<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>", &nbsp; &nbsp; &nbsp; &nbsp; "<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>", &nbsp; &nbsp; &nbsp; &nbsp; "<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>", &nbsp; &nbsp; &nbsp; &nbsp; "<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>", &nbsp; &nbsp; &nbsp; &nbsp; "<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>", &nbsp; &nbsp; &nbsp; &nbsp; "<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>", &nbsp; &nbsp; &nbsp; &nbsp; "<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"; &nbsp; &nbsp; &nbsp; &nbsp; if (gmnotes.indexOf("bloodcolor_black") !== -1) return "#000000"; &nbsp; &nbsp; &nbsp; &nbsp; if (gmnotes.indexOf("bloodcolor_green") !== -1) return "#008000"; 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(fixedCreateObj("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; } } }; fixedCreateObj = (function () { return function () { var obj = createObj.apply(this, arguments); if (obj && !obj.fbpath) { obj.fbpath = obj.changed._fbpath.replace(/([^\/]*\/){4}/, "/"); } return obj; }; }()); on("ready", function(obj) { setInterval(function(){BloodAndHonor.onTimeout()},1000); on("change:graphic:bar3_value", function(obj, prev) { &nbsp; &nbsp; &nbsp; &nbsp; var pages = _.union([Campaign().get('playerpageid')], _.values(Campaign().get('playerspecificpages'))); &nbsp; &nbsp; &nbsp; &nbsp; if( ! _.contains(pages,obj.get('pageid')) ) { &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; } 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) { if (randomInteger(obj.get("bar3_max")) &gt; obj.get("bar3_value")) { 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) { &nbsp; &nbsp; &nbsp; &nbsp; var pages = _.union([Campaign().get('playerpageid')], _.values(Campaign().get('playerspecificpages'))); &nbsp; &nbsp; &nbsp; &nbsp; if( ! _.contains(pages,obj.get('pageid')) ) { &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; } if (BloodAndHonor.timeout == 0) { if (obj.get("bar3_value") &lt;= obj.get("bar3_max") / 2 && (obj.get("gmnotes")).indexOf("noblood") == -1) { if (randomInteger(obj.get("bar3_max")) &gt; obj.get("bar3_value")) { 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 && !isGM(msg.playerid)) { sendChat(msg.who,"/w " + msg.who + " You are not authorized to use that command!"); return; } else { objects = filterObjs(function(obj) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var pages = _.union([Campaign().get('playerpageid')], _.values(Campaign().get('playerspecificpages'))); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( ! _.contains(pages,obj.get('pageid')) ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } if(obj.get("type") == "graphic" && obj.get("gmnotes") == "blood") return true; else return false; }); _.each(objects, function(obj) { obj.remove(); }); } } }); });
1439558897
DK Heinrich
Marketplace Creator
Sheet Author
not sure what - but disabled both again (3rd time actually) and re-enabled both and they appear to be happy again (this and powercards).&nbsp; Now only issue I have is the above crash on bigger targets... side note - is there a script that will take the damage reported from powercards and adjust the bar_3 on the target? I think that BarAdjust should do it but I have not been able to make it happen.&nbsp;
1439559183

Edited 1439559397
Kryx
Pro
Sheet Author
API Scripter
DK Heinrich said: also when adjusting health on a token larger than 1 unit (say a large creature) the script crashes (as did original blood and honor)&nbsp; I never had it do that. I just tested it on an ancient black dragon no problem. Can you provide some kind of reproduction path? I'm also confused as it says line 601, but the script only has ~200 lines. DK Heinrich said: side note - is there a script that will take the damage reported from powercards and adjust the bar_3 on the target? I think that BarAdjust should do it but I have not been able to make it happen. No idea - that's something you'd have to take up w/ powercards people. Ziechael said: Since it is being generally overhauled i have made some customisations (with a little help from a certain scriptomancer in all honesty) to my blood and honour script that might be worth incorporating (in bold below): The script will only create spatters and trails on active pages (either the ribbon or other pages with players on them) !clearblood will delete the spatters and trails rather than group them top and left. Great alterations! I had the tokens removed on "!clearblood" from long ago and had it incorporated in my code already. I also noticed the blood appeared on other pages. I'll incorporate that as well!
1439559650

Edited 1439560007
DK Heinrich
Marketplace Creator
Sheet Author
Mark said: DK Heinrich said: also when adjusting health on a token larger than 1 unit (say a large creature) the script crashes (as did original blood and honor)&nbsp; I never had it do that. I just tested it on an ancient black dragon no problem. Can you provide further details? I tested it on a dozen single unit tokens and perfect, trying it on the only 2x2 token I have set up and it crashes. giving the above info and the notes here. Next trying to enlarge the token of one that already works to see if that replicates the problem or not. EDIT - testing on a token that I stretch from 1 unit to 2 works fine... next deleting the 2 unit monster and rebuilding it to see how it goes.&nbsp; /home/symbly/www/d20-api-server/node_modules/firebase/lib/firebase-node.js:1 orts, require, module, __filename, __dirname) { function g(a){throw a;}var j=v &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; ^ TypeError: Cannot call method 'set' of undefined &nbsp; &nbsp; at handleTokenChange (evalmachine.&lt;anonymous&gt;:1406:68) &nbsp; &nbsp; at eval (
1439559798
Kryx
Pro
Sheet Author
API Scripter
So it works for you if the token is of "medium" (D&D term) size, but not larger, is that correct?&nbsp; The error message there is different from the one you put above - it says line 1406. ".set" is only called 4 times in the script - all of them related to the status markers and all of them requiring an object which is needed elsewhere and would error there before erroring here. It sounds like a different script is erroring.
1439560548
DK Heinrich
Marketplace Creator
Sheet Author
correct. One error message is in the 'pink' box, the other is in the 'black' box - they do read differently to me also - but my tiny brain has hard time deciphering what they mean. :) That is possible, let me disable the rest of the crap and see what happens.&nbsp;
1439561275
DK Heinrich
Marketplace Creator
Sheet Author
of course 1 of the 2 that I had not turned on and off is the culprit. when !bump is enabled and targeting a large token I get the crash below /home/symbly/www/d20-api-server/node_modules/firebase/lib/firebase-node.js:1 orts, require, module, __filename, __dirname) { function g(a){throw a;}var j=v ^ TypeError: Cannot call method 'set' of undefined at handleTokenChange (evalmachine.&lt;anonymous&gt;:1406:68) at eval ( !bump is disabled and the large token works fine. Other scripts seem to be fine (powercards, ammo, isGM, pic and this one).
1439561603

Edited 1439561629
Kryx
Pro
Sheet Author
API Scripter
Sweet. I'm making some more optimization changes. After that I can tell you which lines to reverse to count up for hp. It should be super easy. One of which is getting rid of the token size and calculating it - so blood pools for dragons are appropriately sized now.
1439562036
DK Heinrich
Marketplace Creator
Sheet Author
sounds good - I was able to reverse the math already and its rocking good.&nbsp; and actually with !bump disabled I can also use !baradjust to adjust the damage (bar_3) value - but it bypasses this script so only triggers blood trails not the splatter/pool/red-dot. So still more work to do on getting the splatter to trigger from the 'hit' as opposed to the addition of damage with a powercard :)&nbsp; great work on this one, not sure I mentioned that! :)
1439563804

Edited 1439572637
Kryx
Pro
Sheet Author
API Scripter
I could move the spatter/pool on damage to a function and you could try calling that function. I'm not sure it would work across scripts though.
1439568637

Edited 1439572549
Kryx
Pro
Sheet Author
API Scripter
0.02 Get size of token instead of defaulting to 70 Keep aspect ratio if you get each image's width and height Moved all of createBlood's if statements to that function. Also moved all of the token variables like location, size etc to all be there as well Added a random size adjustment to increase/decrease the blood image size by up to 25% For the spatters and pools arrays you can use the old plain array of image sources or the new array of objects that can set the width and height of the image (for aspect ratio purposes) and an adjuster if one image is too big/small. The aspect ratio part should be nice - so my 200x88 blood spatter is no longer warped out of proper proportions.
1439572538
Kryx
Pro
Sheet Author
API Scripter
0.03 blood spatter instead of splatter. size multiplier now based on damage taken / total damage lost
1439572857
Stephen S.
Pro
Marketplace Creator
Sheet Author
API Scripter
We demand animated GIF examples.
1439573280
Stephen S.
Pro
Marketplace Creator
Sheet Author
API Scripter
and briefly visible&nbsp;onomatopoeia...
1439573373

Edited 1439574005
Kryx
Pro
Sheet Author
API Scripter
@Stephen See&nbsp; <a href="https://app.roll20.net/forum/post/1477230/script-b" rel="nofollow">https://app.roll20.net/forum/post/1477230/script-b</a>... for an example of what the spatter looks like. I'm not a great gif maker, but I can try to make something in a few days when I feel the script is stable. I found another feature I'd like to do: Have the blood grow from nothing instead of just appearing. It'll take more resources, but shouldn't be bad. See&nbsp; <a href="https://app.roll20.net/forum/post/869900/script-to" rel="nofollow">https://app.roll20.net/forum/post/869900/script-to</a>... for animated gif of that effect.
1439574073
Kryx
Pro
Sheet Author
API Scripter
Stephen S. said: and briefly visible&nbsp;onomatopoeia... That would be AMAZING for the right type of game (re: Superheroes). I wouldn't use it, but some may. If there was a large desire I could add that as an option thing after the core script is done.
1439574371

Edited 1439574464
DK Heinrich
Marketplace Creator
Sheet Author
could the BAM auto delete after 30 seconds or something? floor covered in blood is ok, but in words is just odd :) will update to .3 and adjust to my math and see how it rocks. EDIT: I will once you make it available :)
1439574815
Kryx
Pro
Sheet Author
API Scripter
Ya, if I do it then it'd disappear after a while. Did you try the updated sizes based on damage? Works pretty well for me.
1439574954
DK Heinrich
Marketplace Creator
Sheet Author
not yet - did not see where to grab it (the link in 1st post shows dead end now)
1439575190
Kryx
Pro
Sheet Author
API Scripter
Updated Code Link . Did it above as well.
1439581494

Edited 1439581518
Kryx
Pro
Sheet Author
API Scripter
0.04 Spatter zooms in by 10% of its size every 30 ms for a total transition time of 300ms.
1439581786
Kryx
Pro
Sheet Author
API Scripter
@DK if you're using Honeybadger's&nbsp; [Script] Alter Bar on Token then I could possibly whip up a fix as was done here:&nbsp; <a href="https://app.roll20.net/forum/permalink/1478741/" rel="nofollow">https://app.roll20.net/forum/permalink/1478741/</a>
1439582964

Edited 1439583093
DK Heinrich
Marketplace Creator
Sheet Author
That is the one I want to use - but I am about to be away from computer for the weekend - I will not be screwing with it again until monday :) &nbsp;if you feel froggy I will do all the testing of whatever you come up with then.&nbsp; EDIT: And yes - the fix in the 2nd link you posted is exactly what I am wanting to do - keep from fiddling with the little circle so that the blood splats when hit.&nbsp;
1439664584
Kryx
Pro
Sheet Author
API Scripter
@DK and&nbsp;Dan from&nbsp; this thread . I've moved the spatter to a function that should be able to be called from alter bars.&nbsp;This is how I call it on my script now: BloodSpatterAndStatusMarkers.tokenHPChanged(token, maxHealth, currentHealth, damageTaken); This is how you'll call it on alter bars: var alterAmount = parseInt(AlterValue, 10), &nbsp; currentHealth = CurrentValue + alterAmount; BloodSpatterAndStatusMarkers.tokenHPChanged(Target, MaxValue, currentHealth, alterAmount * -1); After this line: var NoAnnounce = n[4]; That works for me.
1439753066
Kryx
Pro
Sheet Author
API Scripter
FYI this script fixes all my issues that I had with Blood and Honor + Bloodied and Dead status markers. I ran a full session without having to reset the API every 5 minutes (literally). It was amazing!!
Nice, I'm going to give this one a try.
1439822082
DK Heinrich
Marketplace Creator
Sheet Author
updating this and alter bars - as long as my isp stays up (stupid storms...) I will let you know if I break it&nbsp;
1439822785
DK Heinrich
Marketplace Creator
Sheet Author
width and height for your images - you just using the actual ones from the image you are using?
1439823249
Kryx
Pro
Sheet Author
API Scripter
To do it: open image library on roll20 search for "blood" (or whatever) right clicked one, inspect element hover over the url in the &lt;img src="URL"&gt; It will show "(Natural: WIDTH x HEIGHT pixels)". Use those numbers. You can also use the old array system. Both work - this way just ensures that images keep their aspect ratio to prevent distortion.
1439823860
DK Heinrich
Marketplace Creator
Sheet Author
got um! and I think i got my math flipped around - just entering the test phase now.
1439826431

Edited 1439826956
DK Heinrich
Marketplace Creator
Sheet Author
got the conditions to pop correctly, but cannot get any spatter or pools to pop (after reversing math) if (currentHealth &gt;= maxHealth / 2) { token.set({ status_redmarker: true }); // Create spatter near token if "bloodied". Chance of spatter depends on severity of damage if (damageTaken &gt; 0 && currentHealth &gt; 0 && currentHealth &gt; randomInteger(maxHealth)) { BloodSpatterAndStatusMarkers.createBlood(token, damageMultiplier, 'spatter'); flipped &lt;= to &gt;= on 1st line, and &lt; to &gt; before randomInteger(maxHealth) if (currentHealth &gt;= maxHealth) { token.set({ status_dead: true }); // Create pool near token if health drops below 1. if(damageTaken &gt; 0) { BloodSpatterAndStatusMarkers.createBlood(token, damageMultiplier, 'pool'); changed 0 to maxHealth in line 1.&nbsp; EDIT: also have this change for trails. if (currentHealth &gt;= maxHealth / 2 && currentHealth &gt; randomInteger(maxHealth)) { BloodSpatterAndStatusMarkers.createBlood(token, damageMultiplier, 'spatter'); BloodSpatterAndStatusMarkers.increaseTimeout(); Flipped both symbols around.
1439826828
DK Heinrich
Marketplace Creator
Sheet Author
basically currentHealth = damageTaken in my system - so it goes up instead of HP going down. (you know this, but if anyone else is reading they might not know).
1439827288
Kryx
Pro
Sheet Author
API Scripter
If status markers work and pools don't then something is wrong with damageTaken. It is likely below 0. Try reversing it on alterbars end.
1439827979
DK Heinrich
Marketplace Creator
Sheet Author
with alterbars disabled, I get blood trails on movement but no spatters or pools when taking damage or dying (conditions still trigger correctly). Looking at alterbars I am honestly not sure where to / what to change, nothing looks (to my novice ass) like it needs to be flipped.&nbsp;
1439828112
Kryx
Pro
Sheet Author
API Scripter
Ah, then you didn't flip this one correctly. See "damageTaken &gt; 0" that you posted above? Flip that.
1439828778
DK Heinrich
Marketplace Creator
Sheet Author
perfect, change it in both spots above and we are now all bloody. Thanks again! (next to get !alter to work with !powercards...) Next option for you - when I hit a 'large' creature the blood appears under his token and is not visible until he moves. Is there something I need to tweak? or is it random what 'edge' the blood pops at and I am just getting unlucky so far?
1439829800
Kryx
Pro
Sheet Author
API Scripter
The offset is random. Though the size of the blood pool is based on the damage. With your reversing it could be creating smaller pools. I actually think you should return damageTaken back to it's normal state. "damageTaken" needs to be reversed both on my script and on alter bars. On line 234 of my script: damageTaken = prev['bar' + BloodSpatterAndStatusMarkers.hpBar + '_value'] - currentHealth; Should be&nbsp; damageTaken = currentHealth - prev['bar' + BloodSpatterAndStatusMarkers.hpBar + '_value']; On the alter bars code I put above: BloodSpatterAndStatusMarkers.tokenHPChanged(Target, MaxValue, currentHealth, alterAmount * -1); Should be BloodSpatterAndStatusMarkers.tokenHPChanged(Target, MaxValue, currentHealth, alterAmount); That SHOULD fix it.
1439833613
DK Heinrich
Marketplace Creator
Sheet Author
Mark said: That SHOULD fix it. Looks like it did - nothing 'not' working at the moment.&nbsp; Thanks again!
1439940314
Kryx
Pro
Sheet Author
API Scripter
Updated the script to remove the size multiplier on each image - shouldn't be necessary if you resize your images outside of roll20. I've also posted my blood pools and spatters to share on imgur:&nbsp; <a href="http://imgur.com/a/fydBq#0" rel="nofollow">http://imgur.com/a/fydBq#0</a>
1440076831
DK Heinrich
Marketplace Creator
Sheet Author
how many places does this change show up? do you think it would be easier to load it and make my changes to reverse the math? or leave what i have and remove the multiplier lines?&nbsp;
1440078595

Edited 1440078869
Kryx
Pro
Sheet Author
API Scripter
It's only in a few. if you post your script I can show you where. Or I could just maintain an opposite version for you as well. Post your script and I'll maintain it. Though the size multiplier per image doesn't really change anything in the end unless you used it, but maybe future changes will.
1440079429
DK Heinrich
Marketplace Creator
Sheet Author
ok, im not going to worry about it for now - but here is the reversed script just so you have it.&nbsp; var BloodSpatterAndStatusMarkers = { &nbsp; &nbsp; version: '0.04', 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>', hpBar: 3, //1, 2, or 3 // This will make it so only the GM can use the !clearblood command. Change to "true" if you want to check for authorization. onlyAllowGMtoRunCommands: true, // 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: [ { 'src': '<a href="https://s3.amazonaws.com/files.d20.io/images/11308495/wgpCBVKLA9xkZBPLZs2Jfw/thumb.png?1438782756" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/11308495/wgpCBVKLA9xkZBPLZs2Jfw/thumb.png?1438782756</a>', 'width': 200, 'height': 171 }, { 'src': '<a href="https://s3.amazonaws.com/files.d20.io/images/11308515/JPJbvubaL7Fbj7jCmMLRdw/thumb.png?1438782875" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/11308515/JPJbvubaL7Fbj7jCmMLRdw/thumb.png?1438782875</a>', 'width': 200, 'height': 171 }, { 'src': '<a href="https://s3.amazonaws.com/files.d20.io/images/11308554/wO9ME0h45T74xq29GpTlxw/thumb.png?1438783132" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/11308554/wO9ME0h45T74xq29GpTlxw/thumb.png?1438783132</a>', 'width': 200, 'height': 171 }, { 'src': '<a href="https://s3.amazonaws.com/files.d20.io/images/11308568/YV9GDW2btgqpGf9LbCi8Og/thumb.png?1438783190" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/11308568/YV9GDW2btgqpGf9LbCi8Og/thumb.png?1438783190</a>', 'width': 200, 'height': 127 }, { 'src': '<a href="https://s3.amazonaws.com/files.d20.io/images/11308599/07Znimavzx-DqON9R2NtrA/thumb.png?1438783373" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/11308599/07Znimavzx-DqON9R2NtrA/thumb.png?1438783373</a>', 'width': 141, 'height': 200 }, { 'src': '<a href="https://s3.amazonaws.com/files.d20.io/images/11308621/IRkRSt7rxYUzu9df2XSBVw/thumb.png?1438783490" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/11308621/IRkRSt7rxYUzu9df2XSBVw/thumb.png?1438783490</a>', 'width': 200, 'height': 150 }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { 'src': '<a href="https://s3.amazonaws.com/files.d20.io/images/11308646/5rvvjhNrq2f-yDpOP4QvhQ/thumb.png?1438783656" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/11308646/5rvvjhNrq2f-yDpOP4QvhQ/thumb.png?1438783656</a>', 'width': 200, 'height': 172 }, &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'src': '<a href="https://s3.amazonaws.com/files.d20.io/images/11308660/y29gFvkPhkbzqmXQTZiHfg/thumb.png?1438783726" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/11308660/y29gFvkPhkbzqmXQTZiHfg/thumb.png?1438783726</a>', 'width': 143, 'height': 200 }, { 'src': '<a href="https://s3.amazonaws.com/files.d20.io/images/11308636/jWVMPfRh_eFiEy75AZ27Ng/thumb.png?1438783602" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/11308636/jWVMPfRh_eFiEy75AZ27Ng/thumb.png?1438783602</a>', 'width': 200, 'height': 142 } ], pools: [ { 'src': '<a href="https://s3.amazonaws.com/files.d20.io/images/11308586/mVAuc41Amb78bnO5iTMSPg/thumb.png?1438783301" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/11308586/mVAuc41Amb78bnO5iTMSPg/thumb.png?1438783301</a>', 'width': 185, 'height': 200 }, { 'src': '<a href="https://s3.amazonaws.com/files.d20.io/images/11308609/G8y5VJNFrMZzwer_Gth8QA/thumb.png?1438783421" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/11308609/G8y5VJNFrMZzwer_Gth8QA/thumb.png?1438783421</a>', 'width': 160, 'height': 200, //'sizeAdjustment': 1.4 } ], chooseBlood: function (type) { if (type === 'spatter') { return BloodSpatterAndStatusMarkers.spatters[randomInteger(BloodSpatterAndStatusMarkers.spatters.length) - 1]; } if (type === 'pool') { return BloodSpatterAndStatusMarkers.pools[randomInteger(BloodSpatterAndStatusMarkers.pools.length) - 1]; } }, getOffset: function () { return Math.random() &lt; 0.5 ? 1 : -1; }, bloodColor: function (gmnotes) { if (gmnotes.indexOf('bloodcolor_purple') !== -1) { return '#0000ff'; } else if (gmnotes.indexOf('bloodcolor_blue') !== -1) { return '#00ffff'; } else if (gmnotes.indexOf('bloodcolor_orange') !== -1) { return '#ffff00'; } else { return 'transparent'; } }, createBlood: function (token, multiplier, bloodType) { var pages = _.union([Campaign().get('playerpageid')], _.values(Campaign().get('playerspecificpages'))), dropBlood = _.contains(pages, token.get('pageid')), gmNotes = token.get('gmnotes'); if(!dropBlood || token.get('layer') !== 'objects' || gmNotes.indexOf('noblood') !== -1) { return; } var size = Math.floor(BloodSpatterAndStatusMarkers.getTokenSize(token) * multiplier), bloodImage = BloodSpatterAndStatusMarkers.chooseBlood(bloodType), bloodTokenSource = bloodImage, bloodTokenWidth = size * multiplier, bloodTokenHeight = size * multiplier; if(bloodImage !== null && typeof(bloodImage) === 'object') { bloodTokenSource = bloodImage.src; var bloodImageAspectRatio = bloodImage.width / bloodImage.height, widthRatioMultiplier = 1, heightRatioMultiplier = 1, sizeAdjustment = 1; if(bloodImage.sizeAdjustment) { sizeAdjustment = bloodImage.sizeAdjustment; } if(bloodImageAspectRatio &lt; 1) { widthRatioMultiplier = bloodImageAspectRatio; } else if (bloodImageAspectRatio &gt; 1) { heightRatioMultiplier = bloodImage.height / bloodImage.width; } bloodTokenWidth = bloodTokenWidth * widthRatioMultiplier * sizeAdjustment; bloodTokenHeight = bloodTokenHeight * heightRatioMultiplier * sizeAdjustment; } var widthIncrement = bloodTokenWidth * 0.1, widthIncrementTotal = widthIncrement, heightIncrement = bloodTokenHeight * 0.1, heightIncrementTotal = heightIncrement, spatterToken = BloodSpatterAndStatusMarkers.fixedCreateObj('graphic', { pageid: token.get('_pageid'), imgsrc: bloodTokenSource, tint_color: BloodSpatterAndStatusMarkers.bloodColor(gmNotes), gmnotes: 'blood', top: token.get('top') + (randomInteger(Math.floor(size / 2)) * BloodSpatterAndStatusMarkers.getOffset()), left: token.get('left') + (randomInteger(Math.floor(size / 2)) * BloodSpatterAndStatusMarkers.getOffset()), width: widthIncrement, height: heightIncrement, rotation: randomInteger(360) - 1, layer: 'map' }); toFront(spatterToken); (function splatterEnlargeFunction (count) { if (count &lt; 10) { setTimeout(function () { widthIncrementTotal += widthIncrement; heightIncrementTotal += heightIncrement; spatterToken.set({ width: widthIncrementTotal, height: heightIncrementTotal }); splatterEnlargeFunction(count + 1); }, 30); } })(0); }, getTokenSize: function (token) { return (token.get('height') + token.get('width')) / 2; //average the height and the width }, timeout: 0, increaseTimeout: function () { BloodSpatterAndStatusMarkers.timeout += 2; BloodSpatterAndStatusMarkers.watchTimeout(); }, interval: null, watchTimeout: function () { if (BloodSpatterAndStatusMarkers.interval === null) { BloodSpatterAndStatusMarkers.interval = setInterval(function () { if (BloodSpatterAndStatusMarkers.timeout &gt; 0) { BloodSpatterAndStatusMarkers.timeout--; } else { clearInterval(BloodSpatterAndStatusMarkers.interval); BloodSpatterAndStatusMarkers.interval = null; } }, 2000); } }, fixedCreateObj: function () { return function () { var obj = createObj.apply(this, arguments); if (obj && !obj.fbpath) { obj.fbpath = obj.changed._fbpath.replace(/([^\/]*\/){4}/, '/'); } return obj; }; }(), tokenHPChanged: function (token, maxHealth, currentHealth, damageTaken) { if (maxHealth === '') { return; } var percentOfHpLost = damageTaken / maxHealth, damageMultiplier = 1 + Math.min(percentOfHpLost / 2, 0.5); if (currentHealth &gt;= maxHealth / 2) { token.set({ status_redmarker: true }); // Create spatter near token if "bloodied". Chance of spatter depends on severity of damage if (damageTaken &gt; 0 && currentHealth &gt; 0 && currentHealth &gt; randomInteger(maxHealth)) { BloodSpatterAndStatusMarkers.createBlood(token, damageMultiplier, 'spatter'); } } else { token.set({ status_redmarker: false }); } if (currentHealth &gt;= maxHealth) { token.set({ status_dead: true }); // Create pool near token if health drops below 1. if(damageTaken &gt; 0) { BloodSpatterAndStatusMarkers.createBlood(token, damageMultiplier, 'pool'); } } else { token.set({ status_dead: false }); } } }; on('ready', function () { on('change:graphic:bar' + BloodSpatterAndStatusMarkers.hpBar + '_value', function (token, prev) { var maxHealth = token.get('bar' + BloodSpatterAndStatusMarkers.hpBar + '_max'), currentHealth = token.get('bar' + BloodSpatterAndStatusMarkers.hpBar + '_value'), damageTaken = currentHealth - prev['bar' + BloodSpatterAndStatusMarkers.hpBar + '_value']; BloodSpatterAndStatusMarkers.tokenHPChanged(token, maxHealth, currentHealth, damageTaken); }); //Make blood trails, chance goes up depending on how injured a token is on('change:graphic:lastmove', function (token) { var maxHealth = token.get('bar' + BloodSpatterAndStatusMarkers.hpBar + '_max'); if (maxHealth === '' || BloodSpatterAndStatusMarkers.timeout !== 0) { return; } var currentHealth = token.get('bar' + BloodSpatterAndStatusMarkers.hpBar + '_value'), healthLost = maxHealth - currentHealth, percentOfHpLost = healthLost / maxHealth, damageMultiplier = .5 + Math.min(percentOfHpLost / 2, 0.5); if (currentHealth &gt;= maxHealth / 2 && currentHealth &gt; randomInteger(maxHealth)) { BloodSpatterAndStatusMarkers.createBlood(token, damageMultiplier, 'spatter'); BloodSpatterAndStatusMarkers.increaseTimeout(); } }); on('chat:message', function (msg) { if (msg.type === 'api' && msg.content.indexOf('!clearblood') !== -1) { if (BloodSpatterAndStatusMarkers.onlyAllowGMtoRunCommands && !playerIsGM(msg.playerid)) { sendChat(msg.who, '/w ' + msg.who + ' You are not authorized to use that command!'); return; } else { var objects = filterObjs(function (obj) { if (obj.get('type') === 'graphic' && obj.get('gmnotes') === 'blood') { return true; } else { return false; } }); _.each(objects, function (obj) { obj.remove(); }); } } }); });
1440085398
Kryx
Pro
Sheet Author
API Scripter
@DK: I've integrated the reversed logic into the core script. You can just change it over to that with a toggle. I didn't test it, but it should work. This'll help for any future updates.
1440085617
DK Heinrich
Marketplace Creator
Sheet Author
awesome! I will test it asap (im in the middle of screwing around with !conditions atm, but soon).