Hey all. Awhile back, a user here made a small script for me that swaps out tokens for "chalk outline" images when they reach 0 HP, and if they're NPCs, removes them from initiative (healing the chalk outline re-swaps and puts the token back into initiative). I love the script, but want to make one modification: I don't want it to affect player tokens at all. The problem is that I have zero script expertise, and the user who made the script for me hasn't responded to my queries. So I was wondering if anyone else could show me how to mod this script so that it only targets NPCs and my players don't have their tokens turned into chalk outlines whenever they drop to 0. Here's the code: /* InitiativeCleaner script: Author: Scott C. Contact: <a href="https://app.roll20.net/users/459831/scott-c" rel="nofollow">https://app.roll20.net/users/459831/scott-c</a> */ var cleaner = cleaner || (function() { 'use strict'; var version = '0.02', lastUpdate = 1555799069, schemaVersion = 0.02, hpBar = 3, ch = function (c) { var entities = { '<' : 'lt', '>' : 'gt', "'" : '#39', '@' : '#64', '{' : '#123', '|' : '#124', '}' : '#125', '[' : '#91', ']' : '#93', '"' : 'quot', '-' : 'mdash', ' ' : 'nbsp' }; if(_.has(entities,c) ){ return ('&'+entities[c]+';'); } return ''; }, esRE = function (s) { var escapeForRegexp = /(\\|\/|\[|\]|\(|\)|\{|\}|\?|\+|\*|\||\.|\^|\$)/g; return s.replace(escapeForRegexp,"\\$1"); }, HE = (function(){ var entities={ //' ' : '&'+'nbsp'+';', '&' : '&'+'amp'+';', '<' : '&'+'lt'+';', '>' : '&'+'gt'+';', "'" : '&'+'#39'+';', '@' : '&'+'#64'+';', //'{' : '&'+'#123'+';', '|' : '&'+'#124'+';', '}' : '&'+'#125'+';', ',' : '&'+'#44'+';', '[' : '&'+'#91'+';', ']' : '&'+'#93'+';', '"' : '&'+'quot'+';', ':' : '&'+'#58'+';', //'-' : '&'+'mdash'+';' }, re=new RegExp('('+_.map(_.keys(entities),esRE).join('|')+')','g'); return function(s){ return s.replace(re, function(c){ return entities[c] || c; }); }; }()), checkInstall = function() { log('-=> cleaner v'+version+' <=- ['+(new Date(lastUpdate*1000))+']'); if( ! _.has(state,'cleaner') || state.cleaner.version !== schemaVersion) { state.cleaner=state.cleaner || {}; log(' > Updating Schema to v'+schemaVersion+' <'); state.cleaner.version = schemaVersion; } }, cleanImgSrc = function(img){ var parts = img.match(/(.*\/images\/.*)(thumb|med|original|max)(.*)$/); if(parts) { return parts[1]+'thumb'+parts[3]; } return; }, cleanField = function(token,prev){ log(`Reacting to change of ${token.get('name')}`); let turnTracker =Campaign().get('initiativepage'), turnOrder = Campaign().get('turnorder'), initiative,character,cleanHistory; try{ turnOrder = JSON.parse(turnOrder); }catch (err){ turnOrder = false; } if(token.get('represents')!=='' && token.get(`bar${hpBar}_value`)*1!==prev[`bar${hpBar}_value`]*1 && turnTracker && turnOrder){ character = getObj('character',token.get('represents')); log(`cleaning battlefield`); const tokenID = token.id; token = getObj('graphic',tokenID); try{ cleanHistory = token.get('gmnotes').replace(/.*?({.*}).*/,'$1').replace(/\n/,''); cleanHistory = JSON.parse(cleanHistory); }catch (err){ cleanHistory = false; } if(token.get(`bar${hpBar}_value`)*1<=0){ createCorpse(token,character,turnOrder); }else if(token.get(`bar${hpBar}_value`)*1>0 && cleanHistory){ reviveToken(token,character,turnOrder); } log(`applying changes to battlefield`); } }, createCorpse = function(token,character,turnOrder){ let deadImage = findObjs({ type:'rollabletable', name:'deadTable' },{caseinsensitive:true})[0], creationObj,tokenTurn; const setObj = {}; deadImage = findObjs({ type:'tableitem', _rollabletableid:deadImage.id }); deadImage = _.reduce(deadImage,(memo,item)=>{ _.each(_.range(item.get('weight')*1),(n)=>{ memo.push(cleanImgSrc(item.get('avatar'))); }); return memo; },[]); deadImage = deadImage[randomInteger(deadImage.length) - 1]; log(`${token.get('name')} is dead, their corpse looks like ${deadImage}`); creationObj = _.reduce([ 'represents','name','left','top','width','height','_pageid','layer','barN_value','barN_link','barN_max','auraN_radius','auraN_color','auraN_square', 'tintcolor','statusmarkers','showname','showplayers_name','showplayers_barN','showplayers_auraN','playersedit_name','playersedit_barN', 'playersedit_auraN','light_radius','light_dimradius','light_otherplayers','light_hassight','light_angle','light_losangle', 'lastmove','light_multiplier','adv_fow_view_distance' ],(memo,attr)=>{ if(/N/.test(attr)){ attr.replace(/(.*)N(.*)/,(match,pre,post)=>{ _.each(/aura/.test(pre) ? [1,2] : [1,2,3],(n)=>{ memo[`${pre}${n}${post}`]=token.get(`${pre}${n}${post}`); }); }); }else{ memo[attr]=token.get(attr); } return memo; },{}); creationObj.rotation = randomInteger(361) - 1; creationObj.imgsrc = deadImage; let newToken = createObj('graphic',creationObj); turnOrder = _.reject(turnOrder,(turn)=>{ if(turn.id === token.id){ tokenTurn = _.clone(turn); if(character.get('controlledby')===''){ return true; }else{ turn.id = newToken.id; } } return false; }); newToken.set({gmnotes: `{"originalToken":"${token.id}","deathInitiative":${JSON.stringify(tokenTurn)}}\n${token.get('gmnotes')}`.replace(/undefined/,'"$&"')}); setObj.layer = 'walls'; token.set(setObj); if(turnOrder){ Campaign().set('turnorder',JSON.stringify(turnOrder)); } }, reviveToken = function(token,character,turnOrder){ let initiative; log(`${token.get('name')} is being revived`); token.get('gmnotes').replace(/{"originalToken":"(.+?)","deathInitiative":("undefined"|.*?})}\n?(.*)/,(match,tokenID,init,originalText)=>{ let origToken = getObj('graphic',tokenID); log(`origToken: ${JSON.stringify(origToken)}`); const setObj = _.reduce([ 'left','top','width','height','layer','barN_value','barN_link','barN_max','auraN_radius','auraN_color','auraN_square', 'tintcolor','statusmarkers','showname','showplayers_name','showplayers_barN','showplayers_auraN','playersedit_name','playersedit_barN', 'playersedit_auraN','light_radius','light_dimradius','light_otherplayers','light_hassight','light_angle','light_losangle', 'lastmove','light_multiplier','adv_fow_view_distance' ],(memo,attr)=>{ if(/N/.test(attr)){ attr.replace(/(.*)N(.*)/,(match,pre,post)=>{ _.each(/aura/.test(pre) ? [1,2] : [1,2,3],(n)=>{ memo[`${pre}${n}${post}`]=token.get(`${pre}${n}${post}`); }); }); }else{ memo[attr]=token.get(attr); } return memo; },{layer:token.get('layer')}); origToken.set(setObj); try{ initiative = JSON.parse(init); }catch (err){ initiative = false; } return originalText; }); log(`initial turnOrder: ${JSON.stringify(turnOrder)}`); if(initiative){ turnOrder = sortInitiative(turnOrder,initiative,token.id); } log(`final turnOrder: ${JSON.stringify(turnOrder)}`); if(turnOrder){ Campaign().set('turnorder',JSON.stringify(turnOrder)); } token.remove(); }, sortInitiative = function(order,init,deadID){ const newOrder = []; let initAdded = false; _.some(order,(turn)=>{ if(turn.id === deadID){ turn.id = init.id; initAdded = true; } return initAdded; }); if(initAdded){ return order; }else{ _.each(order,(turn)=>{ if(turn.pr*1<init.pr*1 && !_.isEmpty(newOrder)&&!initAdded){ newOrder.push(init); newOrder.push(turn); initAdded = true; }else if(turn.pr*1===init.pr*1){ newOrder.push(turn); newOrder.push(init); initAdded = true; }else{ newOrder.push(turn); } }); } if(!initAdded){ newOrder.push(init); } return newOrder; }, RegisterEventHandlers = function() { on('change:graphic', cleanField); }; return { CheckInstall: checkInstall, RegisterEventHandlers: RegisterEventHandlers }; }()); on("ready",function(){ 'use strict'; cleaner.CheckInstall(); cleaner.RegisterEventHandlers(); });