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

Newbie struggles with ScriptCards and TokenIDs...

1677278463

Edited 1677280904
Apologies.   I'm new to Roll20 mods.  [This is actually MooseyJo's husband, the programmer half of the D&D duo.  Call me Unbe.]  :) I'm using ScriptCards, and have have created a few nice things with it so far. I also have Fetch and SelectManager, though I haven't successfully accomplished anything with them yet. I am NOT using TokenMod... nor do I want to change anything in a token. What I want to do is, simply obtain a token ID from a character name. Yes, there can be more than one token for a character.  Don't care.  Gimme one.  :) No, it's not selected in advance, nor do I wish to be prompted to select one. Theoretically, both Fetch and SelectManager can do this... but am I right that they won't/can't return the value back to ScriptCards?  They'll only pass it out to ANOTHER mod somewhere?  [Insert howls of frustration here.] If so, is there some OTHER way, within ScriptCards, to accomplish this, that anyone may know of? Again: The desired solution does NOT involve manually selecting an icon at any time.  I have a character name, I can easily get a character ID, but I wish to access a token ID (any token ID) belonging to that character... Thanks in advance...  :) P.S. I'm also going to edit and add: PLEASE don't ask WHY I want the token ID.   You may have guessed from the above that I have already searched the forums, and read many posts with people trying to accomplish this same task, but always getting derailed. "Oh, you can just select the token." "Oh, TokenMod can do what you want." "Oh you can accomplish that particular goal some other way..." I really, actually, just want to do the actual thing I'm saying.  It's either possible or it isn't, and it's not the end of the world if it's just Not Possible -- but Fetch and SelectManager clearly have SOME trick up their sleeves, and I'm just wondering if it's accessible to me in ScriptCards... Thanks, and I promise I'm not as cranky as this post must make me sound... :)
1677295349

Edited 1677300171
timmaugh
Pro
API Scripter
Hi, Unbe... You're partly right that Fetch will return the information to another mod/script... What actually happens is that it returns the information to the command line , the content of the message, which then would be caught by another mod. Fetch just happens to run first, so by the time ScriptCards would see the message, the command line has already been changed. It's really just shorthand to say that "fetch returns the value for another mod," because in order for Fetch to run, you already have to be in a bangsy message. At that point, you're no longer sending something to the chat output. The only way to get a chat output once you've started a bangsy message is to let the command line be caught by another mod which then outputs a separate message to the chat. So all you have to do is: @(Bob.token_id) Fetch will return the ID of the first token for Bob on this page. Put that wherever you need it in your script cards command line, and it should work.
1677299761

Edited 1677300105
Apologies again, but your sentence before "So all you have to do is" makes no sense at all to me.  Could you try again, slower for us dummies? I've tried both: --=tokenid|@(bob.token_id) and --&tokenid|@(bob.token_id) Neither of these seems to give me bob's token id in a ScriptCard variable, which is what I'm trying to accomplish. Certainly, none of THESE followup statements: --+TokenID:|[$tokenid] --+TokenID:|[$tokenid.raw] --+TokenID:|[$tokenid.text] --+TokenID:|[&tokenid] ...has ever coughed up a token ID. Can you show me a pair of ScriptCard statements that would get a token ID from a character name, store it in a variable, and then display it? I have no doubt I'm doing something stupid, but I haven't found the problem yet... P.S. Typing  @(bob.token_id)  at the chat prompt doesn't do anything either...  Is there something I'm supposed to do with Fetch or SelectManager beyond simply installing them?
1677300160

Edited 1677300228
You might look at Kurt's "Action" script, I believe he might do something like this in the code.    If not, I believe I could write you up something in Scriptcards.  I assume you want the list of Character Names to be presented to you in a dropdown or a scriptcard, and then once selected, it could give you an array of tokenids (when there are more than one).  I could then ping them on the map.  
1677300930

Edited 1677302797
Actually, Will, for this particular use case, I'm hardcoding the script for one particular character, and just want to use the character name in the script to derive a token ID, because I'd like to make that ID the ScriptCards "selected" and "targeted" token, so it displays the token graphic on both sides at the top of the card. That simple.  I'm not NEARLY at the level you suggest. Two lines that convert a character name to a token ID, store it in a ScriptCards variable, and then demonstrate it by printing it out to the chat, are all I'm hoping to figure out right now... If the solution also incorporates "why can't I make Fetch or SelectManager actually *DO* anything?", I will die happy... :) :) I *KNOW* this is a dumb question... but other than by installing it via my game's main page, how would I locate script code for looking at?
This is how the ScriptCards documentation says to use SelectionManager: --@token-mod|{^& select Quej Gr'stra} _on showname ...but again, I don't want to pass anything to another mod, and I can't seem to use SelectionManager from within ScriptCards otherwise. What I'd LIKE to do is something like: {^& select bob} <=== Somehow use SelectionMod to pretend-select Bob... --&tokenid|@{selected|token_id} <== Just like everyone says to do, use the selected token, and store the token ID in my var... Of course, one of my attempts three messages ago to use Fetch would be even nicer... Thanks for trying to help, guys... :)
1677339745
David M.
Pro
API Scripter
Tim, it looks like Fetch is trying to use the token name when using @(Bob.token_id), rather than the character name. I tested with a character named "Bob", but the token (with "represents" set to Bob) had a blank name token property.  Running the following test scriptcard returned an empty string: !script {{   --&tokenID|@(Bob.token_id)   --+tokenID|[&tokenID] }} When I changed the token name to "Bob", it was able to display the id. @MooseyJo, regardless of the method to get the token id, you'll want to store it in a string variable (using --&varName syntax)
1677341586

Edited 1677341911
timmaugh
Pro
API Scripter
My apologies on the incoherence of that sentence. Talk-to-post failed me, there, but I have corrected the sentence in my previous post. Also, just entering a Fetch construction like @(Bob.token_id) into chat won't do anything. All of the metascripts require that your message starts as a bangsy message (prepended with ! ) to let them do work. This is because... while scripts can listen for non-bangsy messages (taking action based on simple chat messages that never go to the Script Moderator), the whole point of metascripts (like Fetch) is to process the message and add/remove data from it along the way... before another script picks the message up. Scripts can't change a simple message headed to chat, so it wouldn't help to try to have Fetch look for Fetch-constructions in a normal message... the Fetch construction would still be in the message that hit the chat output. So you'll have to start with a bangsy message. The easiest way to see if Fetch is working would be to install ZeroFrame (the metascript organizing script), and then send a message using its {&simple} syntax. The {&simple} tag outputs the message as a simple chat message once all of the metascripts (like Fetch) have had a chance to make their alterations. So, with Fetch and ZeroFrame installed, you can test your Fetch construction like this: !The ID returned by Fetch is @(Bob.token_id[not found]).{&simple} You should see something like this hit the chat: The ID returned by Fetch is -M1234567890abcdef ...or... The ID returned by Fetch is not found The "not found" bit in the Fetch construction is a default value in case nothing is found... ie, if the token can't be found to return an ID. Seeing that in the chat would tell you that Fetch is, indeed, working, but you just haven't referenced a token that Fetch can find. If, instead, you see the Fetch construction survive into the chat: The ID returned by Fetch is @(Bob.token_id[not found]) ... that would tell you that Fetch is either not installed, disabled, or that there is some other problem. Once you've confirmed that Fetch is going to return the data you want, I believe the syntax to declare a variable in ScriptCards is: --=var|value EDIT : Corrected by David's post, above. Regarding SelectManager... To understand metascripts (and ScriptCards) generally, you have to remember which message you're in, and when you want the meta-construction to be detected. In something like what you posted from the ScriptCards documentation:  --@token-mod|{^& select Quej Gr'stra} _on showname ...that is the way ScriptCards will dispatch a new, outbound message. So we have our first message (sent to ScriptCards), and then ScriptCards constructs a new command line (from what you provide), and sends a new message out (which, in this case, will be picked up by TokenMod). Both of those messages will go through the entire stack of scripts you have installed, it just happens that not every script will take action. They're all testing for the triggers that tell them "this is my message... it's time to get to work." (Metascripts sit at the head of that queue, and instead of looking for a trigger that tells them "this is my message", they look for triggers that tell them to do things to the message... if you think of the message as a train and installed scripts as stops along the train's route, metascripts are more like a series of tunnels that let the train pass through.) The important bit is that since both messages will run through the metascripts, you have to know when you want to actually "select" the token. If you let SelectManager see that {&select} structure in the first message (the message that will eventually land in ScriptCards), then the token will be detected for the first message. That isn't what  you'd want. You want to select the token (in this case) for the message that will land with TokenMod (ie, the second message). So the documentation you copy/pasted is showing you also how to defer (using the ^ character) the SelectManager construction {&select} so that it isn't immediately detected. When ScriptCards dispatches the new message (through chat, but which we know TokenMod will pick up), it removes the caret. That means that when the second message goes through the scripts installed in your game, SelectManager will now see the construction and select the token you want... and all prior to TokenMod catching the message. That's just explanation for that bit of documentation... in your case, you don't have an outbound message. You just want to be able to access the token immediately in your ScriptCards command line. So you wouldn't defer the detection of the selection. You'd just put this somewhere in your command line: {&select Bob} After that, the token is selected -- and it is selected in the right message -- but this only happens after Roll20 parsers have had their chance at the message, so you aren't going to be able to use Roll20 constructions like @{selected|token_id} ... because at the time you dispatch the message and the Roll20 parsers examine the message, you don't yet have the correct token selected. Using the SelectManager method, you have to use another script to pull the data you want. That can be Fetch, using a reference to the selected token: @(selected.token_id) ...or it can be ScriptCards, using ScriptCards syntax to reference the selected token (ScriptCards doesn't know that the token selection was added by SelectManager... and it doesn't care). Those are two options beyond the initial idea of just using Fetch, where you can use Fetch directly in the ScriptCards syntax... ...but I'm just your resident metamancer. After verifying that Fetch works by using ZeroFrame (as mentioned above) and after replacing Bob with your token name (obviously), if  the above doesn't work  we'll want a ScriptCard acolyte to weigh in. One caveat about using SelectManager and Fetch without ZeroFrame... If you don't use ZeroFrame, then the metascripts run only once, and they run in the order you have them installed in your script stack (even though they'll run before standard scripts). If you have Fetch installed before SelectManager, then you won't be able to first select the token and then pull the data using Fetch. When Fetch discovers its syntax structure in the command line, it will try to pull the data from the selected token at that point... and you don't know what token (if any) will be selected. By having ZeroFrame installed, it will organize the other scripts into an order that typically makes sense (and which you can change), and it will loop through the metascripts until they are done. In the default configuration, SelectManager runs before Fetch. If you are still having issues... If you're still having issues after all of this, please post a screenshot of your installed scripts, and the actual text of the command you're trying to run. Or you can send me an invite to your game and I'll come take a look. We'll get to the bottom of it!
1677343559
timmaugh
Pro
API Scripter
Ah, now that I posted I see the problem David is mentioning... the specific case of... ...looking for a token property ...using a token that represents a character, and ...has an empty token name (ie, only a character name) Until I can code a patch for that (probably tonight), you can adjust for the gap by giving your token a name. After that, everything else I said should hold true.
1677345135
timmaugh
Pro
API Scripter
Or I could just do it now. An updated version of Fetch (now v2.0.4) is in my repo , and it's in the pipeline for the 1-click merge (which I think happens Tuesdays, now...?). As mentioned, this patches the specific problem of looking for a token property on a token which represents a character but which has no token name (ie, although the token would start out with a name matching the represented character, the player/gm would have manually deleted the token's name). If that was your issue, Unbe, this should get you sorted.
...Wow.  A *LOT* to think about and process.  Including getting ZeroFrame installed (which was on my to do list, but not high enough, apparently)... If it's possible that my mods are processing in the wrong order, that's gotta be part of the issue.  (Timmaugh -- you say metascripts will fire before standard scripts.  Is ScriptCards code a "standard script"?   Because it was my first install...) (I know ScriptCards is an upgrade/replacement for PowerCards -- but is there something else that would be a "standard script"?) Looking forward to having access to {&simple} to see some meta output... :) Once ZeroFrame is installed, I will see if Timmaugh's patch has rescued me.  I haven't installed anything except through the 1-click yet, so we'll see how that goes. And now that I check, the character I've been working with, has a default token with both the "represents" and "name" fields filled in.  At least, as displayed in the "edit token properties" window...  Hmmm... Thank you guys SO MUCH for all of this.  I knew I had a lot to learn, but... having only JUST dove in to having a Pro account and having access to mods, I had no idea just how deep this pool actually got. You've given me lots of ideas of how to proceed, which is really what I needed.  I'll leave an update here, either later today or tomorrow, once I have some news...
1677356138

Edited 1677356908
Well, first of all, BREAKTHROUGH! Merely installing ZeroFrame knocked everything into shape (i.e. gave Fetch proper priority) and made this line: --&tokenid|@(Bob.token_id) ...actually return the token ID!  YAY!  PARTY TIME! That said, I'd PREFER to pass in a variable for the name.  I know that Fetch fires before ScriptCards -- just sticking the variable in won't work, because it won't be translated in time -- but I see ScriptCards has a "deferral character" for that.  So as far as I can tell, this should WORK: --&name|Bob --&tokenid|@^([&name].token_id) ...but no luck.  &tokenid gets set to "@^(Bob.token_id)" And... on further reading, I see that ScriptCards is relying on the --@ command to get rid of the "^" before letting Fetch process, and since I'm just assigning the value to a string variable and NOT calling another mod... I may be out of luck here. What're the odds I can get a SECOND mod developer to add a tweak for me?  ;) *SIGH*  Oh well.  Hardcoding a value more than once in your code is bad programmer style, but I'll live with it for now.  Thank you guys again.  I'll try VERY HARD not to lean on your generosity while I learn this scripting stuff.  :) [Followup: Is there a proper, non-rude, non-presumptuous way to submit a feature request to mod developers around here?  I mean, it seems a natural extension of the concept of the deferral character, to extend it to the variable assignment commands...?]
1677357163
timmaugh
Pro
API Scripter
Most scripts you encounter are what we'd call standard scripts... I *think* I'm the only one who has purposefully dabbled in the metascript arena, though credit for the trick of them belongs with The Aaron. So far, my metascript toolbox consists of: ZeroFrame APILogic Fetch SelectManager Muler MathOps Plugger Basically, a standard script is a mod that is intended as the end-recipient of a command line (like TokenMod, ScriptCards, Reporter, SmartAoE), and which registers during a particular window of the sandbox bootup. A metascript is a mod that isn't intended as the end-recipient of a command line, and which registers at a different/earlier window during sandbox startup. You can see a potential grey area there...  with a third group of scripts (typically one-offs or quick gap-fillers) which are both intended to be the end-recipient of a command line but which (knowingly or unknowingly) register at the earlier window. For these, metascripts don't automatically work because of their registration trick ("work" in the sense of modifying the message and letting it pass on to the intended recipient script)... they'll only work if they're installed before the intended recipient script. A lot of times, this won't matter -- like I said, these are typically smaller scriptlets with a small job to do. If it becomes a bigger deal, it isn't hard to change a few lines of code in them to get them to register later. ... ...and... one other thing as you think about the order scripts are installed. Typically, your Mod Deck (when you go to your game launching page, then choose Settings > Mod (API) Scripts ) will show you the order the scripts are installed in, but it isn't always accurate. I've installed a script and instead of appearing as the last script in the tab order, it's 3 or 4 back. If you ever want to know the actual order the scripts are installed in, you can use ScriptInfo . Most of the popular/well-used scripts (at least among those in the forums) use another of Aaron's tricks to report data about themselves... like the order they are installed in, and ScriptInfo will show that to you. Good luck and post back if you continue to have issues.
1677357798
timmaugh
Pro
API Scripter
Moosey Jo said: Well, first of all, BREAKTHROUGH! Merely installing ZeroFrame knocked everything into shape (i.e. gave Fetch proper priority) and made this line: --&tokenid|@(Bob.token_id) ...actually return the token ID!  YAY!  PARTY TIME! Excellent! That said, I'd PREFER to pass in a variable for the name.  I know that Fetch fires before ScriptCards -- just sticking the variable in won't work, because it won't be translated in time -- but I see ScriptCards has a "deferral character" for that.  So as far as I can tell, this should WORK: --&name|Bob --&tokenid|@^([&name].token_id) Two things... if you want a single place to store the name, and then you'd use that variable elsewhere... APILogic provides definitions during the metascript cycle: {&define ([namevar]Bob)} It will do a text replace for term=>definition throughout the rest of the macro, so make sure to pick something unique. Then, since Fetch runs before APILogic, we'd want to defer Fetch constructions using the ZeroFrame deferral (backslash). So this should work: {&define ([namevar]Bob)} --&tokenid|@\(namevar.token_id) Of course, you could also use the Fetch construction to get the ID of the token, but then put that in a ScriptCard syntax structure that lets you "get" that token in a way that would let you get the properties off of that token (so you wouldn't need Fetch constructions after getting the ID... you could use ScriptCards syntax). However, for that, you'd need a disciple of the ScriptCard path. =D [Followup: Is there a proper, non-rude, non-presumptuous way to submit a feature request to mod developers around here?  I mean, it seems a natural extension of the concept of the deferral character, to extend it to the variable assignment commands...?] Typically, just posting to the Mod Forum with your use case and feature-request is enough. If the script is actively maintained (or if it isn't but another scripter is available) it can be added to the list... or explained why it might not work.
1677362785

Edited 1677363480
The equivalent of a precompiler #define *WAS* something I was hoping for... :) Would it be possible (or possible, but a Bad Idea) to use ZeroFrame to bump APILogic ahead of Fetch? [Seems like a #define would be the definition of something you'd always want going first...]
1677370645

Edited 1677511059
timmaugh
Pro
API Scripter
Yep.... Originally there was only APILogic, and it handled everything... But to address scope creep and provide greater flexibility, various components were broken off into discrete scripts. The definitions stayed with APIL because of some interaction with the conditional checks, but I've since thought that that would have been the time to move them. Now there are macros that rely on that timing (happening in APIL), so I don't want to move it. Maybe I could just scrape and duplicate the functionality with a ZeroFrame {&global} tag... Working exactly the same way, just at the headwaters of each trip through the metascript loop. Hmm... That could work. For now, yes, you can reorder the metascripts. You can do it universally, or just in a single command line (or even a single loop). I wouldn't think you'd want APIL always going before fetch, just because you might often want to test character or token properties in one side of a conditional... Ie, "if the health is below x, do this, else..." Plus, if I can get the globals tag active, that would be the specific part you'd want early. For a single command line reorder, use {&0 select apil fetch} somewhere in your command line. You're basically giving primacy of order to the scripts you specify, and those you don't specify will follow after in default order. You don't have to specify ZeroFrame. If you want to see the default order (and the handles you can use in that {&0} tag), you can run !0 from the command line once you have ZeroFrame installed. I'd have to double check the syntax for a universal reorder...