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

Best "Hack" to Create a Graphical Button?

I'm trying to devise a way to create a button-graphic that, when clicked, triggers a function call.  I understand there isn't a direct way to do this (via, say, an on("click:graphic") event or the like), but does anyone have any ideas how the existing API could be used to facilitate similar behavior? So far, the best solution I've come up with is to create a sort of "wiggle" button that responds to being moved, via the "change:graphic" event:  When a player moves the graphic, it performs a scripted action, then moves itself back to its original position (like the various token lock scripts).  I could also use this for incrementing and decrementing values, depending on whether the player moves the button up or down. Has anyone figured out a more elegant way of accomplishing this?  I'm fairly new at working with the Roll20 API, so please let me know if you anticipate any problems with the method I'm considering, too. Thanks in advance for your help!
1493709574
Havoc
Sheet Author
API Scripter
You need something like this? The "Use Fate Point!" is a button. Code: <a href="<<RETRY>>" style="background-image:url('+fortunePointBackground+'); border:0px; background-repeat:no-repeat; background-size:100% 100%; background-color:transparent; background-position:center; color:black; padding:10px 20px 10px 30px">Use Fate Point!</a> And it passes the API command in it (RETRY).
1493723485

Edited 1493723493
The Aaron
Pro
API Scripter
Ryan, Stephen S. and I have spent lots of time talking about all kinds of ways to get a UI on the map like what you're talking about. &nbsp;The best two we've come up with are: Dragtivation -- Exactly what you're talking about. Making a graphic, then watching for the player to move it and taking some action. Rotactivation -- Making a graphic, then watching for the player to rotate it and taking some action. Stephen has built some pretty interesting interfaces out of those two. &nbsp;He's largely concerned with map making with tiles. &nbsp;One of his proto-scripts used Rotactivation to change the selected tile to a different style (for example, clockwise to get progressively more ruined, counter-clockwise to be restored). &nbsp;Another of his scripts creates a whole slew of little buttons to the upper right from the last manipulated point which provide an interface for setting properties on that point. &nbsp;If you look back through some of his posts, you might get some ideas: &nbsp; <a href="https://app.roll20.net/forum/discussions_by/135636" rel="nofollow">https://app.roll20.net/forum/discussions_by/135636</a> If I recall correctly, setting is_drawing is an important step for the Dragtivation tokens as it lets them move only a few pixels without snapping back and failing to send the notification back to the API. &nbsp;It also gets rid of the bars and buttons. &nbsp; Hope that helps!
1493723865

Edited 1493723998
Havoc said: You need something like this? The "Use Fate Point!" is a button. Code: &lt;a href="&lt;&lt;RETRY&gt;&gt;" style="background-image:url('+fortunePointBackground+'); border:0px; background-repeat:no-repeat; background-size:100% 100%; background-color:transparent; background-position:center; color:black; padding:10px 20px 10px 30px"&gt;Use Fate Point!&lt;/a&gt; And it passes the API command in it (RETRY). That looks exactly like what I want!&nbsp; Where does this appear though?&nbsp; Does it work directly on the game board, or is it a character sheet thing?&nbsp; I'm not quite sure how to apply HTML to graphic objects on the main playing area itself. (Also, damn, that's beautiful---if you're ever looking for a player for a FATE game, I'd love the opportunity to apply :)&nbsp; I've been looking for a quality FATE game for quite some time.)
The Aaron said: Ryan, Stephen S. and I have spent lots of time talking about all kinds of ways to get a UI on the map like what you're talking about. &nbsp;The best two we've come up with are: Dragtivation -- Exactly what you're talking about. Making a graphic, then watching for the player to move it and taking some action. Rotactivation -- Making a graphic, then watching for the player to rotate it and taking some action. Stephen has built some pretty interesting interfaces out of those two. &nbsp;He's largely concerned with map making with tiles. &nbsp;One of his proto-scripts used Rotactivation to change the selected tile to a different style (for example, clockwise to get progressively more ruined, counter-clockwise to be restored). &nbsp;Another of his scripts creates a whole slew of little buttons to the upper right from the last manipulated point which provide an interface for setting properties on that point. &nbsp;If you look back through some of his posts, you might get some ideas: &nbsp; <a href="https://app.roll20.net/forum/discussions_by/135636" rel="nofollow">https://app.roll20.net/forum/discussions_by/135636</a> If I recall correctly, setting is_drawing is an important step for the Dragtivation tokens as it lets them move only a few pixels without snapping back and failing to send the notification back to the API. &nbsp;It also gets rid of the bars and buttons. &nbsp; Hope that helps! Ooh I like the idea of rotating---you could easily (?) make little dials that could be set to specific amounts, rather than just up or down.&nbsp; Thank you for the link, I'll definitely review those scripts!
1493726421
The Aaron
Pro
API Scripter
Dragtivation ends up feeling more natural, in our experiences. &nbsp;It's a single click and drag. Rotactivation requires selection, then click and drag on the rotate handle. &nbsp;Also, it always snaps to 45º unless you hold alt, so there is a minimum movement required to activate.
1493743116
Lithl
Pro
Sheet Author
API Scripter
Ryan said: Havoc said: You need something like this? The "Use Fate Point!" is a button. Code: &lt;a href="&lt;&lt;RETRY&gt;&gt;" style="background-image:url('+fortunePointBackground+'); border:0px; background-repeat:no-repeat; background-size:100% 100%; background-color:transparent; background-position:center; color:black; padding:10px 20px 10px 30px"&gt;Use Fate Point!&lt;/a&gt; And it passes the API command in it (RETRY). That looks exactly like what I want!&nbsp; Where does this appear though?&nbsp; Does it work directly on the game board, or is it a character sheet thing?&nbsp; I'm not quite sure how to apply HTML to graphic objects on the main playing area itself. That's in the chat. Command buttons (which normally appear as white text on fuchsia backgrounds) are simply links whose href attribute begins with ! (for API command buttons) or ~ (for ability command buttons). In a rolltemplate, you can style those links however you please. Additionally, you can send a raw anchor tag to the chat via sendChat in the API and style it inline as demonstrated by Havoc.
With rotation, you could set a single token to easily do 8 different things if you click on it and then use &lt;e-key&gt;+mousewheel to rotate 45-degrees at a time. (I'm pretty sure you can detect the angle it ends up at, anyway.) To make it even easier, create a&nbsp;circular graphic with 1-8 on it at the so you always know which choice will occur. Obviously it's something I've thought about, but never got around to doing... Edit: &nbsp;Oops. &nbsp;I guess Ryan already thought of my dial idea. &nbsp;So this post was a waste of time.
1493758399
The Aaron
Pro
API Scripter
Nah, always great to talk about things. =D Stephen S. had a script where the rotation set which tool you were using for "painting" tiles or erasing them, etc. =D
1493800114
plexsoup
Marketplace Creator
Sheet Author
API Scripter
If you're up for putting the buttons in the chat sidebar, you can use the psGUI script. <a href="https://app.roll20.net/forum/post/4637161/library-" rel="nofollow">https://app.roll20.net/forum/post/4637161/library-</a>... <a href="https://github.com/Roll20/roll20-api-scripts/blob/master/psIsoUtils/psGUI.js" rel="nofollow">https://github.com/Roll20/roll20-api-scripts/blob/master/psIsoUtils/psGUI.js</a>
Woo, it works like a charm, thanks all!&nbsp; The script below lets you create a configurable line of dots (it's for Storytelling/White Wolf/Onyx Path games).&nbsp; Wiggle a dot up, and it fills the bar up to that dot.&nbsp; Wiggle a dot down, and it empties that dot and everything below it. Being new to this whole thing, I figured I'd post it in case anyone is inclined to offer feedback on anything I could have done better, coding/best-practices wise.&nbsp; Thanks again for all your help! var&nbsp;DotTracker&nbsp;=&nbsp;DotTracker&nbsp;||&nbsp;{} 'use&nbsp;strict'; var&nbsp;imgDotEmpty&nbsp;=&nbsp;'<a href="https://s3.amazonaws.com/files.d20.io/images/32477494/jX2dkr4WDfMaGEca9vt66w/thumb.png?1493802973" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/32477494/jX2dkr4WDfMaGEca9vt66w/thumb.png?1493802973</a>'; var&nbsp;imgDotFull&nbsp;=&nbsp;'<a href="https://s3.amazonaws.com/files.d20.io/images/32477493/9CH89MKVpxfV6NrUpMUxog/thumb.png?1493802967" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/32477493/9CH89MKVpxfV6NrUpMUxog/thumb.png?1493802967</a>'; DotTracker.dotLine&nbsp;=&nbsp;function&nbsp;(startGridX,&nbsp;startGridY,&nbsp;gridWidth,&nbsp;gridHeight,&nbsp;gridSpacing,&nbsp;dotCount)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;pageID&nbsp;=&nbsp;Campaign().get('playerpageid'); &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;cellSize&nbsp;=&nbsp;70&nbsp;*&nbsp;getObj('page',&nbsp;pageID).get('snapping_increment'); &nbsp;&nbsp;&nbsp;&nbsp;this.width&nbsp;=&nbsp;cellSize&nbsp;*&nbsp;gridWidth; &nbsp;&nbsp;&nbsp;&nbsp;this.height&nbsp;=&nbsp;cellSize&nbsp;*&nbsp;gridHeight; &nbsp;&nbsp;&nbsp;&nbsp;this.startX&nbsp;=&nbsp;cellSize&nbsp;*&nbsp;(startGridX&nbsp;-&nbsp;1)&nbsp;+&nbsp;0.5&nbsp;*&nbsp;this.width; &nbsp;&nbsp;&nbsp;&nbsp;this.startY&nbsp;=&nbsp;cellSize&nbsp;*&nbsp;(startGridY&nbsp;-&nbsp;1)&nbsp;+&nbsp;0.5&nbsp;*&nbsp;this.height; &nbsp;&nbsp;&nbsp;&nbsp;this.gridSpacing&nbsp;=&nbsp;gridSpacing; &nbsp;&nbsp;&nbsp;&nbsp;this.dotCount&nbsp;=&nbsp;dotCount; &nbsp;&nbsp;&nbsp;&nbsp;this.currentValue&nbsp;=&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;this.dots&nbsp;=&nbsp;[]; &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;xShift&nbsp;=&nbsp;0 &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;this.dotCount;&nbsp;i++)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.dots[i]&nbsp;=&nbsp;createObj('graphic',&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_pageid:&nbsp;pageID, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name:&nbsp;'dotTrackerButton', &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;isdrawing:&nbsp;true, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imgsrc:&nbsp;imgDotEmpty, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;left:&nbsp;this.startX&nbsp;+&nbsp;xShift, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;top:&nbsp;this.startY, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width:&nbsp;this.width, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height:&nbsp;this.height, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;controlledby:&nbsp;'all', &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;layer:&nbsp;'objects' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.dots[i].value&nbsp;=&nbsp;i&nbsp;+&nbsp;1; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.dots[i].controller&nbsp;=&nbsp;this; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xShift&nbsp;+=&nbsp;this.width&nbsp;+&nbsp;this.gridSpacing&nbsp;*&nbsp;cellSize; &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;this.SetValue&nbsp;=&nbsp;function&nbsp;(value)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.currentValue&nbsp;=&nbsp;(value&nbsp;&gt;&nbsp;this.dotCount)&nbsp;?&nbsp;this.dotCount&nbsp;:&nbsp;(value&nbsp;&lt;&nbsp;0)&nbsp;?&nbsp;0&nbsp;:&nbsp;value; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;this.currentValue;&nbsp;i++) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.dots[i].set('imgsrc',&nbsp;imgDotFull); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(i&nbsp;=&nbsp;this.dotCount&nbsp;-&nbsp;1;&nbsp;i&nbsp;&gt;=&nbsp;this.currentValue&nbsp;;&nbsp;i--) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.dots[i].set('imgsrc',&nbsp;imgDotEmpty); &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;this.AdjustDotLine&nbsp;=&nbsp;function&nbsp;(obj,&nbsp;prev)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;newYPos&nbsp;=&nbsp;obj.get('top'); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;obj.set({&nbsp;left:&nbsp;prev.left,&nbsp;top:&nbsp;prev.top&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(prev.top&nbsp;&gt;&nbsp;newYPos) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.SetValue(obj.value); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.SetValue(obj.value&nbsp;-&nbsp;1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;}; }; on("change:graphic",&nbsp;function&nbsp;(obj,&nbsp;prev)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(obj.get('name')&nbsp;===&nbsp;'dotTrackerButton')&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;obj.controller.AdjustDotLine(obj,&nbsp;prev); &nbsp;&nbsp;&nbsp;&nbsp;} }); on("ready",&nbsp;function&nbsp;()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;testDotLine1&nbsp;=&nbsp;new&nbsp;DotTracker.dotLine(6,&nbsp;7,&nbsp;2,&nbsp;2,&nbsp;0.5,&nbsp;10); &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;testDotLine2&nbsp;=&nbsp;new&nbsp;DotTracker.dotLine(6,&nbsp;12,&nbsp;2,&nbsp;2,&nbsp;0.5,&nbsp;10); &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;testDotLine3&nbsp;=&nbsp;new&nbsp;DotTracker.dotLine(6,&nbsp;17,&nbsp;2,&nbsp;2,&nbsp;0.5,&nbsp;10); &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;testDotLine4&nbsp;=&nbsp;new&nbsp;DotTracker.dotLine(6,&nbsp;22,&nbsp;2,&nbsp;2,&nbsp;0.5,&nbsp;10); &nbsp;&nbsp;&nbsp;&nbsp;testDotLine1.SetValue(0); &nbsp;&nbsp;&nbsp;&nbsp;testDotLine2.SetValue(3); &nbsp;&nbsp;&nbsp;&nbsp;testDotLine3.SetValue(8); &nbsp;&nbsp;&nbsp;&nbsp;testDotLine4.SetValue(10); });
1493818499
The Aaron
Pro
API Scripter
Hey, great that you have a first version! The feedback I would offer is regarding the use of this. &nbsp;Roll20 objects are stored in a Firebase database. &nbsp;When they are changed (created, manipulated with .set(), etc), their personal state is synchronized via the Firebase. &nbsp;Firebase stores simple objects. &nbsp;There are two problems I think you could run into by attaching properties to Roll20 objects like you have: 1) .controller is a function. &nbsp;Functions are not simple objects, IF &nbsp;Firebase stores properties that are not set via .set(), this property is unlikely to survive. 2) The this &nbsp;you are storing and referencing is in the current execution of the API. &nbsp;When the API is restarted (either by saving a script, or by everyone exiting the game and then rejoining after the automatic shutdown threshold), it is unlikely to still be around. Because of this, I would suggest making a few changes. &nbsp;First to how you are storing the data you want available for each instance of your dot and second to how you are referencing the dot that had a change. Storing Data You have several choices. &nbsp;You could either reconstruct your collection of data on restart of the API, effectively on('ready',...), or you could store it somewhere it will persist across restarts. &nbsp;It doesn't really matter where you store it, just do whichever feels natural to you. &nbsp;You obviously know Javascript, so I'll just summarize some options: Reconstruct: Find all the graphics that have the 'dotTrackerButton' name and relate them based on the page and position Persist: create a property in the global&nbsp; state object and maintain your information there. &nbsp;The state object is persisted for you.&nbsp; Referencing your Dots Every graphic in Roll20 has a unique id. &nbsp;You can use that to lookup information about your object in wherever you store your data. &nbsp;If your stored data has a shape like: data = { [page id]: { [graphic id]: { /* data related to this graphic */ }, [graphic id]: { /* data related to this graphic */ }, [graphic id]: { /* data related to this graphic */ } }, [page id]: { [graphic id]: { /* data related to this graphic */ }, [graphic id]: { /* data related to this graphic */ }, [graphic id]: { /* data related to this graphic */ } } }; Then it's easy to lookup by page id and graphic id, both of which are on the object you get in the change event. &nbsp;You could also create your own dotLine id to associate all the dots in that line with: data = { dots: { [graphic id]: [dotLine id], [graphic id]: [dotLine id], [graphic id]: [dotLine id], [graphic id]: [dotLine id], [graphic id]: [dotLine id] }, dotLines: { [dotLine id]: { /* data related to this dotLine */ }, [dotLine id]: { /* data related to this dotLine */ }, }, nextDotLineID: [some integer] }; I use this second layout in most of my scripts (Look at Bump for one such). &nbsp;I often have a task at api start to go through and clean up anything where graphics don't exist anymore or the graphics have been moved out of where I expect them. &nbsp;Both those things can happen when the API is not running (maybe it crashed?). The last thing I'll mention is just a matter of personal preference. &nbsp;I'm a big fan of the&nbsp; Revealing Module Pattern for writing API scripts. &nbsp;Coming from a heavy C++ programming background, I'm a big fan of encapsulation and reducing the scope of things. &nbsp;You might find you like it as well and it will keep things like imgDotEmpty and imgDotFull out of the global scope.
Thank you so much for the advice! A few questions/clarifications: When you say " .controller is a function", do you mean that " controller ", specifically, is an existing function that I'm overriding?&nbsp; Or do you mean that I'm assigning it incorrectly, and should use set('controller', this) instead?&nbsp; Or do you mean that assigning " this " as a property at all is the wrong way to go about things?&nbsp; (I needed a way to reference the functions in the instantiated dotLine object from the graphic object returned by the on('graphic:change') event.) I modeled my use of this off of the instructions for getting classes to work from this article on the wiki .&nbsp; Are you saying I should avoid using this entirely, or that I just need to properly store the instances I create with my classes?&nbsp;&nbsp; I was planning to use the state object as you suggested, but perhaps a little naively:&nbsp; I was intending to simply create a state.DotTracker.dotLines[] array of my object instances.&nbsp; Is that something I should avoid (perhaps what you're getting at with the next section)? I'm definitely going to have to spend a bit of time figuring out the "Referencing Your Dots" section; I'm sure the script you provided as an example will be a big help.&nbsp; Is this meant to be an alternative to using classes and instances with this entirely, or is it just a cleaner way to reference the instantiated objects once I've created them and linked them to the state object?&nbsp; I too am a big fan of encapsulation (and really everything object-oriented, hence my instant embrace of classes and this in the Roll20 API); the image sources in the global scope are definitely just a quick-and-dirty way of getting the script off the ground Thanks again for your help! &nbsp;
1493825520
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
I'd say that you don't need the this.asdfasdf anywhere in the script. Unless I'm missing something (totally possible), you aren't passing the current state of the function to another instance of the function and javascript assumes that you are using the current iteration of a variable unless told otherwise. What Aaron is saying though is that when you do: this.dots[i].controller&nbsp;=&nbsp;this; You are assigning the entire current state of the function (and the fact that it is a function to the controller property of dots[i]. (honestly this seems like it should cause a circular object to me, but I don't know for sure.
1493831113

Edited 1493831468
Lithl
Pro
Sheet Author
API Scripter
Ryan said: When you say " .controller is a function", do you mean that " controller ", specifically, is an existing function that I'm overriding?&nbsp; Or do you mean that I'm assigning it incorrectly, and should use set('controller', this) instead?&nbsp; Or do you mean that assigning " this " as a property at all is the wrong way to go about things?&nbsp; (I needed a way to reference the functions in the instantiated dotLine object from the graphic object returned by the on('graphic:change') event.) The latter. this.dots[i] is a Roll20 object, and while JS will happily allow you to set whatever properties you want on it with whatever values you please, that won't necessarily be synchronized on Firebase. (Actually, I suspect when it comes to Roll20 objects, no custom properties will be synchronized, but I haven't tested that.) Ryan said: I modeled my use of this off of the instructions for getting classes to work from this article on the wiki .&nbsp; Are you saying I should avoid using this entirely, or that I just need to properly store the instances I create with my classes? FWIW, since that page was written, the API has gained access to&nbsp; actual JavaScript classes , instead of the hacked-together sort-of classes that used to be the standard of JS. That said, the problem here is not in the fact that you're making use of a class, but what you're attempting to store. Ryan said: I was planning to use the state object as you suggested, but perhaps a little naively:&nbsp; I was intending to simply create a state.DotTracker.dotLines[] array of my object instances.&nbsp; Is that something I should avoid (perhaps what you're getting at with the next section)? No, that would be an appropriate use of state. (Edit: for storing simple objects and primitive types; for example, you couldn't correctly store your graphic objects, but you could store their IDs for later retrieval.) However, do note that the contents of state are passed through JSON.stringify when stored on Firebase, which means that values which are not part of the JSON specification (most notably, functions) will be dropped entirely. It also means that circular structures (eg, var obj = {}; obj.foo = obj;) will throw an error if you try to pass them into JSON.stringify (which Roll20 does to the state object automatically). Scott C. said: honestly this seems like it should cause a circular object to me, but I don't know for sure. Yes. this.foo = this is going to create a circular structure. Javascript can handle that just fine, though. JSON can't.
1493839430
The Aaron
Pro
API Scripter
Just as Brian said. =D Regarding the use of this , I'm not going to say you shouldn't use it. &nbsp;However, I don't think I'm boasting when I say that I have more released API scripts than any other contributor and not a single one of them uses this . &nbsp;It might become necessary with later scripts I write that deal with classes, but hasn't so far. &nbsp;That's not to say that using this is bad, just that I've not found a place I needed to do it.
1493843537
Lithl
Pro
Sheet Author
API Scripter
The Aaron said: Just as Brian said. =D Regarding the use of this , I'm not going to say you shouldn't use it. &nbsp;However, I don't think I'm boasting when I say that I have more released API scripts than any other contributor and not a single one of them uses this . &nbsp;It might become necessary with later scripts I write that deal with classes, but hasn't so far. &nbsp;That's not to say that using this is bad, just that I've not found a place I needed to do it. I have a couple scripts that make use of `this`. Some of those are because I have scripts adding onto existing prototypes, though (eg,&nbsp; splitArgs adds itself to the String prototype, so that 'foo'.splitArgs has `this` being a reference to 'foo').&nbsp; Triggered SFX uses `this` to reference functions accessible to the lambda functions written by the user (eg, if the user writes play(...) it's translated to this.play(...) in order to reference the function correctly).&nbsp; Observable and&nbsp; ESRO both use function-as-class syntax.&nbsp; JSQL uses a combination of function-as-class and actual classes.