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] Aura/Tint HealthColor - Freeing up Aura 2

Oh mighty powers that be, I am enjoying the mod - as are my players - yet the Aura 2 function of tokens is being constantly overwritten yet does not seem to be used in any... functional manner. Is it possible for there to be a command to enable Aura 2 on tokens to be free for manual input? Sometimes I want my players to show an aura on their character for a spell, such as spirit guardians. I would appreciate any assistance in this matter.
1554430607
The Aaron
Roll20 Production Team
API Scripter
Yeah, you can just remove the aura2 references.&nbsp; I've done that here for simplicity: /* global createObj TokenMod spawnFxWithDefinition getObj state playerIsGM sendChat _ findObjs log on*/ /* My Profile link: <a href="https://app.roll20.net/users/262130/dxwarlock" rel="nofollow">https://app.roll20.net/users/262130/dxwarlock</a> GIT link: <a href="https://github.com/dxwarlock/Roll20/blob/master/Public/HeathColors" rel="nofollow">https://github.com/dxwarlock/Roll20/blob/master/Public/HeathColors</a> Roll20Link: <a href="https://app.roll20.net/forum/post/4630083/script-aura-slash-tint-healthcolor" rel="nofollow">https://app.roll20.net/forum/post/4630083/script-aura-slash-tint-healthcolor</a> */ /*jshint bitwise: false*/ var HealthColors = HealthColors || (function () { 'use strict'; var version = '1.6.0', ScriptName = "HealthColors", schemaVersion = '1.0.3', Updated = "Feb 12 2019", /*------------------------ ON TOKEN CHANGE/CREATE ------------------------*/ handleToken = function (obj, prev, update) { //CHECK IF TRIGGERED------------ if(state.HealthColors.auraColorOn !== true || obj.get("layer") !== "objects") return; if(obj.get("represents") !== "" || (obj.get("represents") === "" &amp;&amp; state.HealthColors.OneOff === true)) { //**CHECK BARS------------// var barUsed = state.HealthColors.auraBar; var maxValue, curValue, prevValue; if(obj.get(barUsed + "_max") !== "" || obj.get(barUsed + "_value") !== "") { maxValue = parseInt(obj.get(barUsed + "_max"), 10); curValue = parseInt(obj.get(barUsed + "_value"), 10); prevValue = prev[barUsed + "_value"]; } if(isNaN(maxValue) || isNaN(curValue) || isNaN(prevValue)) return; //CALC PERCENTAGE------------ var percReal = Math.round((curValue / maxValue) * 100); var markerColor = PercentToHEX(percReal); //DEFINE VARIABLES--- var pColor = '#ffffff'; var GM = '',PC = ''; var IsTypeOn, PercentOn, ShowDead, UseAura; //**CHECK MONSTER OR PLAYER------------// var oCharacter = getObj('character', obj.get("_represents")); var type = (oCharacter === undefined || oCharacter.get("controlledby") === "") ? 'Monster' : 'Player'; var colortype = (state.HealthColors.auraTint) ? 'tint' : 'aura1'; //IF PLAYER------------ if(type == 'Player') { GM = state.HealthColors.GM_PCNames; PC = state.HealthColors.PCNames; IsTypeOn =state.HealthColors.PCAura; PercentOn = state.HealthColors.auraPercPC; ShowDead = state.HealthColors.auraDeadPC; var cBy = oCharacter.get('controlledby'); var player = getObj('player', cBy); pColor = '#000000'; if(player !== undefined) pColor = player.get('color'); } //IF MONSTER------------ else if(type == 'Monster') { GM = state.HealthColors.GM_NPCNames; PC = state.HealthColors.NPCNames; IsTypeOn =state.HealthColors.NPCAura; PercentOn = state.HealthColors.auraPerc; ShowDead = state.HealthColors.auraDead; } else return; //CHECK DISABLED AURA/TINT ATTRIB------------ if(oCharacter !== undefined) { UseAura = lookupUseColor(oCharacter); } //SET HEALTH COLOR---------- if(IsTypeOn &amp;&amp; UseAura !== "NO") { percReal = Math.min(percReal, 100); if(percReal &gt; PercentOn || curValue === 0) SetAuraNone(obj); else TokenSet(obj, state.HealthColors.AuraSize, markerColor, pColor, update); //SHOW DEAD---------- if(ShowDead === true) { if(curValue &gt; 0) obj.set("status_dead", false); else if(curValue &lt; 1) { var DeadSounds = state.HealthColors.auraDeadFX; if(DeadSounds !== "None" &amp;&amp; curValue != prevValue) PlayDeath(DeadSounds); obj.set("status_dead", true); SetAuraNone(obj); } } } else if((!IsTypeOn || UseAura === "NO") &amp;&amp; obj.get(colortype + '_color') === markerColor) SetAuraNone(obj); //SET SHOW NAMES------------ SetShowNames(GM,PC,obj); //**SPURT FX------------// if(curValue != prevValue &amp;&amp; prevValue != "" &amp;&amp; update !== "YES") { //CHECK BLOOD ATTRIB------------ var UseBlood; if(oCharacter !== undefined) { UseBlood = lookupUseBlood(oCharacter); } if(state.HealthColors.FX === true &amp;&amp; obj.get("layer") == "objects" &amp;&amp; (UseBlood !== "OFF" || UseBlood !== "NO")) { var HurtColor, HealColor, FX, aFX, FXArray = []; var amount = Math.abs(curValue - prevValue); var HitSizeCalc = Math.min((amount / maxValue) * 4, 1); var Scale = obj.get("height") / 70; var HitSize = Math.max(HitSizeCalc, 0.2) * (_.random(60, 100) / 100); //IF HEALED------------ if(curValue &gt; prevValue) { aFX = findObjs({_type: "custfx",name: '-DefaultHeal'}, {caseInsensitive: true})[0]; FX = aFX.get("definition"); HealColor = HEXtoRGB(state.HealthColors.HealFX); FX.startColour = HealColor; FXArray.push(FX); } //IF HURT------------ else if(curValue &lt; prevValue) { aFX = findObjs({_type: "custfx",name: '-DefaultHurt'}, {caseInsensitive: true})[0]; if(aFX) FX = aFX.get("definition"); //CHECK DEFAULT COLOR-- if(UseBlood === "DEFAULT" || UseBlood === undefined) { HurtColor = HEXtoRGB(state.HealthColors.HurtFX); FX.startColour = HurtColor; FXArray.push(FX); } //ELSE CHECK CUSTOM COLOR/FX-- else if(UseBlood !== "DEFAULT" &amp;&amp; UseBlood !== undefined) { HurtColor = HEXtoRGB(UseBlood); //IF CUSTOM COLOR-- if(_.difference(HurtColor, [0, 0, 0, 0]).length !== 0) { FX.startColour = HurtColor; FXArray.push(FX); } //ELSE ASSUME CUSTOM FX-- else { var i = UseBlood.split(/,/); _.each(i, function (FXname) { aFX = findObjs({_type: "custfx",name: FXname}, {caseInsensitive: true})[0]; if(aFX) FXArray.push(aFX.get("definition")); else GMW("No FX with name " + FXname); }); } } } else return; //SPAWN FX------------ _.each(FXArray, function (FX) { SpawnFX(Scale, HitSize, obj.get("left"), obj.get("top"), FX, obj.get("_pageid")); }); } } } }, /*------------------------ CHAT MESSAGES ------------------------*/ handleInput = function (msg) { var msgFormula = msg.content.split(/\s+/); var command = msgFormula[0].toUpperCase(), UPPER =""; if(msg.type == "api" &amp;&amp; command.indexOf("!AURA") !== -1) { var OPTION = msgFormula[1] || "MENU"; if(!playerIsGM(msg.playerid)) { sendChat('HealthColors', "/w " + msg.who + " you must be a GM to use this command!"); return; } else { if(OPTION !== "MENU") GMW("UPDATING TOKENS..."); switch(OPTION.toUpperCase()) { case "MENU": break; case "ON": state.HealthColors.auraColorOn = !state.HealthColors.auraColorOn; break; case "BAR": state.HealthColors.auraBar = "bar" + msgFormula[2]; break; case "TINT": state.HealthColors.auraTint = !state.HealthColors.auraTint; break; case "PERC": state.HealthColors.auraPercPC = parseInt(msgFormula[2], 10); state.HealthColors.auraPerc = parseInt(msgFormula[3], 10); break; case "PC": state.HealthColors.PCAura = !state.HealthColors.PCAura; break; case "NPC": state.HealthColors.NPCAura = !state.HealthColors.NPCAura; break; case "GMNPC": state.HealthColors.GM_NPCNames = msgFormula[2]; break; case "GMPC": state.HealthColors.GM_PCNames = msgFormula[2]; break; case "PCNPC": state.HealthColors.NPCNames = msgFormula[2]; break; case "PCPC": state.HealthColors.PCNames = msgFormula[2]; break; case "DEAD": state.HealthColors.auraDead = !state.HealthColors.auraDead; break; case "DEADPC": state.HealthColors.auraDeadPC = !state.HealthColors.auraDeadPC; break; case "DEADFX": state.HealthColors.auraDeadFX = msgFormula[2]; break; case "SIZE": state.HealthColors.AuraSize = parseFloat(msgFormula[2]); break; case "ONEOFF": state.HealthColors.OneOff = !state.HealthColors.OneOff; break; case "FX": state.HealthColors.FX = !state.HealthColors.FX; break; case "HEAL": UPPER = msgFormula[2]; UPPER = UPPER.toUpperCase(); state.HealthColors.HealFX = UPPER; break; case "HURT": UPPER = msgFormula[2]; UPPER = UPPER.toUpperCase(); state.HealthColors.HurtFX = UPPER; break; case "RESET": delete state.HealthColors; GMW("STATE RESET"); checkInstall(); break; case "UPDATE": manUpdate(msg); return; } aurahelp(OPTION); } } }, /*------------------------ "FUNCTIONS" ------------------------*/ //SET TOKEN COLORS------------ TokenSet = function (obj, sizeSet, markerColor, pColor, update) { var Pageon = getObj("page", obj.get("_pageid")); var scale = Pageon.get("scale_number") / 10; if(state.HealthColors.auraTint === true) { if(obj.get('aura1_color') == markerColor &amp;&amp; update === "YES") { obj.set({'aura1_color': "transparent",}); } obj.set({'tint_color': markerColor,}); } else { if(obj.get('tint_color') == markerColor &amp;&amp; update === "YES") { obj.set({'tint_color': "transparent",}); } obj.set({ 'aura1_radius': sizeSet * scale * 1.8, 'aura1_color': markerColor, 'showplayers_aura1': true, }); } }, //REMOVE ALL------------ SetAuraNone = function (obj) { if(state.HealthColors.auraTint === true) obj.set({'tint_color': "transparent",}); else obj.set({'aura1_color': "transparent"}); }, //FORCE ALL TOKEN UPDATE------------ MenuForceUpdate = function(){ let i = 0; const start = new Date().getTime(); const barUsed = state.HealthColors.auraBar; const workQueue = findObjs({type: 'graphic',subtype: 'token',layer: 'objects'}) .filter((o)=&gt;o.get(barUsed + "_max") !== "" &amp;&amp; o.get(barUsed + "_value") !== ""); const drainQueue = ()=&gt;{ let t = workQueue.shift(); if(t){ const prev = JSON.parse(JSON.stringify(t)); handleToken( t, prev, 'YES'); setTimeout(drainQueue,0); } else { sendChat('Fixing Tokens',`/w gm Finished Fixing Tokens`); } }; sendChat('Fixing Tokens',`/w gm Fixing ${workQueue.length} Tokens`); drainQueue(); var end = new Date().getTime(); return "Tokens Processed: " + workQueue.length + "&lt;br&gt;Run time in ms: " + (end - start); }, SetShowNames = function(GM,PC,obj) { if(GM != 'Off' &amp;&amp; GM != '') { GM = (GM == "Yes") ? true : false; obj.set({'showname': GM}); } if(PC != 'Off' &amp;&amp; PC != '') { PC = (PC == "Yes") ? true : false; obj.set({'showplayers_name': PC}); } }, //MANUAL UPDATE------------ manUpdate = function(msg){ var selected = msg.selected; var allNames = ''; _.each(selected, function(obj) { var token = getObj('graphic', obj._id); var tName = token.get("name"); allNames = allNames.concat(tName+'&lt;br&gt;'); var prev = JSON.parse(JSON.stringify(token)); handleToken(token, prev, "YES"); }); GMW(allNames); }, //ATTRIBUTE CACHE------------ makeSmartAttrCache = function (attribute, options) { let cache = {}, defaultValue = options.default || 'YES', validator = options.validation || _.constant(true); on('change:attribute', function (attr) { if(attr.get('name') === attribute) { if(!validator(attr.get('current'))) { attr.set('current', defaultValue); } cache[attr.get('characterid')] = attr.get('current'); var tokens = findObjs({type: 'graphic'}).filter((o) =&gt; o.get('represents') === attr.get("characterid")); _.each(tokens, function (obj) { var prev = JSON.parse(JSON.stringify(obj)); handleToken(obj, prev, "YES"); }); } }); on('destroy:attribute', function (attr) { if(attr.get('name') === attribute) { delete cache[attr.get('characterid')]; } }); return function(character){ let attr = findObjs({type: 'attribute',name: attribute,characterid: character.id},{caseInsensitive:true})[0] || createObj('attribute',{name: attribute,characterid: character.id, current: defaultValue}); if(!cache[character.id] || cache[character.id] !== attr.get('current')){ if(!validator(attr.get('current'))){ attr.set('current',defaultValue); } cache[character.id]=attr.get('current'); } return cache[character.id]; }; }, lookupUseBlood = makeSmartAttrCache('USEBLOOD',{ default: 'DEFAULT' }), lookupUseColor = makeSmartAttrCache('USECOLOR',{ default: 'YES', validation: (o)=&gt;o.match(/YES|NO/) }), //DEATH SOUND------------ PlayDeath = function (trackname) { var RandTrackName; if(trackname.indexOf(",") &gt; 0) { var tracklist = trackname.split(","); RandTrackName = tracklist[Math.floor(Math.random() * tracklist.length)]; } else RandTrackName = trackname; var track = findObjs({type: 'jukeboxtrack',title: RandTrackName})[0]; if(track) { track.set('playing', false); track.set('softstop', false); track.set('volume', 50); track.set('playing', true); } else { log(ScriptName + ": No track found named " + RandTrackName); } }, //PERC TO RGB------------ PercentToHEX = function (percent) { var HEX; if(percent &gt; 100) HEX = "#0000FF"; else { if(percent === 100) percent = 99; var r, g, b = 0; if(percent &lt; 50) { g = Math.floor(255 * (percent / 50)); r = 255; } else { g = 255; r = Math.floor(255 * ((50 - percent % 50) / 50)); } HEX = "#" + ((1 &lt;&lt; 24) + (r &lt;&lt; 16) + (g &lt;&lt; 8) + b).toString(16).slice(1); } return HEX; }, //HEX TO RGB------------ HEXtoRGB = function (hex) { let parts = (hex || '').match(/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/); if(parts) { let rgb = _.chain(parts).rest().map((d) =&gt; parseInt(d, 16)).value(); rgb.push(1.0); return rgb; } return [0, 0, 0, 0.0]; }, //SPAWN FX------------ SpawnFX = function (Scale,HitSize,left,top,FX,pageid) { _.defaults(FX, { "maxParticles": 100, "duration": 100, "size": 100, "sizeRandom": 100, "lifeSpan": 100, "lifeSpanRandom": 100, "speed": 0, "speedRandom": 0, "angle": 0, "angleRandom": 0, "emissionRate": 100, "startColour": [255,255,255,1], "endColour": [0,0,0,1], "gravity": {"x": 0,"y": 0.0}, }); var newFX = { "maxParticles": FX.maxParticles * HitSize, "duration": FX.duration * HitSize, "size": FX.size * Scale / 2, "sizeRandom": FX.sizeRandom * Scale / 2, "lifeSpan": FX.lifeSpan, "lifeSpanRandom": FX.lifeSpanRandom, "speed": FX.speed * Scale, "speedRandom": FX.speedRandom * Scale, "angle": FX.angle, "angleRandom": FX.angleRandom, "emissionRate": FX.emissionRate * HitSize * 2, "startColour": FX.startColour, "endColour": FX.endColour, "gravity": {"x": FX.gravity.x * Scale,"y": FX.gravity.y * Scale}, }; spawnFxWithDefinition(left,top,newFX,pageid); }, //HELP MENU------------ aurahelp = function (OPTION) { var Update = ''; if(OPTION !== "MENU") Update = MenuForceUpdate(); var img = "background-image: -webkit-linear-gradient(left, #76ADD6 0%, #a7c7dc 100%);"; var tshadow = "-1px -1px #222, 1px -1px #222, -1px 1px #222, 1px 1px #222 , 2px 2px #222;"; var style = 'style="padding-top: 1px; text-align:center; font-size: 9pt; width: 48px; height: 14px; border: 1px solid black; margin: 1px; background-color: #6FAEC7;border-radius: 4px; box-shadow: 1px 1px 1px #707070;'; var off = "#A84D4D"; var disable = "#D6D6D6"; var HR = "&lt;hr style='background-color: #000000; margin: 5px; border-width:0;color: #000000;height: 1px;'/&gt;"; var FX = state.HealthColors.auraDeadFX.substring(0, 4); sendChat('HealthColors', "/w GM &lt;b&gt;&lt;br&gt;" + '&lt;div style="border-radius: 8px 8px 8px 8px; padding: 5px; font-size: 9pt; text-shadow: ' + tshadow + '; box-shadow: 3px 3px 1px #707070; ' + img + ' color:#FFF; border:2px solid black; text-align:right; vertical-align:middle;"&gt;' + '&lt;u&gt;&lt;big&gt;HealthColors Version: ' + version + '&lt;/u&gt;&lt;/big&gt;&lt;br&gt;' + //-- HR + //-- 'Is On: &lt;a ' + style + 'background-color:' + (state.HealthColors.auraColorOn !== true ? off : "") + ';" href="!aura on"&gt;' + (state.HealthColors.auraColorOn !== true ? "No" : "Yes") + '&lt;/a&gt;&lt;br&gt;' + //-- 'Bar: &lt;a ' + style + '" href="!aura bar ?{Bar|1|2|3}"&gt;' + state.HealthColors.auraBar + '&lt;/a&gt;&lt;br&gt;' + //-- 'Use Tint: &lt;a ' + style + 'background-color:' + (state.HealthColors.auraTint !== true ? off : "") + ';" href="!aura tint"&gt;' + (state.HealthColors.auraTint !== true ? "No" : "Yes") + '&lt;/a&gt;&lt;br&gt;' + //-- 'Percentage(PC/NPC): &lt;a ' + style + '" href="!aura perc ?{PCPercent?|100} ?{NPCPercent?|100}"&gt;' + state.HealthColors.auraPercPC + '/'+ state.HealthColors.auraPerc +'&lt;/a&gt;&lt;br&gt;' + //-- HR + //-- 'Show PC Health: &lt;a ' + style + 'background-color:' + (state.HealthColors.PCAura !== true ? off : "") + ';" href="!aura pc"&gt;' + (state.HealthColors.PCAura !== true ? "No" : "Yes") + '&lt;/a&gt;&lt;br&gt;' + //-- 'Show NPC Health: &lt;a ' + style + 'background-color:' + (state.HealthColors.NPCAura !== true ? off : "") + ';" href="!aura npc"&gt;' + (state.HealthColors.NPCAura !== true ? "No" : "Yes") + '&lt;/a&gt;&lt;br&gt;' + //-- 'Show Dead PC: &lt;a ' + style + 'background-color:' + (state.HealthColors.auraDeadPC !== true ? off : "") + ';" href="!aura deadPC"&gt;' + (state.HealthColors.auraDeadPC !== true ? "No" : "Yes") + '&lt;/a&gt;&lt;br&gt;' + //-- 'Show Dead NPC: &lt;a ' + style + 'background-color:' + (state.HealthColors.auraDead !== true ? off : "") + ';" href="!aura dead"&gt;' + (state.HealthColors.auraDead !== true ? "No" : "Yes") + '&lt;/a&gt;&lt;br&gt;' + //-- HR + //-- 'GM Sees all PC Names: &lt;a ' + style + 'background-color:' + ButtonColor(state.HealthColors.GM_PCNames, off, disable) + ';" href="!aura gmpc ?{Setting|Yes|No|Off}"&gt;' + state.HealthColors.GM_PCNames + '&lt;/a&gt;&lt;br&gt;' + //-- 'GM Sees all NPC Names: &lt;a ' + style + 'background-color:' + ButtonColor(state.HealthColors.GM_NPCNames, off, disable) + ';" href="!aura gmnpc ?{Setting|Yes|No|Off}"&gt;' + state.HealthColors.GM_NPCNames + '&lt;/a&gt;&lt;br&gt;' + //--- HR + //-- 'PC Sees all PC Names: &lt;a ' + style + 'background-color:' + ButtonColor(state.HealthColors.PCNames, off, disable) + ';" href="!aura pcpc ?{Setting|Yes|No|Off}"&gt;' + state.HealthColors.PCNames + '&lt;/a&gt;&lt;br&gt;' + //-- 'PC Sees all NPC Names: &lt;a ' + style + 'background-color:' + ButtonColor(state.HealthColors.NPCNames, off, disable) + ';" href="!aura pcnpc ?{Setting|Yes|No|Off}"&gt;' + state.HealthColors.NPCNames + '&lt;/a&gt;&lt;br&gt;' + //-- HR + //-- 'Aura Size: &lt;a ' + style + '" href="!aura size ?{Size?|0.7}"&gt;' + state.HealthColors.AuraSize + '&lt;/a&gt;&lt;br&gt;' + //-- 'One Offs: &lt;a ' + style + 'background-color:' + (state.HealthColors.OneOff !== true ? off : "") + ';" href="!aura ONEOFF"&gt;' + (state.HealthColors.OneOff !== true ? "No" : "Yes") + '&lt;/a&gt;&lt;br&gt;' + //-- 'FX: &lt;a ' + style + 'background-color:' + (state.HealthColors.FX !== true ? off : "") + ';" href="!aura FX"&gt;' + (state.HealthColors.FX !== true ? "No" : "Yes") + '&lt;/a&gt;&lt;br&gt;' + //-- 'HealFX Color: &lt;a ' + style + 'background-color:#' + state.HealthColors.HealFX + ';""href="!aura HEAL ?{Color?|00FF00}"&gt;' + state.HealthColors.HealFX + '&lt;/a&gt;&lt;br&gt;' + //-- 'HurtFX Color: &lt;a ' + style + 'background-color:#' + state.HealthColors.HurtFX + ';""href="!aura HURT ?{Color?|FF0000}"&gt;' + state.HealthColors.HurtFX + '&lt;/a&gt;&lt;br&gt;' + //-- 'DeathSFX: &lt;a ' + style + '" href="!aura deadfx ?{Sound Name?|' + state.HealthColors.auraDeadFX + '}"&gt;' + FX + '&lt;/a&gt;&lt;br&gt;' + //-- HR + //-- Update +//-- '&lt;/div&gt;'); }, //OFF BUTTON COLORS------------ ButtonColor = function (state, off, disable) { var color; if(state == "No") color = off; if(state == "Off") color = disable; return color; }, //CHECK INSTALL &amp; SET STATE------------ checkInstall = function () { log('-=&gt;' + ScriptName + ' v' + version + ' [Updated: ' + Updated + ']&lt;=-'); if(!_.has(state, 'HealthColors') || state.HealthColors.schemaVersion !== schemaVersion) { log('&lt;' + ScriptName + ' Updating Schema to v' + schemaVersion + '&gt;'); state.HealthColors = {schemaVersion: schemaVersion}; state.HealthColors.version = version; } //CHECK STATE VALUES if(_.isUndefined(state.HealthColors.auraColorOn)) state.HealthColors.auraColorOn = true; //global on or off if(_.isUndefined(state.HealthColors.auraBar)) state.HealthColors.auraBar = "bar1"; //bar to use if(_.isUndefined(state.HealthColors.auraTint)) state.HealthColors.auraTint = false; //use tint instead? if(_.isUndefined(state.HealthColors.auraPercPC)) state.HealthColors.auraPercPC = 100; //precent to start showing PC if(_.isUndefined(state.HealthColors.auraPerc)) state.HealthColors.auraPerc = 100; //precent to start showing NPC //----------------- if(_.isUndefined(state.HealthColors.PCAura)) state.HealthColors.PCAura = true; //show players Health? if(_.isUndefined(state.HealthColors.NPCAura)) state.HealthColors.NPCAura = true; //show NPC Health? if(_.isUndefined(state.HealthColors.auraDeadPC)) state.HealthColors.auraDeadPC = true; //show dead X status PC if(_.isUndefined(state.HealthColors.auraDead)) state.HealthColors.auraDead = true; //show dead X status NPC //----------------- if(_.isUndefined(state.HealthColors.GM_PCNames)) state.HealthColors.GM_PCNames = "Yes"; //show GM PC names? if(_.isUndefined(state.HealthColors.PCNames)) state.HealthColors.PCNames = "Yes"; //show players PC Names? //----------------- if(_.isUndefined(state.HealthColors.GM_NPCNames)) state.HealthColors.GM_NPCNames = "Yes"; //show GM NPC names? if(_.isUndefined(state.HealthColors.NPCNames)) state.HealthColors.NPCNames = "Yes"; //show players NPC Names? //----------------- if(_.isUndefined(state.HealthColors.AuraSize)) state.HealthColors.AuraSize = 0.7; //set aura size? if(_.isUndefined(state.HealthColors.FX)) state.HealthColors.FX = true; //set FX ON/OFF? if(_.isUndefined(state.HealthColors.HealFX)) state.HealthColors.HealFX = "00FF00"; //set FX HEAL COLOR if(_.isUndefined(state.HealthColors.HurtFX)) state.HealthColors.HurtFX = "FF0000"; //set FX HURT COLOR? if(_.isUndefined(state.HealthColors.auraDeadFX)) state.HealthColors.auraDeadFX = 'None'; //Sound FX Name //TokenMod CHECK if('undefined' !== typeof TokenMod &amp;&amp; TokenMod.ObserveTokenChange) TokenMod.ObserveTokenChange(handleToken); var FXHurt = findObjs({_type: "custfx",name: "-DefaultHurt"}, {caseInsensitive: true})[0]; var FXHeal = findObjs({_type: "custfx",name: "-DefaultHeal"}, {caseInsensitive: true})[0]; //DEFAULT FX CHECK if(!FXHurt) { GMW("Creating Default Hurt FX"); var Hurt = { "maxParticles": 150, "duration": 50, "size": 10, "sizeRandom": 3, "lifeSpan": 25, "lifeSpanRandom": 5, "speed": 8, "speedRandom": 3, "gravity": {"x": 0.01,"y": 0.65}, "angle": 270, "angleRandom": 25, "emissionRate": 100, "startColour": [0, 0, 0, 0], "endColour": [0, 0, 0, 0], }; createObj('custfx', {name: "-DefaultHurt",definition: Hurt}); } if(!FXHeal) { GMW("Creating Default Heal FX"); var Heal = { "maxParticles": 150, "duration": 50, "size": 10, "sizeRandom": 15, "lifeSpan": 50, "lifeSpanRandom": 30, "speed": 0.5, "speedRandom": 2, "angle": 0, "angleRandom": 180, "emissionRate": 1000, "startColour": [0, 0, 0, 0], "endColour": [0, 0, 0, 0], }; createObj('custfx', {name: "-DefaultHeal",definition: Heal}); } }, //WHISPER GM------------ GMW = function (text) { var DIV = "&lt;div style='width: 100%; border-radius: 4px; box-shadow: 1px 1px 1px #707070; text-align: center; vertical-align: middle; padding: 3px 0px; margin: 0px auto; border: 1px solid #000; color: #000; background-image: -webkit-linear-gradient(-45deg, #a7c7dc 0%,#85b2d3 100%);"; var MSG = DIV + "'&gt;&lt;b&gt;"+text+"&lt;/b&gt;&lt;/div"; sendChat('HealthColors', "/w GM "+MSG); }, //OUTSIDE CALL------------ UpdateToken = function (obj, prev) { if (obj.get("type") === "graphic") handleToken(obj, prev); else GMW("Script sent non-Token to be updated!"); }, //REGISTER TRIGGERS------------ registerEventHandlers = function () { on('chat:message', handleInput); on("change:token", handleToken); on('add:token', function (t) { _.delay(() =&gt; { let token = getObj('graphic', t.id), prev = JSON.parse(JSON.stringify(token)); handleToken(token, prev, "YES"); }, 400); }); }; //RETURN OUTSIDE FUNCTIONS------------ return { GMW: GMW, Update: UpdateToken, CheckInstall: checkInstall, RegisterEventHandlers: registerEventHandlers }; }()); //On Ready on('ready', function () { 'use strict'; HealthColors.GMW("API READY"); HealthColors.CheckInstall(); HealthColors.RegisterEventHandlers(); });