This is because API script changes do not cause events. This version should get triggered by TokenMod: /////////////////////////////////////////////////
/***********************************************/
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,
// 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
// 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="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/6993500/mAA-8agYIwkhEciVVSCFmg/thumb.png?1420411542" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/6993500/mAA-8agYIwkhEciVVSCFmg/thumb.png?1420411542</a>",
],
pools: [
//"<a href="https://s3.amazonaws.com/files.d20.io/images/6993478/77YowTZze57mGAHfSaxwYg/thumb.png?1420411480" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/6993478/77YowTZze57mGAHfSaxwYg/thumb.png?1420411480</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 > 0) {
BloodAndHonor.timeout--;
} else {
return;
}
}
};
on("ready", function(obj) {
setInterval(function(){BloodAndHonor.onTimeout()},1000);
let handleBarChange = 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") <= obj.get("bar3_max") / 2 && prev["bar3_value"] > obj.get("bar3_value") && obj.get("bar3_value") > 0) {
var m=parseInt(obj.get('bar3_max'),10)||1,
v=parseInt(obj.get('bar3_value'),10)||1,
r=randomInteger(m);
if (r>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") <= 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")));
}
};
on("change:graphic:bar3_value", handleBarChange);
if('undefined' !== typeof TokenMod && TokenMod.ObserveTokenChange){
TokenMod.ObserveTokenChange((obj,prev)=>{
if(obj.get('bar3_value')!==prev.bar3_value){
handleBarChange(obj,prev);
}
});
}
//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") <= obj.get("bar3_max") / 2 && (obj.get("gmnotes")).indexOf("noblood") == -1) {
var m=parseInt(obj.get('bar3_max'),10)||1,
v=parseInt(obj.get('bar3_value'),10)||1,
r=randomInteger(m);
if (r>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);
});
}
}
});
});