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

Characters and State

What is the appropriate way to store the player objects for use in the scripts.  I guess its a two part question.  I defined a namespace necro_char_ns which has a method getChars.  The first problem is the function: necro_char_ns.getChars = function() { var currentChars = findObjs({ _type: "player" }); return currentChars; }; returns an empty array. Secondly in this nascent form. as I'm just beginning to code up my script suite, what is the logical way of storing player objects for later usage? My impulse would be to store them in state, but I'd really like some recommendations because nothing is more frustrating than being 3000 lines of code in and having to rewrite a third of your program because of a poor design choice you made in the first 10 minutes.  
1506513786
The Aaron
Pro
API Scripter
When you say "store player objects for later use", what do you mean? Later in the same execution? Or more like remember settings for a player?  On a technical level, you can't store player objects on the state. It will appear to work, but on restart/restore, it will become a corrupted version. The state can only store basic types. Anything that would work in a JSON object.   You seem to be conflating the concepts of Player objects and Character objects.  Player objects represent the humans you've invited to the game. Character objects represent a made up entity in your story. Players can have control of Characters. 
what I'm looking for is a persistent way to reference the game's players and their controlled characters, so rather than say hard coding a character id, I can can pass in a character object as a function parameter by something along the lines of MyPlayers.Jason.Jason'sCharacter
This would be used throughout the code for things like: <psuedo> on graphic:change if(graphic represents player in MyPlayers) { if Myplayers.player1.char  hp < 50% whisper player1 "you are wounded"   }
1506516934

Edited 1506517148
Something along this line: class MyPlayer { public: methods(..) private: Player player; Character char; };
1506518048
The Aaron
Pro
API Scripter
It would take some work to get an object setup the way you're suggesting, and it would be kind of restrictive as whenever a player changed their name, you'd have to change your script.  Better to deal with the player's unique id, and to do it indirectly.  For example: on('ready', ()=>{     const getPlayers = () => findObjs({type:'player'});     const getCharactersForPlayer = (playerid) =>         findObjs({             type: 'character'         }).filter( (c) =>             c.get('controlledby').split(/,/).includes(playerid) ||             c.get('controlledby').split(/,/).includes('all')         );     const getPlayerCharacterMap = () =>         getPlayers().reduce( (m, p) => Object.assign(m,{[p.id]:{player:p,characters:getCharactersForPlayer(p.id)}}),{});     let lookup = getPlayerCharacterMap();     on('chat:message',(msg) => {         if('api'===msg.type && /^!chars\b/.test(msg.content)){             let who=(getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname');             sendChat('',`/w "${who}" Your character's names are: ${(lookup[msg.playerid]||{characters:[]}).characters.map((c)=>c.get('name'))}`);         }     }); }); Run this !chars to be whispered a list of the names of all the characters you control.
ok thank you, I'll try to implement it that way, I pretty fresh on JS and event-driven programming so wasn't sure how to approach it. My inclination was to go the ADT route, thank you for the help. 
1506518851
The Aaron
Pro
API Scripter
Nothing wrong with that, but you don't really need to start there.  I'm betting you're coming from Java or C++, based on your examples above.  I highly recommend reading Javascript, the Good Parts , by Douglas Crockford . I found it quite helpful.  You can also look into Javascript ES6 and ES2017 and ES2018 to see some of the modern Javascript features (I used a bunch of them above). As for getting used to Event Driven programming, your best bet is to do some tutorials on writing for Node.js.  Roll20's API is basically a Node environment, so the skills will transfer pretty well. And of course, feel free to ask any questions you might have about it. =D
Thank you, and yeah I'm coming from C++, I tend to use my smattering of python when I do anything web related.  I'll def pick up the book and read it and look up some tuts on Node.js. JS has been on my todo list anyway. 
1506520156
The Aaron
Pro
API Scripter
C++ is still the gold standard language I measure all others against (In fact, when I solve coding problems in my head, it's in C++ and then translated to the language I'm writing.).  Through the course of working on Roll20 API Scripts, then writing some Chrome Extensions and finally developing a bunch of Node Modules for work, I've come to really like Javascript.  Feel free PM me if you want to chat about Javascript in the context of transitioning from C++, I feel like I'll have a similar viewpoint to what you might have. =D
1506534053
Lithl
Pro
Sheet Author
API Scripter
The Aaron said: On a technical level, you can't store player objects on the state. It will appear to work, but on restart/restore, it will become a corrupted version. The state can only store basic types. Anything that would work in a JSON object. Of course, while state.foo = myPlayerObject; won't work as expected between executions, state.foo = myPlayerObject.toJSON(); will store all of the player's data. That said, later calling JSON.parse(state.foo); will give you a plain object, not a player object (it'll be missing functions like get and set ). Since you would need to call getObj to get the actual player object anyway, it's better to store the player object's id rather than the entire player, both because you wouldn't then need to parse the JSON string, and because you'd save space in the state object. (There is  a limit to how much data you can store in state. Even if for most purposes it's more than enough, the state object is shared by all scripts in a campaign.)