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

State Wiped on Script Restart

I'm having trouble with state data being wiped on script restart. I've disabled all other scripts, and created a new campaign and copied the script with no success. Maybe someone can point out my coding flaw. I may be too close to the script to see the issue... There is only the one script active in the campaign. Not much to it at the moment as I've just started working on it. Everything works as intended, except state data isn't persistent. The entire script currently has only two event handlers: on(chat) and on(ready). The relevant sections of code are shown. Script starts with initializing the state data. state.BuffMgr= state.BuffMgr || []; After a few checks checks in the on(chat) event, the script adds an object to the array. The log() line is the last line before a break statement in a switch() block. No code follows the switch() block. state.BuffMgr[ObjID] = state.BuffMgr[ObjID] || []; state.BuffMgr[ObjID].push({ name: buffname, duration: (duration < 1 || duration == 'perm') ? 'perm' : parseInt(duration), description: buffdesc, }); log(Object.keys(state.BuffMgr)); The log output from the last line shows exactly what I would expect it to show. ["-JclOAGWZGfdksIjjFQe"] If I immediately click the Save Script button, the on(ready) event fires. on('ready', function() { log(Object.keys(state.BuffMgr)); }); The log output should reflect the same log output as before, but shows an empty array. ["-JclOAGWZGfdksIjjFQe"] Restarting sandbox due to script changes... Spinning up new sandbox... [] The only other line anywhere in the script that references state is as the source for an _.each() block. _.each(Object.keys(state.BuffMgr), function() {}); In the most certain event I've overlooked something, here is the complete unfinished script. state.BuffMgr = state.BuffMgr || []; var BM = {}; BM.Command = '!BUFF'; BM.SpeakAs = 'Buff'; on('ready', function() { log(Object.keys(state.BuffMgr)); }); BM.DisplayBuffs = function(id, displayname) { } on('chat:message', function(msg) { var param = msg.content.split(' '); if (msg.type != 'api' || param.shift().toUpperCase() != BM.Command || msg.who.indexOf(' (GM)') == -1) return; var replyTo = '/w ' + msg.who.split(' ')[0] + ' '; var keyword = param.shift().toUpperCase(); switch (keyword) { case 'ADD': var duration = param.shift(); if(!duration || (isNaN(duration) && duration !='perm')) { //any negative duration = perm sendChat(BM.SpeakAs, replyTo + 'Error: Buff duration must be numeric'); return; } var buffname = ''; while (param.length != 0) { buffname += (buffname == '' ? '' : ' ') + param.shift(); } param = buffname.split(','); buffname = param[0].trim(); var buffdesc = param[1] ? param[1].trim() : ''; if (buffname == '') { sendChat(BM.SpeakAs, replyTo + 'Error: Buff name must be provided'); return; } if (!msg.selected) { sendChat(BM.SpeakAs, replyTo + 'Error: Select a token to buff'); return; } _.each(msg.selected, function(obj) { var token = getObj('graphic', obj['_id']); if (!token) return; var ObjID = token.get('represents'); if(ObjID == '') { ObjID = token.get('_id'); } state.BuffMgr[ObjID] = state.BuffMgr[ObjID] || []; state.BuffMgr[ObjID].push({ name: buffname, duration: (duration < 1 || duration == 'perm') ? 'perm' : parseInt(duration), description: buffdesc, }); log(Object.keys(state.BuffMgr)); }); break; case 'PURGE': break; case 'LIST': if (param != 0 && param.shift().toUpperCase() == 'ALL') { _.each(Object.keys(state.BuffMgr), function(id) { var obj = getObj('character', id); if (!obj) { obj = getObj('graphic', id); } if (obj) { var displayname = obj.get('name') == '' ? 'Token' : obj.get('name'); BM.DisplayBuffs(id, displayname); } }); } else { if (msg.selected) { _.each(msg.selected, function(obj) { obj = getObj('graphic', obj['_id']); if (!obj) return; if (obj.get('represents') != '') { obj = getObj('character', obj.get('represents')); } var displayname = obj.get('name') == '' ? 'Token' : obj.get('name'); BM.DisplayBuffs(obj.get('_id'), displayname); }); } else { sendChat(BM.SpeakAs, replyTo + 'Error: Select a token or use ALL'); return; } } break; case 'TIMER': break; default: sendChat(BM.SpeakAs, replyTo + 'Error: ' + keyword + ' is not a valid keyword.'); break; } });
1419974455
Lithl
Pro
Sheet Author
API Scripter
Roll20 objects have string ids. You are trying to use those strings as indices into an array. Arrays can only have integer indices. Here's some code I just ran in my developer console: > var a = [] < undefined > a < [] > a["foo"] = [{name:"bar",duration:"bar",description:"baz"}] < [Object] > a < [] > Object.keys(a) < ["foo"] At a guess, it looks like Object.keys (and myArray[myString]) is coercing the array into an object, but myArray is still an array. Based on your experience, the synchronization process Roll20 is using to save the state is cleaning up strange incongruencies like an array with object keys. Try changing your initialization to state.BuffMgr || {} instead (initializing BuffMgr as an object, instead of initializing it as an array). You may need to run a piece of code once that simply sets BuffMgr to an object, since it's currently an array.
Amazing. Changed as you suggested. Had to reset the state data, but it worked. Will remember that going forward. Good thing coding isn't my day job... Thanks for the quick reply and solution!