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

[Script] ScriptCards - My "Spiritual Successor" to PowerCards

1657975111

Edited 1657975412
Thanks for the efforts, I still have an issue apparently where all the messages are doubled, whether the next in turn is visible or not.  It actually outputs the turn of the one playing, and when you press "next" then it re-outputs the one that has just played and the new player's turn. Sorry for all the bother and for my mis-explaination.it's like putting a finger in a cog's wheel and let yourself get swallowed in... ;)
1657976206
David M.
Pro
API Scripter
I'm not seeing that. The only duplicates I see are when advancing the turn from an invisible npc. Square token below is a PC, the rest npcs. The wolf in position 4 is invisible. Eagle in position 3 has a status marker. 
1657976696

Edited 1657976855
David M.
Pro
API Scripter
Sorry for spamming the thread everyone else. Probably should have moved this to a PM :/ OK, going the GM whisper route, try this. If current turn is invisible npc, will whisper to gm. If not, the "next turn" will be the next pc or visible npc. EDIT - I edited the macro below. Since we are whispering the invis turn to GM, now it includes the picture :) !script {{ --/|TRIGGER_REPLACEMENTS --/|If there are no entries in the turn order, don't do anything --?"X[*C:turnorder]X" -eq "X[]X"|SKIP --&turnOrderStr|[*C:turnorder] --~turnOrderStr|string;replaceall;";;[&turnOrderStr] --~turnOrder|string;split;},{;[&turnOrderStr] --%i|1;[$turnOrderCount];1 -->ParseTurnOrder|[&turnOrder[&i]];[&i] --%| --:OUTPUT| --#title|[&name1] --?[$hideTurn1] -eq 1|[ --#whisper|gm --]| --+[&imgStr1]|[b][&name1]'s Turn[/b] --?"X[&currentEffects1]" -eq "X"|NOSTATUS --+Current Effects|[&currentEffects1] --:NOSTATUS| --=t|2 --=done|0 --=maxIterations|100 --:VisibleTurnLoop| --=maxIterations|[$maxIterations] - 1 --?[$hideTurn[$t.Raw]] -eq 1|[ --=t|[$t]+1 % [$turnOrderCount] --]|[ --+Next Turn|[&name[$t.Raw]] --=done|1 --]| --?[$done] -ne 1 -and [$maxIterations] -ne 0|VisibleTurnLoop --:SKIP| --X| End macro --:FUNCTIONS| --:ParseTurnOrder| accepts turnorder string and item number as parameters --~str|string;split;:;[%1%] --~ids|string;split;,;[&str2] --~customVals|string;split;,;[&str4] --=isNPC|[*[&ids1]:npc] --?[$isNPC] -eq 1|[ --&name[%2%]|npc --]| --?[$isNPC] -eq 0 -and [&ids1] -ne -1|[ --&name[%2%]|[*[&ids1]:t-name] --]| --?[$isNPC] -eq 0 -and [&ids1] -eq -1|[ --&name[%2%]|[&customVals1] --]| --&imgStr[%2%]|[img width=70][*[&ids1]:t-imgsrc][/img] --?[*[&ids1]:t-layer] -eq gmlayer -and [$isNPC] -eq 1|[ --=hideTurn[%2%]|1 --]|[ --=hideTurn[%2%]|0 --]| --&currentEffects[%2%]|[*[&ids1]:t-statusmarkers] --<| }}
1657976936

Edited 1657977012
here's how it goes for me <a href="https://www.veed.io/view/3fdaf274-99d9-4377-a04a-78786d21af9c?sharingWidget=true" rel="nofollow">https://www.veed.io/view/3fdaf274-99d9-4377-a04a-78786d21af9c?sharingWidget=true</a> EDIT : Don't know how to make a gif lol
1657977204
David M.
Pro
API Scripter
Weird. Maybe something is off with your trigger setup, or some other kind of script interaction?
David M. said: Sorry for spamming the thread everyone else. Probably should have moved this to a PM :/ OK, going the GM whisper route, try this. If current turn is invisible npc, will whisper to gm. If not, the "next turn" will be the next pc or visible npc. EDIT - I edited the macro below. Since we are whispering the invis turn to GM, now it includes the picture :) !script {{ --/|TRIGGER_REPLACEMENTS --/|If there are no entries in the turn order, don't do anything --?"X[*C:turnorder]X" -eq "X[]X"|SKIP --&amp;turnOrderStr|[*C:turnorder] --~turnOrderStr|string;replaceall;";;[&amp;turnOrderStr] --~turnOrder|string;split;},{;[&amp;turnOrderStr] --%i|1;[$turnOrderCount];1 --&gt;ParseTurnOrder|[&amp;turnOrder[&amp;i]];[&amp;i] --%| --:OUTPUT| --#title|[&amp;name1] --?[$hideTurn1] -eq 1|[ --#whisper|gm --]| --+[&amp;imgStr1]|[b][&amp;name1]'s Turn[/b] --?"X[&amp;currentEffects1]" -eq "X"|NOSTATUS --+Current Effects|[&amp;currentEffects1] --:NOSTATUS| --=t|2 --=done|0 --=maxIterations|100 --:VisibleTurnLoop| --=maxIterations|[$maxIterations] - 1 --?[$hideTurn[$t.Raw]] -eq 1|[ --=t|[$t]+1 % [$turnOrderCount] --]|[ --+Next Turn|[&amp;name[$t.Raw]] --=done|1 --]| --?[$done] -ne 1 -and [$maxIterations] -ne 0|VisibleTurnLoop --:SKIP| --X| End macro --:FUNCTIONS| --:ParseTurnOrder| accepts turnorder string and item number as parameters --~str|string;split;:;[%1%] --~ids|string;split;,;[&amp;str2] --~customVals|string;split;,;[&amp;str4] --=isNPC|[*[&amp;ids1]:npc] --?[$isNPC] -eq 1|[ --&amp;name[%2%]|npc --]| --?[$isNPC] -eq 0 -and [&amp;ids1] -ne -1|[ --&amp;name[%2%]|[*[&amp;ids1]:t-name] --]| --?[$isNPC] -eq 0 -and [&amp;ids1] -eq -1|[ --&amp;name[%2%]|[&amp;customVals1] --]| --&amp;imgStr[%2%]|[img width=70][*[&amp;ids1]:t-imgsrc][/img] --?[*[&amp;ids1]:t-layer] -eq gmlayer -and [$isNPC] -eq 1|[ --=hideTurn[%2%]|1 --]|[ --=hideTurn[%2%]|0 --]| --&amp;currentEffects[%2%]|[*[&amp;ids1]:t-statusmarkers] --&lt;| }} That's perfect for me !!! Sorry y'all guys.
1658233042
Kurt J.
Pro
API Scripter
ScriptCards 2.0.2 is now live on OneClick Here is the consolidated list of updates since the previous OneClick version (1.7.7). Most of these are documented in the Wiki, but there are a still a few changes to make. Major New Features &nbsp;ScriptCards Triggers - Triggers is a feature that allows you to create a specially named character in your game (ScriptCards_Triggers) and define abilities on that character that will be executed when certain events happen in your game, like changing maps, turn order updates, character attribute changes, etc. See the wiki for more information on using Triggers and some examples. Features Updated/Changed &nbsp;Pings - You can now use the --V (visual effects) command to send pings to the VTT. Pings are supported for VFX types of "token" and "point". To send a ping, simply replace the effect descriptor with "ping". Optionally, and additional "moveall" parameter can be added to the --v command to zoom all players viewes to the pinged location: --vtoken|@{selected|token_id} ping moveall &nbsp;Repeating Rows by Index - The --R command has been expanded to allow --Rbyindex to look up repeating items by index number. The syntax is --Rbyindex|&lt;character_id&gt;;&lt;section_prefix&gt;;&lt;indexNumber&gt; &nbsp;Array Referencing - Using [@ArrrayName()] or [$ArrayName(length)] now returns the number of items in an array. [@ArrayName(maxindex)] or [@ArracyName(lastindex)] returns the index of the last item (length - 1) &nbsp;Button Formatting - Adds the ability to set button font sizes inline with the button declaration. Appending :??px (ie, :24px) to a button Opening tag will set the font size for that button : [button:24px] for example. IF you use in-line button colors, they must be specified before the font size (so [button:#f00:24px] is fine, but [button:24px:#f00] will not generate a button) &nbsp;String function striphtml - will remove all HTML tags from a string. &nbsp;Subtitles now support formatting - The leftsub and rightsub settings are now run through the inline formatting function to support things like [b], [i], etc. &nbsp;Font Size Inline Formatting - New Inline formatting code: [F#]...[/F] sets the font size inline to # px. Ex: [F10]Size 10p/F] &nbsp;Player Attributes - when using [*id:attribute] referencing it is now possible to use a player ID to retrieve player attribute information. New Settings &nbsp;- titlefontstyle (default "normal") &nbsp;- titlefontweight (default "strong") &nbsp;- buttonpadding - allows you to control the size of the space around the text on buttons. The default padding is "5px" &nbsp;- enableattributesubstitution - If set to a non-0 value, attribute lookups that contains @{} references to other attributes will be recursively evaluated by looking up their subreferences. This behavior only modifies the *S, *T, *- and *R reference structures since these attribute references don't apply to anything that isn't a character. Bug Fixes &nbsp;- Corrected a potential sandbox crash when referencing array values with [@...()] without the () portion &nbsp;- Fix for reroll dice formulas not properly displaying the dice results that were dropped/rerolled in the hoverover. &nbsp;- Fix for a bug in exploding dice (and anything with a reroll) that could cause REALLY weird results &nbsp;- Bug fix when retrieving repeating section values that are purely numeric (was leaving them out of the returned list)
1658275951

Edited 1658351079
Edit: Work-around provided by David M. here .&nbsp; Thanks, David! I've come across an issue, I suppose it's more an issue with how Roll20 works than with ScriptCards, but perhaps someone here is aware of a work-around? When you subtract from the bar value of a token, if the result is 0 then the actual value stored is null, not 0.&nbsp; This can be a problem if you are comparing the stored value of the bar against something else in the script. Entering 0 manually on the token's bar stores it properly as 0 and not a null value, but if the value is 2, for example, and you subtract 2 (in the field or through TokenMod) rather than just entering 0, it becomes null instead.
I am trying to work with the string commands and cannot make this work:&nbsp;&nbsp; &nbsp; --~Mod|string;before;+;[*S:spellcasting_ability] &nbsp; --=Maximum|[*S:level] + [*S:[&amp;Mod]] &nbsp; --+|[*S:character_name] can prepare up to a maximum of [$Maximum] spells. Interestingly enough, outputting [&amp;Mod] by itself to chat gives the correct answer (charisma_mod) but, once the above macro is run, the chat shows that the output is: 9 + [*S:charisma_mod] but not the correct output of (9 + 4).&nbsp;&nbsp; What am I doing wrong?
1658678671
Kurt J.
Pro
API Scripter
Michael C. said: I am trying to work with the string commands and cannot make this work:&nbsp;&nbsp; &nbsp; --~Mod|string;before;+;[*S:spellcasting_ability] &nbsp; --=Maximum|[*S:level] + [*S:[&amp;Mod]] &nbsp; --+|[*S:character_name] can prepare up to a maximum of [$Maximum] spells. Interestingly enough, outputting [&amp;Mod] by itself to chat gives the correct answer (charisma_mod) but, once the above macro is run, the chat shows that the output is: 9 + [*S:charisma_mod] but not the correct output of (9 + 4).&nbsp;&nbsp; What am I doing wrong? The issue you are running into is that what is actually stored in the spellcasting_ability attribute is something like "@{intelligence_mod}+", and needs to have some additional manipulation done because the chat server is trying to clobber it when displaying it :) It gets further complicated by the SriptCards roll parser trying to make sense of [*S:@{intelligence_mod] (even though you can't see the @{) If you change your string manipulation to: --~Mod|string;after;{;[*S:spellcasting_ability] --~Mod|string;before;};[&amp;Mod] The final output should work as expected. Here, we are stripping off the @{ first and then the }+ at the end.
1658790331

Edited 1658790974
David M.
Pro
API Scripter
5e Mirror Image Scriptcard I was inspired by keithcurtis' Mirror Image approach &nbsp;that uses three macros and token-mod to handle Mirror Image in 5e, though it doesn't seem to preserve other existing statusmarkers. I figured it should be possible to make a single scriptcard handle all that, so I gave it a shot.&nbsp; How it works: Select caster token and run the macro. Choose from the two Action options: To initialize, choose "Casting spell" - it adds a half-haze statusmarker with an overlayed "3". All other statusmarkers are preserved. An initialization message prints to chat. If the caster is attacked, choose "Checking target" - the statusmarkers are parsed and a d20 roll is compared to a target number based on the number of duplicates remaining (the numeric overlay). A reentrant button is printed if a duplicate is determined to be the actual target, along with the calculated AC of the duplicate. If the attack hits (attacks are handled as normal outside of this scriptcard), then you click the "Remove" button and the statusmarkers are updated with the new count. Chat output announces the new number of duplicates reamining. Once the last duplicate is removed, the half-haze marker is fully removed from the token (again preserving the other markers) Notes: You can change the mirror image statusmarker to something else if you want by modifying the variable on line 3. I don't have any spell slot management in here, but you can use whatever method you normally use if that's your thing You may want to reverse the order of the Action query, since targeting happens more often than casting. This may also avoid accidental "casting" when the spell is already in effect (which would overwrite the current number of duplicates) Yes, having an attribute track this would have been easier, but I wanted the statusmarker to give a visible indicator and update automatically with minimal input so I went the parsing and rebuilding route. Potential Issues: Not sure if an attack macro (called after the targeting check) from another scriptcard that uses reentrant buttons would mess this up. I haven't used reentrant scripts much at all, so don't know if the reentrant state object would get annihilated. Macro: !script {{ --#title|Mirror Image --#hidecard|0 --&amp;mirrorMarker|half-haze --&amp;mirrorURL|<a href="https://s3.amazonaws.com/files.d20.io/images/4/O_Jtj7g5zcePHKDrDsxrEw/icon.png?1575370613" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/4/O_Jtj7g5zcePHKDrDsxrEw/icon.png?1575370613</a> --/|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --:Main body| --/|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&amp;action|?{Mirror Image Action?|Casting Spell,Casting|Checking Target,Checking} --:GET CURRENT STATUS MARKERS ON TOKEN| insert into array called markersArr --~|array;statusmarkers;markersArr;@{selected|token_id} --~thisMarker|array;getfirst;markersArr --?[&amp;action] -eq Casting|&gt;CastSpell|&gt;CheckTarget --X| End Macro --/|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --:Reentrant insertion point. the previous number of duplicates is passed back to script| --/|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --:RemoveDuplicate| --#leftsub|Removing duplicate... --&amp;statusmarkers| --=numDuplicates|[&amp;reentryval] - 1 --+[img width=32 height=32][&amp;mirrorURL][/img]|[b]Duplicates remaining: [$numDuplicates.Raw][/b] --~|array;statusmarkers;markersArr;@{selected|token_id} --~thisMarker|array;getfirst;markersArr --:Build the statusmarker string out of current markers, but substituting mirrorMarker number with decremented amount --:ReentrantLoop| --?"X[&amp;thisMarker]X" -inc "X[&amp;mirrorMarker]" -and [$numDuplicates] -eq 0|SKIP --?"X[&amp;thisMarker]X" -inc "X[&amp;mirrorMarker]"|&gt;AppendStatusMarkerString;[&amp;mirrorMarker]@[$numDuplicates];1|&gt;AppendStatusMarkerString;[&amp;thisMarker];0 --:SKIP| --~thisMarker|array;getnext;markersArr --?"X[&amp;thisMarker]" -ne "XArrayError"|ReentrantLoop --&gt;SetMarkers| --X| --/|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --:FUNCTIONS| --/|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --:CastSpell| --#leftsub|Initializing Spell Effect... --+[img width=32 height=32][&amp;mirrorURL][/img]|[b]@{selected|token_name} conjures 3 illusory duplicates[/b] --?"X[&amp;thisMarker]" -eq "XArrayError" -or "X[&amp;thisMarker]" -eq "X"|[ --&gt;AppendStatusMarkerString|[&amp;mirrorMarker]@3 --&gt;SetMarkers| --X| --]| --:Build the statusmarker string out of current markers, but overwrites existing mirrorMarker with initialized number| --=mirrorMarkerFound|0 --:CastLoop| --?"X[&amp;thisMarker]X" -inc "X[&amp;mirrorMarker]"|&gt;AppendStatusMarkerString;[&amp;mirrorMarker]@3;1|&gt;AppendStatusMarkerString;[&amp;thisMarker];0 --~thisMarker|array;getnext;markersArr --?"X[&amp;thisMarker]" -ne "XArrayError"|CastLoop --?[$mirrorMarkerFound] -eq 0|&gt;AppendStatusMarkerString;[&amp;mirrorMarker]@3 --&gt;SetMarkers| --&lt;| --:CheckTarget| --#leftsub|Checking target... --:Build the statusmarker string out of current markers, out of current markers, customize output based on num duplicates left --=mirrorMarkerFound|0 --:TargetLoop| --?"X[&amp;thisMarker]X" -inc "X[&amp;mirrorMarker]"|[ --=mirrorMarkerFound|1 --~temp|string;split;@;[&amp;thisMarker] --?[$tempCount] -eq 1|=numDuplicates;1|=numDuplicates;[&amp;temp2] --?[$numDuplicates] -eq 3|&gt;RollAndOutput;3 --?[$numDuplicates] -eq 2|&gt;RollAndOutput;2 --?[$numDuplicates] -eq 1|&gt;RollAndOutput;1 --?[$numDuplicates] -eq 0|NoDuplicates --]| --?"X[&amp;thisMarker]X" -ninc "X[&amp;mirrorMarker]"|&gt;AppendStatusMarkerString;[&amp;thisMarker];0 --~thisMarker|array;getnext;markersArr --?"X[&amp;thisMarker]" -ne "XArrayError"|TargetLoop --?[$mirrorMarkerFound] -eq 0|[ --:NoDuplicates| --+No illusory duplicates remaining| --+[#990000]Attack automatically targets the caster![/#]| --X| --]| --&gt;SetMarkers| --&lt;| --:AppendStatusMarkerString| accepts a marker string and boolean if matches mirrorMarker, will append to statusmarkers as comma-delimited list --?"X[&amp;statusmarkers]" -eq "X"|[ --&amp;statusmarkers|+[%1%] --]|[ --&amp;statusmarkers|+,[%1%] --]| --?[$mirrorMarkerFound] -ne 1|=mirrorMarkerFound;[%2%] --&lt;| --:RollAndOutput|accepts num duplicates as parameter --&gt;AppendStatusMarkerString|[&amp;thisMarker];1 --=AC|10+@{selected|dexterity_mod} --?[%1%] -eq 3|=targetNum;6 --?[%1%] -eq 2|=targetNum;8 --?[%1%] -eq 1|=targetNum;11 --=Roll|1d20 --+[img width=32 height=32][&amp;mirrorURL][/img]|[b]Duplicates remaining: [%1%][/b] --+Roll|[$Roll] [b]vs. &gt;= Target Number [$targetNum][/b] --?[$Roll] -ge [$targetNum]|DuplicateTargeted|CasterTargeted --:DuplicateTargeted| --+[#009900]Duplicate is targeted![/#]|[b]AC = [$AC][/b] --+Click to remove a duplicate|[rbutton]Remove::RemoveDuplicate;[%1%][/rbutton] --&lt;| --:CasterTargeted| --+[#990000]Caster is targeted![/#]| --&lt;| --:SetMarkers| --!t:@{selected|token_id}|statusmarkers:[&amp;statusmarkers] --&lt;| }} Example output. Our caster Trix is poisoned (existing marker) and casts Mirror Image. A couple iterations of targeting checks are shown.&nbsp;
Hello 2 all and special Thanks to all develloping people for ScriptCards. I'm right in the middle for custom L5R 4th CharSheets and Game-Mods by useing ScriptCards. 2 Question i couldn't find out in this thread and the documentation: 1. Is there the possibility to start a Card by an Player and direct the --i Information Request to the GM. (Usecase: the player attemts a Skill roll, the GM provide the Target Number in-chat and the Player just geht the info, if the roll succeded or not. 2. Is there any help available to implement the Emphasess Rolls, where 10s are expoding (Xd10!&gt;10) and 1s will be rerolled once (Xd10ro&lt;1), so the patterns have to be combined. Thanks for all replys. Stay safe, whereever you are.
Hello! I am trying to learn scriptcards. I have some programing knowledge so I understand the basics, but I am having some trouble finding out how to implement splitting a string. For example: --&amp;TestString|This,is,a,string --~TestArray| {&amp;Teststring....?} How might I go about saying "split this string up by commas into an array"
1658988214

Edited 1658988255
Johan W. said: Hello! I am trying to learn scriptcards. I have some programing knowledge so I understand the basics, but I am having some trouble finding out how to implement splitting a string. For example: --&amp;TestString|This,is,a,string --~TestArray| {&amp;Teststring....?} How might I go about saying "split this string up by commas into an array" The syntax for ScriptCards is in the following location:&nbsp;&nbsp; <a href="https://wiki.roll20.net/Script:ScriptCards" rel="nofollow">https://wiki.roll20.net/Script:ScriptCards</a> It includes a set of array and string functions that can accomplish what you are looking for in a couple different ways: Split Function (String) string split string;split;delimiter;stringValue special Splits&nbsp; stringValue &nbsp;into pieces, breaking it at&nbsp; delimiter . Returns a rollVariable with "Count" appended to the assigned variable name and a series of string variables with numbers appended (starting at 1) for each of the returned pieces. --&amp;MyListOfCommaDelimValues|Dog,Cat,Bird --~item|string;split;,;[&amp;MyListOfCommaDelimValues] --+Count|[$itemCount] --+Item 1|[&amp;item1] --+Item 2|[&amp;item2] --+Item 3|[&amp;item3] This syntax (I've not tested), should produce the following output on a scriptcard: Count 3 Item 1 Dog Item 2 &nbsp;Cat Item 3 &nbsp;Bird FromString function (Array) array fromstring arrayname;delimiter;string unused Creates an array from "string", splitting "string" on "delimiter" to separate the items --&amp;MyListOfCommaDelimValues|Dog,Cat,Bird --~|array;fromstring;MyArray;,;[&amp;MyListOfCommaDelimValues] You would then need to use one of the many array functions to traverse, review, modify, sort, add and remove items.&nbsp;&nbsp; Category Name Function Name Parameters Return Type Description array define arrayname;value1;value2;... none Creates an array called "arrayname" and adds value1, value2, etc. to the array array sort arrayname none Sorts the specified array in place in ascending order (alphabetically) array numericsort arrayname none Sorts the specified array in place in ascending order (numerically) ( v 1.4.10+&nbsp; ) array add arrayname;value1;value2;... none Adds value1, value2, ... to the existing array "arrayname" array remove arrayname;value1;value2;... none Removes value1, value2, ... from the existing array "arrayname". Resets the array index to 0. array replace arrayname;currentvalue;newvalue none Replaces all occurrences of "currentvalue" in "arrayname" with "newvalue" array setatindex arrayname;index;newvalue none Replaces the array item at index "index" with "newvalue" array getindex arrayname stringVariable Retrieves the current index in "arrayname" and stores it in the supplied string variable array setindex arrayname;newindex none Sets the current index in array "arrayname" to "newindex" array getcurrent arrayname stringVariable Gets the item at the current array index in "arrayname" and returns it as a string variable. Will return "ArrayError" if there is no current item. array getnext arrayname stringVariable Increments the current index in "arrayname" and returns the new current value. Will return "ArrayError" if the end of the array is reached. array getprevious arrayname stringVariable Decrements the current index in "arrayname" and returns the new current value. Will return "ArrayError" if the the current index was already zero. array getfirst arrayname stringVariable Set the current index of "arrayname" to zero and retrieve the current item. Will return "ArrayError" if there is no current item. array getlast arrayname stringVariable Set the current index of "arrayname" to the last item in the array and retrieve the current item. Will return "ArrayError" if there is no current item. array removeat arrayname;indexposition none Removes the item at index "indexposition" from "arrayname". Resets the current array index to 0. array indexof arrayname;searchvalue stringVariable Searches the array "arrayname" for an item with the value of "searchvalue" and, if found, returns the index of the first matching value or "ArrayError" if not found array getlength arrayname stringVariable Returns the number of items in array "arrayname" array pagetokens arrayname;tokenid;(optional filter) stringVariable Creates an array (arrayname) of all of the token ids (technically Graphics objects) on the same page as the specified token id. Returns the number of tokens found to the stringVariable. Available optional filters are&nbsp;: all, char, graphic, pc, npc. The filters will return only those tokens that match that criteria (char means tokens have a "represents", graphic doesn't. pc indicates a represents token has a controlledby, npc doesn't.) array selectedtokens arrayname stringVariable Creates an array (arrayname) of all of the token ids (technically Graphics objects) selected when the script was executed. Returns the number of tokens found to the stringVariable. array stringify arrayname stringVariable Returns all of the items in "arrayname" as a string separated by default semicolon (;) or (new in 1.6.7) the current #parameterdelimeter array fromstring arrayname;delimiter;string unused Creates an array from "string", splitting "string" on "delimiter" to separate the items array statusmarkers arrayname;tokenid none Creates an array (arrayname) of the active statusmarkers (sometimes called Token Markers) for the specified tokenid
1659007868

Edited 1659007924
David M.
Pro
API Scripter
To piggyback on Will's explanation and using his example, here are a couple of ways to traverse through a variable number of comma-delimited array elements.&nbsp; With pseudo-"arrays" created with string;split. Uses a for...loop with itemCount and nested references e.g.&nbsp; [&amp;item[&amp;i]] . (Quirk: note that our index i is a string variable type within the for...loop) !script {{ --&amp;MyListOfCommaDelimValues|Dog,Cat,Bird --~item|string;split;,;[&amp;MyListOfCommaDelimValues] --+Count|[$itemCount] --%i|1;[$itemCount];1 --+Item [&amp;i]|[&amp;item[&amp;i]] --%| }}&nbsp; With true arrays using array;fromstring. Uses getfirst/getnext to traverse the array. I added a roll variable i to produce the same output as above. (quirk: note that arrLen is a string variable containing a numeric value. You could make the output look exactly the same as above (with roll formatting) if you assigned a roll variable to the contents of arrLen (not shown) - it currently prints the string "number". !script {{ &nbsp; --&amp;MyListOfCommaDelimValues|Dog,Cat,Bird &nbsp; --~|array;fromstring;MyArray;,;[&amp;MyListOfCommaDelimValues] &nbsp; --~arrLen|array;getlength;MyArray &nbsp; --+Count|[&amp;arrLen] &nbsp; --~element|array;getfirst;MyArray &nbsp; --=i|0 &nbsp; --:Loop| &nbsp; &nbsp; &nbsp; --=i|[$i] + 1 &nbsp; &nbsp; &nbsp; --+Item [$i]|[&amp;element] &nbsp; &nbsp; &nbsp; &nbsp;--~element|array;getnext;MyArray &nbsp; &nbsp; &nbsp; --?[&amp;element] -ne ArrayError|Loop &nbsp; --:Done| }}
Okay, I think I need a little bit of help here. I can't seem to get the following Scriptcard to do what I want it to do. The following script is pretty simple. It's designed to randomly populate the map with NPCs. It rolls to determine gender, then according to the gender it rolls off of either NPC Male or NPC Female. It then randomly rolls a side (each table has 40 NPCs). All of that seems to be working as designed. What isn't working are the Offsets. I just can't get it to work. It just stacks all of the tokens on the target token. I know I'm messing up the array somehow, but I just can't seem to catch it.&nbsp; Oh, and while I'm asking for help, I'm wondering if there's a way to keep it from rolling the same table entry it has already spawned.&nbsp; Here's the Code: !scriptcard {{ --/|Script Name : NPC Generator --/|Author : GM Goss --#sourceToken|@{selected|token_id} --=Counter|0 --~Offsets|string;split;:;0,1:0,-1:1,0:1,1:1,-1:2,0:3,-3:4,4 --=PCCount|?{How many NPCs to Create?|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20} --:AddNPC| --=Counter|[$Counter] + 1 --=CoinFlip|1d2 --?[$CoinFlip.Total] -eq 1|NPCMale --?[$CoinFlip.Total] -eq 2|NPCFemale --X| --:NPCMale| --=TableSide|1d41 -1 --@forselected+|Spawn _name|NPC Male _side|[$TableSide.Total]_offset|[&amp;Offsets[%1%]]_order|toFront _fx|nova-magic _expand|15,30 --?[$Counter.Total] -lt [$PCCount.Total]|AddNPC --X| --:NPCFemale| --=TableSide|1d41 -1 --@forselected+|Spawn _name|NPC Female _side|[$TableSide.Total]_offset|[&amp;Offsets[%2%]]_order|toFront _fx|nova-magic _expand|15,30 --?[$Counter.Total] -lt [$PCCount.Total]|AddNPC --X| }}
1659040896
David M.
Pro
API Scripter
GM Goss, maybe try something like this method? Note this is untested - I just pulled parts from another scriptcard that I had that went up to 32 creatures in a grid pattern. Here is a map of the X &amp; Y offsets it should produce. Interior value is the creature number. The gray headers are the X &amp; Y offsets. You can adjust the offsets to whatever pattern you want (e.g. increase all the X offsets by 1 if you don't want to spawn directly on top of selected token) !scriptcard {{ --/|Script Name : NPC Generator --/|Author : GM Goss --#sourceToken|@{selected|token_id} --=Counter|0 --~DefineArrayOfXOffsets|array;define;offsetX;0;1;0;1;0;1;2;2;2;0;1;2;3;3;3;3;0;1;2;3;4;4;4;4;4;0;1;2;3;4;5;5 --~DefineArrayOfYOffsets|array;define;offsetY;0;0;1;1;2;2;0;1;2;3;3;3;0;1;2;3;4;4;4;4;0;1;2;3;4;5;5;5;5;5;0;1 --=PCCount|?{How many NPCs to Create?|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20} --:AddNPC| --=Counter|[$Counter] + 1 --=CoinFlip|1d2 --=X|[@offsetX([$Counter.Raw])] --=Y|[@offsetY([$Counter.Raw])] --?[$CoinFlip.Total] -eq 1|NPCMale --?[$CoinFlip.Total] -eq 2|NPCFemale --X| --:NPCMale| --=TableSide|1d41 -1 --@forselected+|Spawn _name|NPC Male _side|[$TableSide.Total] _offset|[$X.Raw],[$Y.Raw] _order|toFront _fx|nova-magic _expand|15,30 --?[$Counter.Total] -lt [$PCCount.Total]|AddNPC --X| --:NPCFemale| --=TableSide|1d41 -1 --@forselected+|Spawn _name|NPC Female _side|[$TableSide.Total] _offset|[$X.Raw],[$Y.Raw] _order|toFront _fx|nova-magic _expand|15,30 --?[$Counter.Total] -lt [$PCCount.Total]|AddNPC --X| }}
David M. said: GM Goss, maybe try something like this method? Note this is untested - I just pulled parts from another scriptcard that I had that went up to 32 creatures in a grid pattern. Here is a map of the X &amp; Y offsets it should produce. Interior value is the creature number. The gray headers are the X &amp; Y offsets. You can adjust the offsets to whatever pattern you want (e.g. increase all the X offsets by 1 if you don't want to spawn directly on top of selected token) !scriptcard {{ --/|Script Name : NPC Generator --/|Author : GM Goss --#sourceToken|@{selected|token_id} --=Counter|0 --~DefineArrayOfXOffsets|array;define;offsetX;0;1;0;1;0;1;2;2;2;0;1;2;3;3;3;3;0;1;2;3;4;4;4;4;4;0;1;2;3;4;5;5 --~DefineArrayOfYOffsets|array;define;offsetY;0;0;1;1;2;2;0;1;2;3;3;3;0;1;2;3;4;4;4;4;0;1;2;3;4;5;5;5;5;5;0;1 --=PCCount|?{How many NPCs to Create?|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20} --:AddNPC| --=Counter|[$Counter] + 1 --=CoinFlip|1d2 --=X|[@offsetX([$Counter.Raw])] --=Y|[@offsetY([$Counter.Raw])] --?[$CoinFlip.Total] -eq 1|NPCMale --?[$CoinFlip.Total] -eq 2|NPCFemale --X| --:NPCMale| --=TableSide|1d41 -1 --@forselected+|Spawn _name|NPC Male _side|[$TableSide.Total] _offset|[$X.Raw],[$Y.Raw] _order|toFront _fx|nova-magic _expand|15,30 --?[$Counter.Total] -lt [$PCCount.Total]|AddNPC --X| --:NPCFemale| --=TableSide|1d41 -1 --@forselected+|Spawn _name|NPC Female _side|[$TableSide.Total] _offset|[$X.Raw],[$Y.Raw] _order|toFront _fx|nova-magic _expand|15,30 --?[$Counter.Total] -lt [$PCCount.Total]|AddNPC --X| }} I'm gonna play around with it but that works great. Thanks, Dave.&nbsp;
I am sorry if this has been asked and answered somewhere else, but I'm trying to create a action button (for use in chat chat area, not on the character sheet) link that connects to a handout.&nbsp; And perhaps some links to examples using buttons. Thanks in advance.
1659300035

Edited 1659300189
Kurt J.
Pro
API Scripter
Toby said: I am sorry if this has been asked and answered somewhere else, but I'm trying to create a action button (for use in chat chat area, not on the character sheet) link that connects to a handout.&nbsp; And perhaps some links to examples using buttons. Thanks in advance. You can certainly do this, though you'll need to know the object ID for the handout you want to open. As far as I know, the easiest way to do this is: Open the handout you want to link to Click the Pop-Out button in the upper right to open the handout in a new window Hit F12 to open the developer tools for the popout window On the "Elements" tab, expand the Body and then the Div section inside it. In the Div code under that div, look for the "data-handoutid" value. Here is a screenshot with the ID hilighted: Armed with the ID, creating a button in ScriptCards is simple (ignore the hyperlink formatting in the code block below): [button]Handout Title::<a href="http://journal.roll20.net/handout/YOUR_HANDOUT_ID_HERE[/button]" rel="nofollow">http://journal.roll20.net/handout/YOUR_HANDOUT_ID_HERE[/button]</a> Which will open the handout when clicked. Note that all IDs start with a - sign, so you'll need everything within the quotes.
I am having trouble getting my mind around the "getselected" function.&nbsp; Could someone illustrate an example of its form and function for me, please?
1659442635
David M.
Pro
API Scripter
!script {{ --~tokID|getselected --%i|1;[$tokIDCount] --+id[&amp;i]|[&amp;tokID[&amp;i]] --%| }}
1659446245
Kurt J.
Pro
API Scripter
Michael C. said: I am having trouble getting my mind around the "getselected" function.&nbsp; Could someone illustrate an example of its form and function for me, please? It should be noted that roll20 has what I assume is a bug in that the msg.selected portion of a message object (what the API gets) will be missing if the chat message contains a @{target...} reference, so in that case, getselected won't return anything since - as far as the API knows - nothing is selected.
Okay, this might be a stupid question and I may have just missed something simple, but I'll go ahead and ask anyway. I wrote the following basic Scriptcard to add traits to the GM Notes of a token. !scriptcard {{ --/|Script Name : NPC Generator --/|Author : GM Goss --#hidecard|1 --=Roll1|[T#NPC-Abilities] --=Roll2|[T#NPC-Talents] --=Roll3|[T#NPC-Mannerisms] --=Roll4|[T#NPC-Interaction-Traits] --=Roll5|[T#NPC-Bonds] --=Roll6|[T#NPC-Flaw] --=Roll7|[T#NPC-Appearance] --&amp;Result|[$Roll1.tableEntryText] + [$Roll2.tableEntryText] + [$Roll3.tableEntryText] + [$Roll4.tableEntryText] + [$Roll5.tableEntryText] + [$Roll6.tableEntryText] + [$Roll7.tableEntryText] --@set-gmnote|[&amp;Result] }} If I paste it into chat with the token selected, it does what it's supposed to do. If it put it in a macro or in an Ability, then it doesn't work and displays the following in chat.&nbsp; I thought that maybe it was something being added to the Ability or Macro that breaks it, but if I copy directly from the Macro and paste it into chat, then it works. What am I doing wrong?
1659538810
David M.
Pro
API Scripter
Do you have a space or invisible html character (sometimes included when you copy from certain text editors) in front of the "!" in your macro? Pretty sure this will mess things up. It will work if you "test macro" but not when running the saved macro.&nbsp;&nbsp;
David M. said: Do you have a space or invisible html character (sometimes included when you copy from certain text editors) in front of the "!" in your macro? Pretty sure this will mess things up. It will work if you "test macro" but not when running the saved macro.&nbsp;&nbsp; Yep, that was it. I knew it was something stupid like that. Thanks, David. I appreciate it.&nbsp;
is there a way to specify font color in the --i command?&nbsp; I tried &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; --i[#ff0000]Please click the button below[/#];Select [%1%] Target (w/in 5')|[&amp;TargetString] but it didn't work.
1659543257

Edited 1659543407
@David - Thanks! Ok, I get that you use your mouse to do a group selection of tokens but how does it (and by extension, oneself) know which token is first, second, third, etc.?&nbsp;&nbsp; Edit:&nbsp; @Kurt - Thanks!&nbsp; Does this remain true if the target id is assigned through --sourceTarget command at the start of the macro?&nbsp; Or am I getting confused...
1659555901
timmaugh
Pro
API Scripter
Kurt J. said: Michael C. said: I am having trouble getting my mind around the "getselected" function.&nbsp; Could someone illustrate an example of its form and function for me, please? It should be noted that roll20 has what I assume is a bug in that the msg.selected portion of a message object (what the API gets) will be missing if the chat message contains a @{target...} reference, so in that case, getselected won't return anything since - as far as the API knows - nothing is selected. Using SelectManager can give you at least 1 selected token "back", however. Well, one easily: {&amp; select @{selected|token_id} } But you could also put multiple tokens in there (comma separated), or even targeting returns: {&amp; select @{target|Selected Token 1|token_id}, @{target|Selected Token 2|token_id} } By the time ScriptCards would see the message, the msg.selected property will be present and filled with the appropriate tokens.
I thought I'd ask here since I'm pretty sure that someone has probably already created the subroutine I need for a Scriptcard. What I'm trying to do is make a subroutine that rolls a random number (between 1-60), and then add that into an array. Then when another random number is rolled, it compares that number against the array and if it's in the array, it rerolls. I got the rest of the Scriptcard built, but for some reason I'm having problems with arrays. Any help would be appreciated.&nbsp;
1659808926

Edited 1659808977
David M.
Pro
API Scripter
More than one way to skin a cat for this one. Below, I went with building a comma-delimited string and then using the fromstring array function. This makes it easier to check for the existence of a duplicate roll more easily (without having to build and loop through your array to check each iteration). Just using a -inc conditional to check for duplicates. Included some debugging and test output to convince ourselves that it is working. Note that if numRolls is close to the max number of possible values, the more likely you are to get a "Execution Limit Reached. Terminating Script" error in your console log and a blank scriptcard in chat. For the 1d60 example, this occurs pretty frequently above 51 unique rolls.&nbsp;&nbsp; !script {{ --#title|Unique Rolls Example --&amp;rollType|1d60 --&amp;allRollsStr| --=numRolls|10 --#leftsub|[$numRolls] Rolls --#rightsub|[&amp;rollType] --:Loop through the number of unique rolls you want| --%i|1;[$numRolls];1 --&gt;RollUnique|[&amp;rollType] --%| --:Here's the String we made| --+debug allRollsStr|[&amp;allRollsStr] --:This populates our array from the comma-delimited string --~|array;fromstring;rollArray;,;[&amp;allRollsStr] --+Testing array values...| --~arrayLen|array;getlength;rollArray --~val|array;getfirst;rollArray --+item1|[&amp;val] --%i|2;[&amp;arrayLen];1 --~val|array;getnext;rollArray --+item[&amp;i]|[&amp;val] --%| --X| --:RollUnique| builds a comma-delimited string that we will turn into an array when we are done rolling --:Loop| --=thisRoll|[%1%] --?[&amp;allRollsStr] -inc [$thisRoll.Raw]|Loop --=rollCount|[$rollCount]+1 --?[$rollCount] -lt [$numRolls]|[ --&amp;allRollsStr|+[$thisRoll.Raw], --]|[ --&amp;allRollsStr|+[$thisRoll.Raw] --]| --&lt;| }}
Thanks, David. That's exactly what I was searching for.&nbsp; David M. said: More than one way to skin a cat for this one. Below, I went with building a comma-delimited string and then using the fromstring array function. This makes it easier to check for the existence of a duplicate roll more easily (without having to build and loop through your array to check each iteration). Just using a -inc conditional to check for duplicates. Included some debugging and test output to convince ourselves that it is working. Note that if numRolls is close to the max number of possible values, the more likely you are to get a "Execution Limit Reached. Terminating Script" error in your console log and a blank scriptcard in chat. For the 1d60 example, this occurs pretty frequently above 51 unique rolls.&nbsp;&nbsp; !script {{ --#title|Unique Rolls Example --&amp;rollType|1d60 --&amp;allRollsStr| --=numRolls|10 --#leftsub|[$numRolls] Rolls --#rightsub|[&amp;rollType] --:Loop through the number of unique rolls you want| --%i|1;[$numRolls];1 --&gt;RollUnique|[&amp;rollType] --%| --:Here's the String we made| --+debug allRollsStr|[&amp;allRollsStr] --:This populates our array from the comma-delimited string --~|array;fromstring;rollArray;,;[&amp;allRollsStr] --+Testing array values...| --~arrayLen|array;getlength;rollArray --~val|array;getfirst;rollArray --+item1|[&amp;val] --%i|2;[&amp;arrayLen];1 --~val|array;getnext;rollArray --+item[&amp;i]|[&amp;val] --%| --X| --:RollUnique| builds a comma-delimited string that we will turn into an array when we are done rolling --:Loop| --=thisRoll|[%1%] --?[&amp;allRollsStr] -inc [$thisRoll.Raw]|Loop --=rollCount|[$rollCount]+1 --?[$rollCount] -lt [$numRolls]|[ --&amp;allRollsStr|+[$thisRoll.Raw], --]|[ --&amp;allRollsStr|+[$thisRoll.Raw] --]| --&lt;| }}
1660540353

Edited 1660627443
I was wondering if someone could help me with a change:attribute:hp &nbsp;Trigger script I am working on. The change:attribute:hp &nbsp;returns the character_id as a property. However, looking up if a status marker is present requires a token_id via the built-in statusmarkers function. I am pretty sure I could use the character_id in TokenMod to set a statusmarker but is there any way that I can check for status markers with the character_id? Or somehow get the token-id in some fashion during this Trigger run? EDIT: I think I can use change:graphic &nbsp;to do what I was looking to do. It's trigger provides all the Token properties and I should be able to do something similar to Kurt J's change_graphic trigger example since hp is mapped to a token bar. Looks like it triggers multiple times for different tokens but I can probably use the Campaign playerpageid property to reduce the number of triggers. It would be great if there was a way to make the attribute trigger a little more useful in the sense of getting a Token id to work on since this old works for changes to attributes linked to a token bar so 3 max.
I've an interesting question.&nbsp; I want do display an emote with the token image associated with the character sheet but I don't want to force them to roll from a selected token. Is their a way to reference the token image associated with a specific CHARACTER sheet as opposed to the selected token?
Toby said: I've an interesting question.&nbsp; I want do display an emote with the token image associated with the character sheet but I don't want to force them to roll from a selected token. Is their a way to reference the token image associated with a specific CHARACTER sheet as opposed to the selected token? This isn't exactly what you're asking for, but it may get you to the same place. Using SelectManager and Fetch: {&amp;select &lt;whatever the character name is&gt;} @(selected.token_id) Use that in place of @{selected|token_id}
1660660197

Edited 1660660225
The following Information request is not acting how I expect it --IEnter;Enter|t;target1;Target 1||q;willing1;Is this target willing|Yes,1|No,0||q;vehicle1;Is this target a vehicle?|No,0|Yes,1||t;target2;Target 2||q;willing2;Is this target willing|Yes,1|No,0||q;vehicle2;Is this target a vehicle?|No,0|Yes,1 I want it to request a target and then ask the questions about it, but instead it asks for all the targets first and then it only asks the questions once.&nbsp; Then it assigns the answers to the one set of questions to both sets of variables.
1660664538
timmaugh
Pro
API Scripter
Couple of things to remember... 1) All top-level queries (ie, those not nested in other queries) are issued in the same go, one after another, and 2) A query's index (what makes it unique) is its question, and any time that query index (that question) appears in the command line after the first, the value of the original answer is used. That's why you're getting the same results for both targets. Also... 3) In the order of operations, targeting is resolved&nbsp; before queries, so you're always going to have the targeting requests before the questions for those targets.
1660675771

Edited 1660675784
Kurt J.
Pro
API Scripter
Joshua N. said: I was wondering if someone could help me with a change:attribute:hp &nbsp;Trigger script I am working on. The change:attribute:hp &nbsp;returns the character_id as a property. However, looking up if a status marker is present requires a token_id via the built-in statusmarkers function. I am pretty sure I could use the character_id in TokenMod to set a statusmarker but is there any way that I can check for status markers with the character_id? Or somehow get the token-id in some fashion during this Trigger run? EDIT: I think I can use change:graphic &nbsp;to do what I was looking to do. It's trigger provides all the Token properties and I should be able to do something similar to Kurt J's change_graphic trigger example since hp is mapped to a token bar. Looks like it triggers multiple times for different tokens but I can probably use the Campaign playerpageid property to reduce the number of triggers. It would be great if there was a way to make the attribute trigger a little more useful in the sense of getting a Token id to work on since this old works for changes to attributes linked to a token bar so 3 max. Going from token to character is easy - the token contains a reference to what character it represents (if any). Of course, this doesn't work the other way around : character sheets don't know anything about tokens, since there can be an unlimited number of tokens that reference the same character and they are all individual objects. You would need to do something like use the pagetokens array function to get a list of all of the tokens on the current page and then look for the character ID in question in them to get the token that represents the character.
1660675853
Kurt J.
Pro
API Scripter
Colin C. said: Toby said: I've an interesting question.&nbsp; I want do display an emote with the token image associated with the character sheet but I don't want to force them to roll from a selected token. Is their a way to reference the token image associated with a specific CHARACTER sheet as opposed to the selected token? This isn't exactly what you're asking for, but it may get you to the same place. Using SelectManager and Fetch: {&amp;select &lt;whatever the character name is&gt;} @(selected.token_id) Use that in place of @{selected|token_id} In the ScriptCard itself, you can always use a specific character or token ID in --#sourcetoken and don't need to use a @{selected} reference: --#sourcetoken|-3dnj54k842nxnbc and from that point on, [*S:...] would always reference that character.
Kurt J. said: Joshua N. said: I was wondering if someone could help me with a change:attribute:hp &nbsp;Trigger script I am working on. The change:attribute:hp &nbsp;returns the character_id as a property. However, looking up if a status marker is present requires a token_id via the built-in statusmarkers function. I am pretty sure I could use the character_id in TokenMod to set a statusmarker but is there any way that I can check for status markers with the character_id? Or somehow get the token-id in some fashion during this Trigger run? EDIT: I think I can use change:graphic &nbsp;to do what I was looking to do. It's trigger provides all the Token properties and I should be able to do something similar to Kurt J's change_graphic trigger example since hp is mapped to a token bar. Looks like it triggers multiple times for different tokens but I can probably use the Campaign playerpageid property to reduce the number of triggers. It would be great if there was a way to make the attribute trigger a little more useful in the sense of getting a Token id to work on since this old works for changes to attributes linked to a token bar so 3 max. Going from token to character is easy - the token contains a reference to what character it represents (if any). Of course, this doesn't work the other way around : character sheets don't know anything about tokens, since there can be an unlimited number of tokens that reference the same character and they are all individual objects. You would need to do something like use the pagetokens array function to get a list of all of the tokens on the current page and then look for the character ID in question in them to get the token that represents the character. Thanks for the response Kurt. I wasn't able to make the change:attribute &nbsp;work since it seems from the docs that pagetokens function requires a tokenid already to work. The selectedtokens function could work since it doesn't require a token id already but when the change:attribute &nbsp;trigger fires, it is not a guarantee that the token will be selected. I was able to do what I wanted with the change:graphic &nbsp;and that worked out well so it's not a big deal for me but it did limit the change:attribute &nbsp;trigger a bit if you need to reference any properties only on tokens like statusmarkers. Thanks for ScriptCards. I find it very useful.
timmaugh said: 2) A query's index (what makes it unique) is its question, and any time that query index (that question) appears in the command line after the first, the value of the original answer is used. 3) In the order of operations, targeting is resolved&nbsp; before queries, so you're always going to have the targeting requests before the questions for those targets. That explains it.&nbsp; Thank you.
This isn't exactly what you're asking for, but it may get you to the same place. Using SelectManager and Fetch: {&amp;select &lt;whatever the character name is&gt;} @(selected.token_id) Use that in place of @{selected|token_id} So, wait is this something I can use to have my players not need to select their token, but use functions that require a token selected?&nbsp; If so is their a tutorial on how its used?&nbsp; Cause this is the biggest complaint I get from my players, they have to select their tokens to make rolls (I kinda have OCD and like everything to have lots of details in the chat output).
1660764435

Edited 1660764614
timmaugh
Pro
API Scripter
Toby said: This isn't exactly what you're asking for, but it may get you to the same place. Using SelectManager and Fetch: {&amp;select &lt;whatever the character name is&gt;} @(selected.token_id) Use that in place of @{selected|token_id} So, wait is this something I can use to have my players not need to select their token, but use functions that require a token selected?&nbsp; If so is their a tutorial on how its used?&nbsp; Cause this is the biggest complaint I get from my players, they have to select their tokens to make rolls (I kinda have OCD and like everything to have lots of details in the chat output). Yep. SelectManager and Fetch are a class of script called "metascripts". They aren't intended to "catch" the message the way other scripts do; they're more like workers on an assembly line watching messages go by so they can detect syntax in the command line that triggers particular operations. By the time the message passes that part of the assembly line and is received by the "destination" script (like ScriptCards, Token-Mod, Spawn, ChatSetAttrs, etc.), the message has been altered according to the detected syntax, and the syntax has been removed from the command line. The destination scripts aren't even aware anything was changed. SelectManager does many things (see the linked thread), but here we're using the ability to select tokens virtually using a comma-separated list of the tokens you want to choose: {&amp; select Bob the Hirsute, Clarence} Since this resolves after Roll20 parsing, we can do this: {&amp; select @{selected|token_id} } But we can't rely on Roll20 constructions elsewhere like @{selected|AC}: !defend --ac|@{selected|AC} {&amp; select Bob} This will not consistently get Bob's AC, because that is resolved before he is virtually selected. That's why you have to change those Roll20 constructions to be Fetch constructions (using either a pipe or a period for the divider): !defend --ac|@(selected|AC) {&amp; select Bob} Fetch has the ability to do a default value if it doesn't find one on the token/character, too. Details on that are in the Fetch thread . One thing to note... Metascripts still have an order to them -- they will operate in the order they are installed. Sometimes you want them to operate in a different order, however. The example Colin demonstrated would require SelectManager to take action first (virtually selecting the token) before Fetch could go get the piece of information. The best way to manage this is to also install ZeroFrame (think of this as the manager for the assembly line, telling the other metascripts how to arrange themselves). With ZF installed, SM is defaulted to act before Fetch, no matter what order the scripts are installed. More Reading... The MetaToolbox MetaToolbox Wiki MetaToolbox Examples (from Wiki) ... Specific SelectManager Example (helping Dealer script) SelectManager + Fetch Example (helping TokenMod and a standard message) EDIT: One more thing... Certain Roll20 functions will still require a selected token... like trying to roll an initiative to the Tracker. Those things are resolved before the metascripts have a chance to do anything. However, for most of those you can find a standard script that will help you do what you want to do (eg, an Initiative script), in whose command lines you could still utilize metascript syntax.
I think I have hit a bug related to setting a new delimiter with #parameterdelimiter. If I remove the line #parameterdelimiter|, then the script outputs the selected token ids as expected. But if I set the #parameterdelimiter to anything else, I get no more output. I have repo'd this on versions 2.0.2k which is the latest I see in roll20 script library and in version 2.1.7b which is the latest I saw in Github. !script {{ --#title|Select Test --~NumSelect|array;getlength;SC_SelectedTokens --+DEBUG|Number of selected tokens: [&amp;NumSelect] --?[&amp;NumSelect] -eq "ArrayError"|DONE --~|system;dumpvariables;array --#parameterdelimiter|, --~TIDs|array;stringify;SC_SelectedTokens --+DEBUG|[&amp;TIDs] --#parameterdelimiter|; --:DONE| --X| }} In the 2.1.7b version from Github I was able to use the delimiter in the stringify function itself as expected. Also I've noticed on the documentation releases in some posts here and on the wiki, there are a couple places where instead of parameterdelimiter, there are parameterdelimeter. I checked the script in Github and only see references to parameterdelimiter so I think the meter references are simply typos in the doc.
1661108594
Kurt J.
Pro
API Scripter
Joshua N. said: I think I have hit a bug related to setting a new delimiter with #parameterdelimiter. If I remove the line #parameterdelimiter|, then the script outputs the selected token ids as expected. But if I set the #parameterdelimiter to anything else, I get no more output. I have repo'd this on versions 2.0.2k which is the latest I see in roll20 script library and in version 2.1.7b which is the latest I saw in Github. !script {{ --#title|Select Test --~NumSelect|array;getlength;SC_SelectedTokens --+DEBUG|Number of selected tokens: [&amp;NumSelect] --?[&amp;NumSelect] -eq "ArrayError"|DONE --~|system;dumpvariables;array --#parameterdelimiter|, --~TIDs|array;stringify;SC_SelectedTokens --+DEBUG|[&amp;TIDs] --#parameterdelimiter|; --:DONE| --X| }} In the 2.1.7b version from Github I was able to use the delimiter in the stringify function itself as expected. Also I've noticed on the documentation releases in some posts here and on the wiki, there are a couple places where instead of parameterdelimiter, there are parameterdelimeter. I checked the script in Github and only see references to parameterdelimiter so I think the meter references are simply typos in the doc. Setparemeterdelimiter sets the delimiter YOU use for future statements: --#parameterdelimiter|, --~TIDs|array;stringify;SC_SelectedTokens would not have the intended effect because you have changed the parameter delimiter from ';' to ',', meaning you would need to do --#parameterdelimiter|, --~TIDs|array,stringify,SC_SelectedTokens Prior to version 2.1.0, there is not a way to get stringify to separate the values with another character, but that is addressed in that version (on the GitHub Repo ) by allowing an additional parameter which is used as the separator, so you would just need: --~TIDs|array;stringify;SC_SelectedTokens;, To return the string separated by commas. No need to set the parameterdelimiter (which is really only there to allow you to work around strings that have semicolons in them for some functions. There are a lot of upcoming language improvements in version 2.1.7, which is on the repo and coming to OneClick in the near future.
Kurt J. said: Joshua N. said: I think I have hit a bug related to setting a new delimiter with #parameterdelimiter. If I remove the line #parameterdelimiter|, then the script outputs the selected token ids as expected. But if I set the #parameterdelimiter to anything else, I get no more output. I have repo'd this on versions 2.0.2k which is the latest I see in roll20 script library and in version 2.1.7b which is the latest I saw in Github. !script {{ --#title|Select Test --~NumSelect|array;getlength;SC_SelectedTokens --+DEBUG|Number of selected tokens: [&amp;NumSelect] --?[&amp;NumSelect] -eq "ArrayError"|DONE --~|system;dumpvariables;array --#parameterdelimiter|, --~TIDs|array;stringify;SC_SelectedTokens --+DEBUG|[&amp;TIDs] --#parameterdelimiter|; --:DONE| --X| }} In the 2.1.7b version from Github I was able to use the delimiter in the stringify function itself as expected. Also I've noticed on the documentation releases in some posts here and on the wiki, there are a couple places where instead of parameterdelimiter, there are parameterdelimeter. I checked the script in Github and only see references to parameterdelimiter so I think the meter references are simply typos in the doc. Setparemeterdelimiter sets the delimiter YOU use for future statements: --#parameterdelimiter|, --~TIDs|array;stringify;SC_SelectedTokens would not have the intended effect because you have changed the parameter delimiter from ';' to ',', meaning you would need to do --#parameterdelimiter|, --~TIDs|array,stringify,SC_SelectedTokens Prior to version 2.1.0, there is not a way to get stringify to separate the values with another character, but that is addressed in that version (on the GitHub Repo ) by allowing an additional parameter which is used as the separator, so you would just need: --~TIDs|array;stringify;SC_SelectedTokens;, To return the string separated by commas. No need to set the parameterdelimiter (which is really only there to allow you to work around strings that have semicolons in them for some functions. There are a lot of upcoming language improvements in version 2.1.7, which is on the repo and coming to OneClick in the near future. Thanks Kurt. I misunderstood what that setting was for, sorry about the bogus report. I am looking forward to 2.1.7 coming to OneClick. I have been testing it out in a test game I have and there are some really nice improvements there. One other question I have for you if I may, since I believe you are the sole maintainer of ScriptCards at the moment, is around the pagetokens function. In a previous post you had mentioned using pagetokens function to grab token ids. All the documentation and examples show pagetokens passing in a token id to the function, which then grabs a page id. Looking at the current code of ScriptCards shows that it also takes a page id directly. Using the page id worked great for a script I wrote but I wanted to ask if that way of using the pagetokens function was intended and supported. I don't want to abuse the API and have it break down the road because I was using an unreleased "feature".
1661187725
Kurt J.
Pro
API Scripter
Yes, using a page id is valid there... I'll need to update the wiki :)
1661243942
Kurt J.
Pro
API Scripter
ScriptCards 2.1.7c is now Live on OneClick The latest version of ScriptCards is now live on OneClick. This version mostly focuses on bringing some convenience features to the language. Here is the full list of changes since 2.0.2k: - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Additional sandbox protection code for some rare crash cases - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; New options for conditional and case statements: o &nbsp;&nbsp; You can now specify “&lt;” as the result of a conditional branch or case result to return immediately from a subroutine call. For example, “--?[$Roll] -eq 1|&lt;” will return out of the function if the value of $Roll is 1. o &nbsp;&nbsp; You can now specify “+” as the result of a conditional branch or case result to create a line of output conditionally. The bolded portion of the output line comes first, followed by a semicolon, followed by the non-bolded content. For example, “--?[$Roll.Base] -eq 1|+Fumble;Something has gone terribly wrong!” will only output the “Fumble…” text if the die roll of $Roll was a 1. o &nbsp;&nbsp; You can now specify “*” as the result of a conditional branch or case result to create a line of GM-only output conditionally. The bolded portion of the output line comes first, followed by a semicolon, followed by the non-bolded content. For example, ‘--?”[*T:resistance]” -inc “fire”|*Resistant;This creature is resistant to fire attacks’ will only output the “Resistant…” text if the resistance attribute contains fire, and the message will only be displayed to the GM. - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Updates to array functions o &nbsp;&nbsp; The array;stringify function now accepts and optional additional parameter that, if specified, will be used to separate the joined array objects instead of the default semicolon. (Ex. --~Result|array;stringify;MyArray;,) o &nbsp;&nbsp; The array;sort and array;numericalsort functions now accept an optional additional parameter. If set to “descending” (or really just the first for letters – desc) the sort order will be reversed: (Ex. --~|array;numericsort;MyArray;Descending) - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object handling has been improved o &nbsp;&nbsp; Arrays of object IDs for Roll20 objects can now be returned with the array;objects function. This&nbsp; function has the format: --~|array;object:OBJECTTYPE;ArrayName;Filter Where OBJECTTYPE is one of campaign, player, page, path, text, graphic, character, attribute, ability, handout, macro, rollabletable, tableitem, deck, card, hand, jukeboxtrack, custfx. The Filter parameter will return only objects whose filter field starts with the specified text (non-case sensitive). For any object with a name property, the filter field is “name”. For other objects the filter field is _displayname for players, title for jukeboxtracks, stroke (color) for paths, text for text and not supported for campaign, card, and hand objects. Ex: --~|array;objects:handout;MyArray;magic item Returns an array of object IDs for all Handouts with a name starting with “magic item”. o &nbsp;&nbsp; Object modification statements (--!) now support the ability to modify any type of object by specifying the object type and object id in the tag portion of the statement. Note that very little checking is done on this (if the property you are setting is imgsrc, the image source will be&nbsp;&nbsp; reformatted per Roll20 requirements). &nbsp; Ex: --!graphic:@{selected|token_id}|bar1_value:256 Will set the "bar1_vlaue" property of the selected graphic object to 256. As with variable referencing, you are likely better off using the specific object type commands (ie, --!t: and --!a:, etc.) when they are available. Note that setting Bio, Notes, and GMNotes will actually make the setting, but it isn't immediate and will not necessarily be available if read back within the same script. It will also throw a console message about needing to pass a callback. o &nbsp;&nbsp; The variable reference notation [*O:objectId:objecttype:property] can be used to retrieve any property from any type of object (with the standard limitations on bio, notes, etc.) The object types are campaign, player, page, path, text, graphic, character, attribute, ability, handout, macro, rollabletable, tableitem, deck, card, hand, jukeboxtrack, custfx. Note that you are likely better off using the type-specific referencing types when available (like [*C:] for campaign, etc.) Note that retrieving the "action" property of a macros and abilities is not supported, as this will often lead to a sandbox crash as ScriptCards tries to parse any potential variables in the macro text. - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The built-in turnorder function now supports sorting the turn order: --~turnorder|sort will sort numerically in descending order. adding and optional third parameter with a value of either "a" (for ascending) or "u" (for up) will sort numerically in ascending order. - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Retrieve Repeating Section information into Arrays: o &nbsp;&nbsp; array;fromrepeatingsection;ArrayName;character_id;repeating_section_name;repeating_field_name will return an array by looking up all of the repeating section entries on Character_ID for the "repeating_section_name" repeating list and return an array consisting of all of the values of repeating_field_name for that section. Ex: ~|array;fromrepeatingsection;AttackNames;@{selected|character_id};repeating_attack;atkname o &nbsp;&nbsp; array;fullrepeatingsection;ArrayName;character_id;repeating_section_name;field1:field2:field3;separation_sequence will return an array the same as fromrepeatingsection except that multiple fields can be added to the array entries. The returned values will be separated in the array entry by separation_sequence. Note that the field list is colon (:) separated. Ex: --~| array;fullrepeatingsection;MyArray;@{selected|character_id};repeating_attack;atkname:dmgbase:dmgtype;: - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String Variable Referencing now has an extended syntax that allows you to return substrings, &nbsp;modified versions of strings, or information about the &nbsp;&nbsp;&nbsp;&nbsp;string. This is done by including the information you want in parentheses after the variable name inside the [&amp;..] block: Examples: &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString] = "The quick Brown Fox jumps over the Lazy Dog" &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(length)] = 43 &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(tolowercase)] = "the quick brown fox jumps over the lazy dog" &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(touppercase)] = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG" &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(totitlecase)] = "The Quick Brown Fox Jumps Over The Lazy Dog" &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(replace,quick,fast)] = "The fast Brown Fox jumps over the Lazy Dog" &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(replaceall,o,i)] = "The fast Briwn Fix jumps iver the Lazy Dig" &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(contains,Dog)] = 1 &lt;-- Case sensitive contains &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(contains,dog)] = 0 &lt;-- Case sensitive contains &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(icontains,dog)] = 1 &lt;-- Non-Case Sensitive contains &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(indexof,Jumps)] = -1 &lt;-- Case sensitive indexof - indexof returns -1 if not found &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(iindexof,jumps)] = 20 &lt;-- Non-case sensitive indexof. First location where the sequence occurs &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(lastindexof,o)] = 41 &lt;-- The character position (0-based) of the last time the sequence occurs &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(4)] = "Quick Brown Fox Jumps Over the Lazy Dog" &lt;-- Starting at char #4, rest of string &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(4,5)] = "Quick" &lt;-- 5 characters beginning at character 4 &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(-3)] = "Dog" &lt;-- The last 3 characters of the string &nbsp;&nbsp;&nbsp;&nbsp;[&amp;MyString(-8,4)] = "Lazy" &lt;-- Starting 8 characters from the end of the string, 4 characters - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bug Fixes o &nbsp;&nbsp; When using --#whisper with a non-blank value, the output of the emote section was being skipped. It is now shown as intended. o &nbsp;&nbsp; When using the &amp; branch modifier of a conditional to set a string to an empty string, the assignment was failing, leaving the old value in the string. o &nbsp;&nbsp; Using --!t to set token values to blank is now possible o &nbsp;&nbsp; Using --!t to set barX_link values is now supported
I could use some help with this code.&nbsp; I am trying to make a marco that will run down a list of question and allow me to input the vaule for a monster char sheet.&nbsp; It is not for 5e but another, but I keep getting a error that I need --sel to be used what i am doing wrong Here is the code: !scriptcard {{ --hidecard | 1 --:ArmorClass | --=ArmorClass |?{AC|} --+ debug | [$ArmorClass.Text] --@setattr |_sel _ArmorClass|[$ArmorClass.Text] }}
1661463389

Edited 1661463423
@cyberlinxz - it looks like you may not be using the correct attribute for a NPC and are using a numerical variable to store a text result. (ie. the .TEST is unnecessary.)&nbsp; For DnD 5e character sheets, it would be: !scriptcard {{ -- # hidecard|1 --:ArmorClass| --=ArmorClass|?{AC|0} --+debug|[$ArmorClass] --@setattr| _sel _ npc_ac |[$ArmorClass] }} (The # was left out of the hidecard command as well and I would not put spaces between command codes like --+ debug | as opposed to --+debug| as such commands might not function.)