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

Calling on The Aaron - BloodandHonor

Like totally know this is now a essential defunct API, but in my opinion the greatest API to EVER exist.  The original creators seem to be MIA, but I can't help but notice The Aaron is on it for a fix.  What is the chance this has been updated since: 0.8.2 In addition what is the chances that someone out there The Aaron or not can update this great masterpiece.  The visceral combat that this flavors is amazing.  Dripping blood through the dungeon corridors, it adds a atmosphere that many other APIs just really can't touch.   We need this updated, or at least I do.  Does anyone know of a more up to date script or knows what happen to this?
Works fine for me, what is it doing?
1533650119
The Aaron
Pro
API Scripter
Yeah, I can probably make some updates to it if needed. I don't use it and haven't used it, but I have tried to keep it running for those that do.   So, what are you looking for?
So I notice it doesn't operate well when you stack it on top of a lot of other APIs and I was wondering anything could be updated or streamlined with it regarding that.  I don't know anything about coding but I was wondering in general if it needed to be updated at this point it hasn't been in numerous years but it's always worked great for me I just wanted to check in with anyone who worked on this to see.
1533661973
The Aaron
Pro
API Scripter
Volomon said: it doesn't operate well when you stack it on top of a lot of other APIs Can you go into a bit more detail about this?
I'll give you what I have it seems like when it's running with other scripts it eventually locks up and crashes the API. GroupInitiative G Torch G 5th Edition OGL by Roll20 Companion G Concentration G LazyExperience G Aura/Tint HealthColors G CombatTracker Critical.js BloodandHonor.js G StatusInfo New Script That's what I have currently.  I'm not sure if maybe it's something else but I've run into the same issue with BloodandHonor in a previous game.
1533664656
The Aaron
Pro
API Scripter
How does it not operate well?  What are the symptoms and observable behavior differences?
The API gives an error I'll have to wait till it happens again to post it.  Then the API has to be restarted before it locks up again. 
1533673561
The Aaron
Pro
API Scripter
Ok, once you get the error, I can probably fix it.
1533706652

Edited 1533709430
You don't know if this automatically still conflicts with Itsatrap do you?
1533730071
The Aaron
Pro
API Scripter
I have no idea.  I have a vague recollection of running across that but I don't remember if I fixed it or it fixed itself.  If you do find that it still conflicts, let me know and I'll take a look.
I actually have a version that works well with Its-a-Trap. Try this one out after putting in some of your own graphics. (I'm not the author. I just picked this up somewhere when last this discussion was up. :D ) var BloodSpatter = { version: '0.1.0', 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 hpCountUp: false, baseSize: 0.75, // 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: [ {'Your-own-graphic-here'}, ], pools: [ { 'src': 'Your-bloodpool-graphic-here', 'width': 100, 'height': 100 }, ], chooseBlood: function (type) { if (type === 'spatter') { return BloodSpatter.spatters[randomInteger(BloodSpatter.spatters.length) - 1]; } if (type === 'pool') { return BloodSpatter.pools[randomInteger(BloodSpatter.pools.length) - 1]; } }, getOffset: function () { return Math.random() &lt; 0.5 ? 1 : -1; }, bloodColor: function (gmnotes) { if (gmnotes.indexOf('bloodcolor_purple') !== -1) { return '#20124d'; } else if (gmnotes.indexOf('bloodcolor_blue') !== -1) { return '#00ffff'; } else if (gmnotes.indexOf('bloodcolor_orange') !== -1) { return '#ffff00'; } else if (gmnotes.indexOf('bloodcolor_green') !== -1) { return '#274e13'; } else if (gmnotes.indexOf('bloodcolor_black') !== -1) { return '000000'; } else { return '#a61c00'; } }, createBlood: function (token, multiplier, bloodType) { var pages = _.union([Campaign().get('playerpageid')], _.values(Campaign().get('playerspecificpages'))); var dropBlood = _.contains(pages, token.get('pageid')); var gmNotes = token.get('gmnotes'); if (!dropBlood || token.get('layer') !== 'objects' || gmNotes.indexOf('noblood') !== -1) { return; } var size = Math.floor(BloodSpatter.getTokenSize(token) * multiplier); var bloodImage = BloodSpatter.chooseBlood(bloodType); var bloodTokenSource = bloodImage; var bloodTokenWidth = size * multiplier; var bloodTokenHeight = size * multiplier; if (bloodImage !== null &amp;&amp; typeof(bloodImage) === 'object') { bloodTokenSource = bloodImage.src; var bloodImageAspectRatio = bloodImage.width / bloodImage.height; var widthRatioMultiplier = 1; var heightRatioMultiplier = 1; if (bloodImageAspectRatio &lt; 1) { widthRatioMultiplier = bloodImageAspectRatio; } else if (bloodImageAspectRatio &gt; 1) { heightRatioMultiplier = bloodImage.height / bloodImage.width; } bloodTokenWidth = bloodTokenWidth * widthRatioMultiplier; bloodTokenHeight = bloodTokenHeight * heightRatioMultiplier; } var widthIncrement = bloodTokenWidth * 0.1; var widthIncrementTotal = widthIncrement; var heightIncrement = bloodTokenHeight * 0.1; var heightIncrementTotal = heightIncrement; var spatterToken = BloodSpatter.fixedCreateObj('graphic', { pageid: token.get('_pageid'), imgsrc: bloodTokenSource, tint_color: BloodSpatter.bloodColor(gmNotes), gmnotes: 'blood', top: token.get('top') + (randomInteger(Math.floor(size / 2)) * BloodSpatter.getOffset()), left: token.get('left') + (randomInteger(Math.floor(size / 2)) * BloodSpatter.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 () { BloodSpatter.timeout += 4; BloodSpatter.watchTimeout(); }, interval: null, watchTimeout: function () { if (BloodSpatter.interval === null) { BloodSpatter.interval = setInterval(function () { if (BloodSpatter.timeout &gt; 0) { BloodSpatter.timeout--; } else { clearInterval(BloodSpatter.interval); BloodSpatter.interval = null; } }, 2000); } }, fixedCreateObj: function () { return function () { var obj = createObj.apply(this, arguments); if (obj &amp;&amp; !obj.fbpath) { obj.fbpath = obj.changed._fbpath.replace(/([^\/]*\/){4}/, '/'); } return obj; }; }(), tokenHPChanged: function (token, maxHealth, currentHealth, damageTaken) { if (maxHealth === '') { return; } var percentOfHpLost = damageTaken / maxHealth; var damageMultiplier = BloodSpatter.baseSize + percentOfHpLost; if ((!BloodSpatter.hpCountUp &amp;&amp; currentHealth &lt;= maxHealth / 2) || (BloodSpatter.hpCountUp &amp;&amp; currentHealth &gt;= maxHealth / 2)) { token.set({ status_red: true }); // Create spatter near token if "bloodied". Chance of spatter depends on severity of damage if (damageTaken &gt; 0 &amp;&amp; currentHealth &gt; 0 &amp;&amp; ( (!BloodSpatter.hpCountUp &amp;&amp; currentHealth &lt; randomInteger(maxHealth)) || (BloodSpatter.hpCountUp &amp;&amp; currentHealth &gt; randomInteger(maxHealth)) )) { BloodSpatter.createBlood(token, damageMultiplier, 'spatter'); } } else { token.set({ status_red: false }); } if ((!BloodSpatter.hpCountUp &amp;&amp; currentHealth &lt;= 0) || (BloodSpatter.hpCountUp &amp;&amp; currentHealth &gt;= maxHealth)) { token.set({ status_skull: true }); // Create pool near token if health drops below 1. if (damageTaken &gt; 0) { BloodSpatter.createBlood(token, damageMultiplier, 'pool'); } } else { token.set({ status_skull: false }); } } }; on('ready', function () { on('change:graphic:bar' + BloodSpatter.hpBar + '_value', function (token, prev) { var maxHealth = token.get('bar' + BloodSpatter.hpBar + '_max'); var currentHealth = token.get('bar' + BloodSpatter.hpBar + '_value'); var previousHealth = prev['bar' + BloodSpatter.hpBar + '_value']; var damageTaken; if (!BloodSpatter.hpCountUp) { damageTaken = previousHealth - currentHealth; } else { damageTaken = currentHealth - previousHealth; } BloodSpatter.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' + BloodSpatter.hpBar + '_max'); if (maxHealth === '' || BloodSpatter.timeout !== 0) { return; } var currentHealth = token.get('bar' + BloodSpatter.hpBar + '_value'); var healthLost = maxHealth - currentHealth; var percentOfHpLost = healthLost / maxHealth; var damageMultiplier = (BloodSpatter.baseSize / 2) + percentOfHpLost; if ((!BloodSpatter.hpCountUp &amp;&amp; currentHealth &lt;= maxHealth / 2 &amp;&amp; currentHealth &lt; randomInteger(maxHealth)) || (BloodSpatter.hpCountUp &amp;&amp; currentHealth &gt;= maxHealth / 2 &amp;&amp; currentHealth &gt; randomInteger(maxHealth))) { BloodSpatter.createBlood(token, damageMultiplier, 'spatter'); BloodSpatter.increaseTimeout(); } }); on('chat:message', function (msg) { if (msg.type === 'api' &amp;&amp; (msg.content.indexOf('!clearblood') !== -1 || msg.content.indexOf('!clear blood') !== -1)) { if (BloodSpatter.onlyAllowGMtoRunCommands &amp;&amp; !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' &amp;&amp; obj.get('gmnotes') === 'blood') { return true; } else { return false; } }); _.each(objects, function (obj) { obj.remove(); }); } } }); });
Thanks a lot Raven!