Created
March 28, 2019 14:39
-
-
Save keithcurtis1/890f4ace4f1d240a82f2113131da9e36 to your computer and use it in GitHub Desktop.
Constrains HP to 0-Max, and applies dead status to Shaped Roll20 token
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* global TokenMod, ChatSetAttr */ | |
on('ready', () => { | |
// Configuration parameters | |
const HPBarNum = 1; | |
const TempHPMarker = 'yellow'; | |
const DeadMarker = 'dead'; | |
const TempHPAttributeName = 'temp_hp'; | |
///////////////////////////////////////////// | |
const bar = `bar${HPBarNum}_value`; | |
const lnk = `bar${HPBarNum}_link`; | |
const max = `bar${HPBarNum}_max`; | |
const mrk = `status_${TempHPMarker}`; | |
const ded = `status_${DeadMarker}`; | |
const checkTempHP = (obj) => { | |
let v = parseFloat(obj.get('current')); | |
findObjs({ | |
type: 'graphic', | |
represents: obj.get('characterid') | |
}) | |
.filter( (t) => t.get(lnk) !== '') | |
.forEach((g)=>{ | |
g.set(mrk,(v>0 ? (v>9 ? true : v) : false) ); | |
}); | |
}; | |
const assureTempHPMarkers = () => { | |
let queue = findObjs({ | |
type: 'attribute', | |
name: TempHPAttributeName | |
}); | |
const burndownQueue = ()=>{ | |
if(queue.length){ | |
let attr = queue.shift(); | |
checkTempHP(attr); | |
setTimeout(burndownQueue,0); | |
} | |
}; | |
burndownQueue(); | |
}; | |
const temporalTempHPCache = {}; | |
const accountForHPBarChange = (obj,prev) => { | |
// 1. did hp change and is it a scale | |
const hpMax = parseInt(obj.get(max),10); | |
let hp = parseInt(obj.get(bar),10); | |
const diff = hp-parseFloat(prev[bar]); | |
if( !isNaN(hpMax) && diff !== 0 ) { | |
let changes = {}; | |
// 2. does it represent a character | |
// 3. does the hp bar represent an attribute | |
const character = getObj('character',obj.get('represents')); | |
if( diff < 0 && character && obj.get(lnk)!=='' ){ | |
// 4. is there temp hp | |
const temp_hp = findObjs({ | |
type: 'attribute', | |
characterid: character.id, | |
name: TempHPAttributeName | |
})[0]; | |
if( temp_hp ) { | |
const now = Date.now(); | |
// 5. have we accounted for it. | |
if( !temporalTempHPCache.hasOwnProperty(character.id) || (now-temporalTempHPCache[character.id].when)>300 ) { | |
// calculate necessary change | |
const tempHP = parseFloat(temp_hp.get('current'))||0; | |
const newTmpHP = Math.max((tempHP+diff),0); | |
const toHeal = tempHP - newTmpHP; | |
temporalTempHPCache[character.id]={ | |
when: now, | |
toHeal: toHeal | |
}; | |
temp_hp.set('current', newTmpHP); | |
checkTempHP(temp_hp); | |
} | |
hp += temporalTempHPCache[character.id].toHeal; | |
changes[bar] = hp; | |
} | |
} | |
if(hp > hpMax) { | |
hp = hpMax; | |
changes[bar] = hp; | |
changes[ded] = false; | |
} else if(hp <= 0) { | |
hp=0; | |
changes[bar] = hp; | |
changes[ded] = true; | |
} else { | |
changes[ded] = false; | |
} | |
obj.set(changes); | |
} | |
}; | |
const onAttributeChange = (obj) => { | |
if(obj.get('name') === TempHPAttributeName){ | |
checkTempHP(obj); | |
} | |
}; | |
on("change:attribute", onAttributeChange); | |
on("change:token", accountForHPBarChange); | |
if('undefined' !== typeof TokenMod && TokenMod.ObserveTokenChange){ | |
TokenMod.ObserveTokenChange(accountForHPBarChange); | |
} | |
if('undefined' !== typeof ChatSetAttr && ChatSetAttr.registerObserver){ | |
ChatSetAttr.registerObserver('change',onAttributeChange); | |
} | |
if('undefined' !== typeof ApplyDamage && ApplyDamage.registerObserver){ | |
ApplyDamage.registerObserver('change',accountForHPBarChange); | |
} | |
assureTempHPMarkers(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment