Ok, I've got something for you to try. CAVEAT: this will overwrite your existing attributes! You may wish to try it out on a copy of your game. If you create any of the three attributes [ total_mana, current_mana, mana ], the script will create the others and fill all 3 with pertinent information the next time a spell is cast or a long rest is taken. It will also keep them up to date with the right values at any of those events and on restart of the API. Here's the code: on('ready',function(){
"use strict";
var
getManaTotalByCharacterID = function(charid){
return 0 +
(getAttrByName(charid,'lvl1_slots_total')*1)+
(getAttrByName(charid,'lvl2_slots_total')*2)+
(getAttrByName(charid,'lvl3_slots_total')*3)+
(getAttrByName(charid,'lvl4_slots_total')*4)+
(getAttrByName(charid,'lvl5_slots_total')*5)+
(getAttrByName(charid,'lvl6_slots_total')*6)+
(getAttrByName(charid,'lvl7_slots_total')*7)+
(getAttrByName(charid,'lvl8_slots_total')*8)+
(getAttrByName(charid,'lvl9_slots_total')*9);
},
getManaUsedByCharacterID = function(charid){
return 0 +
(getAttrByName(charid,'lvl1_slots_expended')*1)+
(getAttrByName(charid,'lvl2_slots_expended')*2)+
(getAttrByName(charid,'lvl3_slots_expended')*3)+
(getAttrByName(charid,'lvl4_slots_expended')*4)+
(getAttrByName(charid,'lvl5_slots_expended')*5)+
(getAttrByName(charid,'lvl6_slots_expended')*6)+
(getAttrByName(charid,'lvl7_slots_expended')*7)+
(getAttrByName(charid,'lvl8_slots_expended')*8)+
(getAttrByName(charid,'lvl9_slots_expended')*9);
},
assureAttrs = function (charid, attrs){
let usedMana=getManaUsedByCharacterID(charid),
totalMana=getManaTotalByCharacterID(charid);
(attrs.total_mana||createObj('attribute',{
characterid: charid,
name: 'total_mana'
})).set('current',totalMana);
(attrs.current_mana||createObj('attribute',{
characterid: charid,
name: 'current_mana'
})).set('current',totalMana-usedMana);
(attrs.mana||createObj('attribute',{
characterid: charid,
name: 'mana'
})).set({
current: totalMana-usedMana,
max:totalMana
});
},
verifyAttributes = function(){
_.chain(filterObjs((o)=> 'attribute'===o.get('type') && _.contains(['mana','total_mana','current_mana'],o.get('name'))))
.reduce((m,o)=>{
let cid=o.get('characterid');
m[cid] = (m[cid]||{});
m[cid][o.get('name')]=o;
return m;
},{})
.each((v,k)=>{
assureAttrs(k,v);
})
;
},
detectCasting = function(msg){
if('api'===msg.type && !msg.rolltemplate){
if(msg.content.match(/^!(longrest|spelltracking)/)){
_.defer(verifyAttributes);
}
} else if(msg.playerid.toLowerCase() !== 'api' && msg.rolltemplate && msg.content.match(/{{\s*spelllevel\s*=\s*\d+\s*}}/) ) {
_.defer(verifyAttributes);
}
},
handleAttrChanges = function(obj,prev){
if(_.contains([
'lvl1_slots_total', 'lvl2_slots_total', 'lvl3_slots_total',
'lvl4_slots_total', 'lvl5_slots_total', 'lvl6_slots_total',
'lvl7_slots_total', 'lvl8_slots_total', 'lvl9_slots_total',
'lvl1_slots_expended', 'lvl2_slots_expended', 'lvl3_slots_expended',
'lvl4_slots_expended', 'lvl5_slots_expended', 'lvl6_slots_expended',
'lvl7_slots_expended', 'lvl8_slots_expended', 'lvl9_slots_expended',
'total_mana', 'current_mana', 'mana' ], prev.name)){
let charid = obj.get('characterid'),
a=_.reduce(filterObjs((o) => {
return o.get('characterid')=== charid &&
'attribute'===o.get('type') &&
_.contains(['mana','total_mana','current_mana'], o.get('name'));
}),(m,o)=> {
m[o.get('name')]=o;
return m;
}, {});
if(_.keys(a).length){
assureAttrs(charid,a);
}
}
};
verifyAttributes();
on('change:attribute', handleAttrChanges);
on('chat:message', detectCasting);
});