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

Kurt J. said: non said: I think this is a Scriptcard issue so I thought that maybe this would be the better place to ask: currently I'm trying to make a Macro that deals damage and then checks to see if a creature is going to be below 50% hp or 0% hp and apply the Red or Dead Statusmarker respectively. So far it works but when I run it, it asks for a Target 2 times, the first for a 'Target' and the second for a '1'. Here's the exact syntax: @{target|1|hp|max} If I try that syntax outside of a Scriptcard it works without asking for a second target. I can't change the '1' out since without it, the check returns 'undefined,' so I'm a bit stuck. I've also tried using the '[*T:var]' syntax but that also yields 'undefined.' I'm using that like so: [*T:1|hp|max] If y'all know a better way to get the Max HP of a @{target} within Scriptcards it'd be much appreciated, thanks! For the sake of thoroughness, here's the line in its context:   --:Mark| --=HalfHP|@{target|1|hp|max} \ 2 --=TotalHP|@{target|bar1} + @{target|bar3} --=EstFinalHP|[$TotalHP] - [$TotalDamage] --? [$EstFinalHP] -le [$HalfHP]|MarkRed --? [$EstFinalHP] -le 0|MarkDead --:ReturnMark| --<| @{} notation is processed by the chat server before ScriptCards ever sees it. The reason you are being prompted twice is that your macro is asking for two targets: an unamed targetwith @{target|bar3} and a target named "1" with @{target|1|hp|max}. In both cases, ScriptCards only gets to see the final result of this lookup, and never knows there was any targeting done. If you wish to use the [*T:] notation, you need to set the #targettoken parameter. This can be done like this: --#targettoken|@{target|token_id}. From then on, you can use [*T:attribute] to retrieve character attributes or [*T:t-attribute] to retrieve token attributes. Since it isn't  a complete script, I can't test it, but something along these lines should work: --:Mark| --#targettoken|@{target|token_id} --=HalfHP|[*T:hp^] \ 2 --=EstFinalHP|[*T:hp] - [$TotalDamage] --? [$EstFinalHP] -le [$HalfHP]|MarkRed --? [$EstFinalHP] -le 0|MarkDead --:ReturnMark| --<| Also, if you are using something like Token_mod, etc to apply the damage, keep in mind that it won't take place until after the script completes, so it isn't possible to check before and after status of attributes. What you have above is the right way to do it (look at what it was beforehand and subtract the new damage amount and compare that. The hp^ syntax works exactly like I needed it to, thanks!
1621874472

Edited 1621882482
Craven said: How can i call a macro from within scriptcard without using a button. Example I have a macro called longrest and shortrest and I want to make a scriptcard that players select --&chose|?{What type of rest?|Long, |Short, } that will run the correct macro. The macros are stored on a character sheet.  The without a button confuses me as I would generally use the [button] functionality.  You can do all this within a single scriptcard. * Provide a list of options to players (short rest, long rest, ....) each enclosed within an [button]ButtonText::~[CharName]|[MacroName][/button]Something like: !script {{ ... --+|[c][button]Short Rest::~[charname]|SHORT_REST[/button][/c] --+|[c][button]Short Rest::~[charname]|LONG_REST[/button][/c] ... ... }} When the user clicks on the associated button, it should kick off the associated macro. There is also a [sheetbutton], not currently in the Wiki, that has the following syntax: [sheetbutton]ButtonCaption::Character::AbilityMacro[/sheetbutton]  
Kurt J. said: Will M. said: @Kurt - on your Distance calcs, could you divide the result by 70 after you perform your final equation? On very large maps with a snapping_increment less than 1 (like .2), the rounding being performed is having a significant impact on the result.  For example: Go from this: case "euclideandistance": var result = 0; if (params.length >= 3) { var token1 = getObj("graphic", params[1]); var token2 = getObj("graphic", params[2]); if (token1 && token2) { // Calculate the euclidean unit distance between two tokens (params[1] and params[2]) var x1 = token1.get("left") / 70; var x2 = token2.get("left") / 70; var y1 = token1.get("top") / 70; var y2 = token2.get("top") / 70; result = Math.floor(Math.sqrt(Math.pow((x1-x2),2)+Math.pow((y1-y2),2))); } } rollVariables[variableName] = parseDiceRoll(result.toString(), cardParameters); break; to this: case "euclideandistance": var result = 0; if (params.length >= 3) { var token1 = getObj("graphic", params[1]); var token2 = getObj("graphic", params[2]); if (token1 && token2) { // Calculate the euclidean unit distance between two tokens (params[1] and params[2]) var x1 = token1.get("left"); var x2 = token2.get("left"); var y1 = token1.get("top"); var y2 = token2.get("top"); result = Math.floor(Math.sqrt(Math.pow((x1-x2),2)+Math.pow((y1-y2),2))) / 70.0; } } rollVariables[variableName] = parseDiceRoll(result.toString(), cardParameters); break; I am careful about changing the way things work in case someone is using them in a macro, but how about this: I can create a new distance method, maybe euclidianpixels that returns the raw value you could then divide by 70, or euclidianlongrange that does the /70 as you describe above. That would work great.  I've actually added a routine like this to my version of your dev code to make it work.  On a side note, it got me thinking about if it would be possible to create my own ScriptCard library of functions and tie it to your core logic through inheritance.  That way, as SC continues to evolve and improve, my version would always get your latest improvements, but it would also include new functions I wrote and only I could use.  
David M. said: Woombak said: Am I dreaming or I've seen some of you working on a radar script ? Yep, that's me. You can direct any questions about it that aren't scriptcard-related to the dedicated thread , though its scope is really more detection-oriented rather than "do stuff to the things". <<At the risk of being both premature and off-topic for this thread: I had a novel UI idea and had started a new script for that exact purpose a while ago that was radar-adjacent, but it was a bear and I paused work on it early in development to focus on other things. I should probably resurrect that project, though no promises that it will pan out. End of off-topic discussion - you may now resume normal scriptcard-relevant conversations ;) >> I've seen your new thread and it's looks awesome ! Was wondering how I could tweak it up to be able to determine if the foes of my PC willing to cas a spell are in range or not!  I know that he coul duse the ruler tool to do so but I'd like to know if there's a way to know(w scriptcard of course) before releasing an AOE, who's gonna be in.... Thanks in advance !
1621900754
David M.
Pro
API Scripter
Woombak, sounds like a pretty straightforward use of the radar script, though keep in mind that line effects are not supported by the script. Keeping this scriptcards-related, you could have your SC fire a radar api call and output a button linked to a macro or ability that has the "real" AoE spell SC in it. If you're not catching who you want in the AoE, then don't click the SC spell button. However, this sounds a bit fiddly. Instead, I'd probably use the Spawn script to create an instance of the default token for your AoE spell's "character" (with art either something semi-transparent or with a predefined token aura so you can see underlying target tokens), move it into place, then leave it selected as the source token for a subsequent SC AoE spell macro/ability. You could put the SC into an ability on the AoE spell's character sheet so you could set it as a token action for convenience.
!scriptcard  {{   --#title|Claws   --#titlecardbackground|#993333   --#leftsub/Melee Attack   --#rightsub/5’ Reach   --#sourceToken|@{selected|token_id}   --#targetToken|@{target|token_id}   --#emoteText|@{selected|token_name} attacks @{target|token_name}   --=AttackDamage|1d20 + 3 [STR]   --+Attack|You rolled [$AttackDamage] to hit vs Armor Class @{target|ac}   --?[$AttackDamage.Base] –eq 20|Crit   --?[$AttackDamage.Base] –eq 1|Fumble   --?[$AttackDamage.Total] –1t @{target|ac}|Miss   --:Hit|   -->RollDamage|   --+Hit!|You dealt [$Damage] slashing damage   --X|     --:Miss|   --+Miss|Your attack missed!   --X|     --:Fumble|   --+Fumble|Your attack went horribly wrong!   --X|   --:Crit|   -->RollDamage|crit   --+Critical Hit!|You dealt [$Damage] slashing damage on a critical hit!    --X|     --:RollDamage|   --?[%1%] –eq crit|CritDamage   --=Damage|1d4+ 3 [STR]   --<|   --:CritDamage|   --:Damage|1d4 + 3 [STR] + 1d8 [CRIT]   --<| }} I use roll20 and bought pro for my friend so I have access to the api scripts. I am honestly just winging this and am pretty sure this is mostly done on Dnd 5e over what we use as pathfinder. I basically watched your entire video and copied the one longsword attack and made a few changes (and by that I mean like claw) I did notice that that AttackRoll function and npc_ac function seem to be different on Pathfinder which is annoying and I was able to get it to show the attack roll by making a few changes but when it comes to hitting and missing the script always states its a hit and never fails regardless of my role. If someone could help me with this that would be great and I could do my best to figure it out as I go but I am struggling with this, if not no worries and I still greatly enjoyed your videos.
it also isnt adding the leftsub or rightsub into the macro at all so not sure if that's just an error on my part or also some disconnect between DND and pathfinder
1621923566

Edited 1621963000
Will M. said: Craven said: How can i call a macro from within scriptcard without using a button. Example I have a macro called longrest and shortrest and I want to make a scriptcard that players select --&chose|?{What type of rest?|Long, |Short, } that will run the correct macro. The macros are stored on a character sheet.  The without a button confuses me as I would generally use the [button] functionality.  You can do all this within a single scriptcard. * Provide a list of options to players (short rest, long rest, ....) each enclosed within an [button]ButtonText::~[CharName]|[MacroName][/button]Something like: !script {{ ... --+|[c][button]Short Rest::~[charname]|SHORT_REST[/button][/c] --+|[c][button]Short Rest::~[charname]|LONG_REST[/button][/c] ... ... }} When the user clicks on the associated button, it should kick off the associated macro. There is also a [sheetbutton], not currently in the Wiki, that has the following syntax: [sheetbutton]ButtonCaption::Character::AbilityMacro[/sheetbutton]   Let's talk buttons for a sec. I don't understand how to call a macro. This is how it is done in the chat server. --+|[c][button]Action::!
#Inventory-Arrays [/button][/c] This works fine until I save the macro. After I open the macro again it somehow gets rewritten to... --+|[c][button]Action::! #Inventory-Arrays [/button][/c] Then it doesn't work anymore. How do I get around the ascii return? I know there has to be a simple solution. I just don't see it.
1621941488

Edited 1621943434
David M.
Pro
API Scripter
@Tyler, I didn't try to run your card, but a couple things jumped out after a quick scan: 1) Your left & right sub are using a "/" instead of a "|" delimiter, should be this: --#leftsub|Melee Attack --#rightsub|5’ Reach 2) Your Miss conditional has a typo. Should be -lt (for "less than"), and you typed -1t. This would cause the flow to never branch to the Miss code block, and the Hit block would always run. --?[$AttackDamage.Total] –lt @{target|ac}|Miss EDIT - Could be other issues, not sure. I don't play PF, so double-check the attribute name for Armor Class. Currently using the 5e "ac" attribute for comparisons. For example, if PF has a different attribute like "armorclass" or something then it will have to be changed in the two locations within the scriptcard.
Thanks David, The leftsub and rightsub definitely work now, that is actually an l, not sure why it looks like that but when i went to change it it looks the same for some reason. so i still cant figure that out but I will keep trying
Little help, I need to check which is greater [*S:npcd_str_save] and [*S:npcd_str_mod] and store the greater value in --=strength_save_bonus| in 1 line if I can. Example monsters has a mod of 3 and str save of 0 the I want to store the 3. Example 2 has a mod of 3 but a save of 6 I want to store the 6.  Thanks in advance whom ever can help.  Craven 
1621966272

Edited 1621966662
Andy said: Will M. said: Craven said: How can i call a macro from within scriptcard without using a button. Example I have a macro called longrest and shortrest and I want to make a scriptcard that players select --&chose|?{What type of rest?|Long, |Short, } that will run the correct macro. The macros are stored on a character sheet.  The without a button confuses me as I would generally use the [button] functionality.  You can do all this within a single scriptcard. * Provide a list of options to players (short rest, long rest, ....) each enclosed within an [button]ButtonText::~[CharName]|[MacroName][/button]Something like: !script {{ ... --+|[c][button]Short Rest::~[charname]|SHORT_REST[/button][/c] --+|[c][button]Short Rest::~[charname]|LONG_REST[/button][/c] ... ... }} When the user clicks on the associated button, it should kick off the associated macro. There is also a [sheetbutton], not currently in the Wiki, that has the following syntax: [sheetbutton]ButtonCaption::Character::AbilityMacro[/sheetbutton]   Let's talk buttons for a sec. I don't understand how to call a macro. This is how it is done in the chat server. --+|[c][button]Action::!
#Inventory-Arrays [/button][/c] This works fine until I save the macro. After I open the macro again it somehow gets rewritten to... --+|[c][button]Action::! #Inventory-Arrays [/button][/c] Then it doesn't work anymore. How do I get around the ascii return? I know there has to be a simple solution. I just don't see it. I don't store my macros in the Macros Panel, but use the ability macros area in a dedicated character sheet I named "Mule", which makes it simple for me to backup and move my macros between campaigns.  I give my players rights to control "Mule", which enables them to execute the macros store in it. In script cards, there are 2 button types, [button] & [sheetbutton] that can be employed to run a macro from a character sheet!  They basically do the same thing, but with a little different syntax. Button Syntax:  [button]Caption::Action[/button] Sheet Button Syntax: [sheetbutton]Caption::Character::AbilityMacro[/sheetbutton] Both of these commands should work, assuming you have a character sheet name Mule and an Ability Macro on that sheet called Long-Rest . [button]Take a Long Rest::~Mule|Long-Rest[/button] [sheetbutton]Take a Long Rest::Mule::Long-Rest[/sheetbutton] I tend to use the [button] syntax and not sure why both exist, other than Kurt was trying to make it simpler for us newbies to call Sheet Macros early on.   Finally, there is a 3rd button type [rbutton] or Reentry Button which I absolutely love.  It allows you to basically pause execution of your macro and conditionally call different subroutines based on user selection.  The syntax for that is: [rbutton]caption::branch label;argument[/rbutton] !script {{ --#reentrant|HealingPotionMacro ... --+|[rbutton]Down a Healing Potion::Healing-Potion;[&TokenId]\Regular[/rbutton] --+|[rbutton]Down a Greater Healing Potion::Healing-Potion;[&TokenId]\Greater[/rbutton] --+|[rbutton]Down a Superior Healing Potion::Healing-Potion;[&TokenId]\Superior[/rbutton] --+|[rbutton]Down a Supreme Healing Potion::Healing-Potion;[&TokenId]\Supreme[/rbutton] --X| --:Healing-Potion|   --~Arg|string;split;\;[&reentryval]   --&TokenId|[&Arg1]   --&PotionType|[&Arg2]   --C[&PotionType]|Regular:Regular|Greater:Greater|Superior:Superior|Supreme:Supreme ... RButton only support sending one argument, but I often want to send 2 or more.  As you can see in the code above, I stack all my arguments together, using a backslash as a delimiter, and then split them back out in the reentry routine (Healing-Potion).   Hope this helps
1621968612

Edited 1621969504
Will M. said: Andy said: Will M. said: Craven said: How can i call a macro from within scriptcard without using a button. Example I have a macro called longrest and shortrest and I want to make a scriptcard that players select --&chose|?{What type of rest?|Long, |Short, } that will run the correct macro. The macros are stored on a character sheet.  The without a button confuses me as I would generally use the [button] functionality.  You can do all this within a single scriptcard. * Provide a list of options to players (short rest, long rest, ....) each enclosed within an [button]ButtonText::~[CharName]|[MacroName][/button]Something like: !script {{ ... --+|[c][button]Short Rest::~[charname]|SHORT_REST[/button][/c] --+|[c][button]Short Rest::~[charname]|LONG_REST[/button][/c] ... ... }} When the user clicks on the associated button, it should kick off the associated macro. There is also a [sheetbutton], not currently in the Wiki, that has the following syntax: [sheetbutton]ButtonCaption::Character::AbilityMacro[/sheetbutton]   Let's talk buttons for a sec. I don't understand how to call a macro. This is how it is done in the chat server. --+|[c][button]Action::!
#Inventory-Arrays [/button][/c] This works fine until I save the macro. After I open the macro again it somehow gets rewritten to... --+|[c][button]Action::! #Inventory-Arrays [/button][/c] Then it doesn't work anymore. How do I get around the ascii return? I know there has to be a simple solution. I just don't see it. I don't store my macros in the Macros Panel, but use the ability macros area in a dedicated character sheet I named "Mule", which makes it simple for me to backup and move my macros between campaigns.  I give my players rights to control "Mule", which enables them to execute the macros store in it. In script cards, there are 2 button types, [button] & [sheetbutton] that can be employed to run a macro from a character sheet!  They basically do the same thing, but with a little different syntax. Button Syntax:  [button]Caption::Action[/button] Sheet Button Syntax: [sheetbutton]Caption::Character::AbilityMacro[/sheetbutton] Both of these commands should work, assuming you have a character sheet name Mule and an Ability Macro on that sheet called Long-Rest . [button]Take a Long Rest::~Mule|Long-Rest[/button] [sheetbutton]Take a Long Rest::Mule::Long-Rest[/sheetbutton] I tend to use the [button] syntax and not sure why both exist, other than Kurt was trying to make it simpler for us newbies to call Sheet Macros early on.   Finally, there is a 3rd button type [rbutton] or Reentry Button which I absolutely love.  It allows you to basically pause execution of your macro and conditionally call different subroutines based on user selection.  The syntax for that is: [rbutton]caption::branch label;argument[/rbutton] !script {{ --#reentrant|HealingPotionMacro ... --+|[rbutton]Down a Healing Potion::Healing-Potion;[&TokenId]\Regular[/rbutton] --+|[rbutton]Down a Greater Healing Potion::Healing-Potion;[&TokenId]\Greater[/rbutton] --+|[rbutton]Down a Superior Healing Potion::Healing-Potion;[&TokenId]\Superior[/rbutton] --+|[rbutton]Down a Supreme Healing Potion::Healing-Potion;[&TokenId]\Supreme[/rbutton] --X| --:Healing-Potion|   --~Arg|string;split;\;[&reentryval]   --&TokenId|[&Arg1]   --&PotionType|[&Arg2]   --C[&PotionType]|Regular:Regular|Greater:Greater|Superior:Superior|Supreme:Supreme ... RButton only support sending one argument, but I often want to send 2 or more.  As you can see in the code above, I stack all my arguments together, using a backslash as a delimiter, and then split them back out in the reentry routine (Healing-Potion).   Hope this helps Thank you. This is exactly what I was looking for and very easy to understand. I'm excited to give the rbutton a try. This opens up my development again. My gratitude!
1621971498
timmaugh
Pro
API Scripter
Craven said: Little help, I need to check which is greater [*S:npcd_str_save] and [*S:npcd_str_mod] and store the greater value in --=strength_save_bonus| in 1 line if I can. Example monsters has a mod of 3 and str save of 0 the I want to store the 3. Example 2 has a mod of 3 but a save of 6 I want to store the 6.  Thanks in advance whom ever can help.  Craven  If there is no built-in way to do this in ScriptCards, you can do it with the meta-toolbox (Math, ZeroFrame, SelectManager, and Fetch). If you expect to have the token selected, you can put this on the assignment side of the ScriptCards command where you want to store the greater of the two values: {& math max(@(selected.npcd_str_save), @(selected.npcd_str_mod))} (This assumes Fetch will run before MathOps, which is how it comes pre-configured; if you need to force this order, you'll need to include the construction {&0 fetch, math} somewhere in your macro.) Because Fetch is a metascript and runs *after* Roll20 parses the line but before ScriptCards, you can utilize Roll Queries to return the NPC you'd actually like to read: {& math max(@(?{Pick NPC|Cake|Death}.npcd_str_save),@(?{Pick NPC}.npcd_str_mod))} All of that happens before the message reaches ScriptCards. Also, while you're here... Craven  said: How can i call a macro from within scriptcard without using a button. Example I have a macro called longrest and shortrest and I want to make a scriptcard that players select --&chose|?{What type of rest?|Long, |Short, } that will run the correct macro. The macros are stored on a character sheet.  Your question referenced non-button solutions within ScriptCards. There has been some discussion of various button -solutions within ScriptCards. In case the non-button portion of that request was more important than the within-ScriptCards portion, I can offer the obverse... a non-button solution not within ScriptCards. Read that here ...
1621971800

Edited 1621971920
Kurt J.
Pro
API Scripter
Craven said: Little help, I need to check which is greater [*S:npcd_str_save] and [*S:npcd_str_mod] and store the greater value in --=strength_save_bonus| in 1 line if I can. Example monsters has a mod of 3 and str save of 0 the I want to store the 3. Example 2 has a mod of 3 but a save of 6 I want to store the 6.  Thanks in advance whom ever can help.  Craven  There are a couple of ways to do this: --?[*S:npcd_str_save] -gt [*S:npcd_str_mod]|=strength_save_bonus;[*S:npcd_str_save]|=strength_save_bonus;[*S:npcd_str_mod] is probably the most straightforward (this requires 1.2.5 or later). You could also use the math;max function: --~strength_save_bonus|math;max;[*S:npcd_str_mod];[*S:npcd_str_save] Which works with the current OneClick version of
@Tyler - one of the things I learned the hard way is that not all targets are the same.  The problem with using "ac" in your test is that "ac" is the attribute for non-NPC characters.  NPCs use "npc_ac".  Kurt had a gosub that illustrates a work-around:     --=TargetAC|@{target|npc_ac}     --?[$TargetAC.Total] -gt 0|DoneWithAC     --=TargetAC|@{target|ac}     --:DoneWithAC| This may solve your dilemma.
1621973694
Kurt J.
Pro
API Scripter
Michael C. said: @Tyler - one of the things I learned the hard way is that not all targets are the same.  The problem with using "ac" in your test is that "ac" is the attribute for non-NPC characters.  NPCs use "npc_ac".  Kurt had a gosub that illustrates a work-around:     --=TargetAC|@{target|npc_ac}     --?[$TargetAC.Total] -gt 0|DoneWithAC     --=TargetAC|@{target|ac}     --:DoneWithAC| This may solve your dilemma. With the non-branching conditional changes, this could also be shortened considerably: --?"@{target|npc_ac}" -gt 0|=TargetAC;@{target|npc_ac}|=TargetAC;@{target|ac} The quotes are needed around the npc_ac reference because, for PCs, this will be empty, and --? -gt 0 will fail without something to compare on the left side, but --?"" -gt 0 will be fine.
1621975851

Edited 1622033963
Kurt J.
Pro
API Scripter
ScriptCards 1.2.8a now Available - SelectManager Deferral Support Note : I ninja-updated 1.2.8a on the GIST because I had partially implemented some changes to the distance functions that could potentially impact existing scripts. I backed those out of 1.2.8a, so if you have already downloaded it, it is a good idea to re-grab it. Following some discussion between timmaugh and Will M and a suggestion from timmaugh that stemmed from that, I've added support for a SelectManager deferral character in --@ (api call) commands ( available on the GIST ). This means you can use {^& ... } in your --@ statements, and the ^ will be stripped out so that SelectManager will process the token when the API is called instead of when ScriptCards itelf is called. For example: !script {{ --@token-mod|{^& select Quej Gr'stra} _on showname }} With SelectMangager and Token-Mod installed, this will turn on the nameplate for a character named "Quej Gr'stra" without the need for that character to be selected.
1622039341

Edited 1622039706
My Dying and Stabilized macros using purchased Marker Pack RPG Condition Markers v2.  Dying !token-mod {{ --set statusmarkers|path-dying|dd-unconscious|dd-prone }} !script {{ --#title|Condition Dying --#sourceToken|@{selected|token_id} --#leftsub|@{selected|token_name} --#emoteText|@{selected|token_name} Condition set. --#titlecardbackground|#990000 --#titleFontColor|#FFFFFF --#evenrowbackground|#B6AB91 --#oddrowbackground|#CEC7B6 --#emoteBackground|#FFFFFF --#buttonTextColor|#000000 --#buttonBackground|#transparent --#buttonBorderColor| --#buttonFontSize| --#buttonFontFace| --+[sm width=25px]path-dying[/sm]|[b]You are Dying[/b] --+[sm width=25px]dd-unconscious[/sm]|[b]Unconscious[/b] • Any attack that hits the creature is a critical hit if the attacker is within 5 feet of the creature. --+[sm width=25px]dd-prone[/sm]|[b]Prone[/b] • The creature drops whatever it’s holding and falls prone. --+[sm width=25px]path-bleeding[/sm]|[b]Bleeding out![/b] • If at 0 HP on you next turn make a death save vs DC 10. • 3 Fails and you are dead • When you make a death saving throw and roll a 1 on the d20, it counts as two failures. If you roll a 20 on the d20, you regain 1 hit point. --+Take Damage:| • Take damage and its 1 failure. If the damage is a critical you take 2 failures. --+|[c] [button]Click Here for Death Save::~@{selected|character_name}|3.01-DeathSave[/button] [/c] }} Stable !token-mod {{ --set statusmarkers|-path-dying|-dd-unconscious|-dd-prone }} !script {{ --#title|Condition Dying --#sourceToken|@{selected|token_id} --#leftsub|@{selected|token_name} --#emoteText|@{selected|token_name} Condition set. --#titlecardbackground|#990000 --#titleFontColor|#FFFFFF --#evenrowbackground|#B6AB91 --#oddrowbackground|#CEC7B6 --#emoteBackground|#FFFFFF --+[sm width=25px]path-dying[/sm]|[b]You are no longer Dying[/b] --+[sm width=25px]dd-unconscious[/sm]|[b]Unconscious[/b] • You are still unconscious unless you have been healed and have at least 1 hp or more. --+[sm width=25px]dd-prone[/sm]|[b]Prone[/b] • A prone creature’s only movement option is to crawl, unless it stands up and thereby ends the condition. To get up you need to use 15' of your movement. --+[sm width=25px]path-bleeding[/sm]| • No longer Bleeding and should rest your death Save. }} Anyone know of a macro to reset the death saves for 5e OGL sheet?
The documentation for the sheet says it you can have it auto reset if you turn it on.   !deathsavetracking on/off/quiet  - Automatically ticks off successes and failures when death saves are rolled, clearing on death, stabilization, or hp recovery Down in the OGL code for the sheet - I found this for the Death Saves area: <div class="subcontainer" style="float: right;">                     <div class="row-container">                         <span class="label" data-i18n="successes-u">SUCCESSES</span>                         <input type="checkbox" name="attr_deathsave_succ1">                         <input type="checkbox" name="attr_deathsave_succ2">                         <input type="checkbox" name="attr_deathsave_succ3">                     </div>                     <div class="row-container">                         <span class="label" data-i18n="failures-u">FAILURES</span>                         <input type="checkbox" name="attr_deathsave_fail1">                         <input type="checkbox" name="attr_deathsave_fail2">                         <input type="checkbox" name="attr_deathsave_fail3">                     </div>                     <button type="roll" name="roll_death_save" style="margin-top: 6px;" value="@{wtype}&{template:simple} {{rname=^{death-save-u}}} {{mod=@{death_save_bonus}}} {{r1=[[@{d20}+@{death_save_bonus}[MOD]@{globalsavingthrowbonus}]]}} {{normal=1}} {{global=@{global_save_mod}}} @{charname_output} {{licensedsheet=@{licensedsheet}}}" data-i18n="death-saves-u">DEATH SAVES</button> I don't recall seeing an attribute named attr_deathsave_succ1in the list of attributes, but you may be able to use the SetAttr api script to adjust these values.  
1622043110
David M.
Pro
API Scripter
Good find, Will. If you toggle some of the death save "successes" and "failures" radio buttons in a character sheet and run the following, you can see what the current values are: Save 1 state: @{selected|deathsave_succ1} Save 2 state: @{selected|deathsave_succ3} Save 3 state: @{selected|deathsave_succ3} Fail 1 state: @{selected|deathsave_fail1} Fail 2 state: @{selected|deathsave_fail2} Fail 3 state: @{selected|deathsave_fail3} However, I'm not sure if changing those attributes from "on" to "0" will actually update the red dot on the character sheet or not. That is probably handled with a sheet worker, and could depend on if the buttons trigger the attribute change or the attribute change triggers the buttons, or both. 
Will M. said: The documentation for the sheet says it you can have it auto reset if you turn it on.   !deathsavetracking on/off/quiet  - Automatically ticks off successes and failures when death saves are rolled, clearing on death, stabilization, or hp recovery Down in the OGL code for the sheet - I found this for the Death Saves area: <div class="subcontainer" style="float: right;">                     <div class="row-container">                         <span class="label" data-i18n="successes-u">SUCCESSES</span>                         <input type="checkbox" name="attr_deathsave_succ1">                         <input type="checkbox" name="attr_deathsave_succ2">                         <input type="checkbox" name="attr_deathsave_succ3">                     </div>                     <div class="row-container">                         <span class="label" data-i18n="failures-u">FAILURES</span>                         <input type="checkbox" name="attr_deathsave_fail1">                         <input type="checkbox" name="attr_deathsave_fail2">                         <input type="checkbox" name="attr_deathsave_fail3">                     </div>                     <button type="roll" name="roll_death_save" style="margin-top: 6px;" value="@{wtype}&{template:simple} {{rname=^{death-save-u}}} {{mod=@{death_save_bonus}}} {{r1=[[@{d20}+@{death_save_bonus}[MOD]@{globalsavingthrowbonus}]]}} {{normal=1}} {{global=@{global_save_mod}}} @{charname_output} {{licensedsheet=@{licensedsheet}}}" data-i18n="death-saves-u">DEATH SAVES</button> I don't recall seeing an attribute named attr_deathsave_succ1in the list of attributes, but you may be able to use the SetAttr api script to adjust these values.   That might work but I think it would re-set it for everyone. I will keep looking. I try to have my players go back to the character sheet as little as possible because they play on small laptop screen and it hard to have the sheet open and see the map and tokens. I use 2 32" curved monitors so I am good.  
1622046102
timmaugh
Pro
API Scripter
Craven, I think the idea would be that you would use ChatSetAttr to set the attribute from a macro, and that would be limited to the character you wanted to target (or, using forselected, a number of characters that you chose). One other complication to be aware of might be something related to this post detailing a problem with sheetworkers on the live server, and how it handles checkboxes on the character sheet.
Is there a place where people could post the different ScriptCards they made that could be easily organized?  I feel like we might be redoing a bunch of work.
1622055979
David M.
Pro
API Scripter
Yep! It's a newish thread, but you can find some examples right here . Note that the linked thread is intended for sharing completed working scriptcards. If you are looking for support, it's best to keep those questions on the current thread.
1622059172

Edited 1622829348
Kurt J.
Pro
API Scripter
ScriptCards version 1.2.9 Now Available I've posted the latest update to ScriptCards over on the GIST . Mostly adding requested features, but a couple of other new things as well. Here is what is new/changed: Bug Fix  - The "after" string function will now omit the specified separator from the value it returns. Formatting - No functional change, but apparently at some point I hilighted the whole script in VSCode and hit tab a couple of times and indented everything. I fixed that :) I've also begin adding more verbose comments throughout the code. That will continue as a work in progress. Custom VFX for Point effects  - The relatively new "--Vpoint" effect statement now supports custom FX. New Distance Functions  - Two new distance functions are available. "euclideanpixel" will return the raw pixel distance between two tokens (without dividing by 70). "euclideanlong" will return the unit distance, but divides the result by 70 AFTER calculating the distance to reduce rounding errors over very long ranges. New String Functions  - "replaceall" will replace all occurrences of the search string in the source text (replace replaces only the first occurrence). "trim" will remove spaces from the beginning and end of the string.     ex: --~newString|string;replaceall;w;m;lets eat some w&ws     ex: --~newString|string;trim;   HELLO THERE    Behavior Change  - I have added a new setting value called "executionlimit", with a default of 30000. W hen processing a script, the number of lines executed is tracked. If that number exceeds "executionlimit", ScriptCards will log an error message to the API console and abort execution of the script. If you need to execute more than 30000 lines of code, just set the parameter higher for that particular script (i.e. : --#executionlimit|100000). The intent here is to prevent scripting logic errors from crashing the sandbox with an infinite loop. My lightningbolt and fireball macros in VERY crowded areas don't hit the 30000 limit, so it should be good for most scripts. I can always up the default if there are issues. Deferred Meta Script Resolution  - I mentioned this in 1.2.8a, but I've expanded on it a bit. As some more detail, when calling another API script with ScriptCards via the --@ statement, it is now possible to include some meta script (SelectManager, Fetch) by inserting a deferral character into the meta call. For example, if I want to have ScriptCards call TokenMod as if the token for "Quej Gr'stra" (yes, I let Roll20 name my test NPCs) I could use something like this:   --@token-mod|{^& select Quej Gr'stra} _on showname The "^" in between { and & will prevent SelectManager from seeing the call when the ScriptCard script is processed, but the --@ statement will remove the deferral character so the command that will be sent by ScriptCards is:   !token-mod {& select Quej Gr'stra} --on showname With the deferral character removed, SelectManager will see the {& select ...} and do its magic. The deferral character is a setting that can be changed:   --#deferralcharacter|% Will make % the deferral character for future --@ statements in the running script. There are currentl three supported Meta script structures: {^&...} for SelectManager, @^(...) and *^(...) for fetch, where the ^ in the structures here represents the placement of the deferral character. Please note that while I have tested the SelectManager deferrals, I have not done extensive testing with the Fetch deferrals, so if you run into issues let me know and i'll correct them.
1622071945
timmaugh
Pro
API Scripter
Kurt J. said: Deferred Mega Script Resolution  - I mentioned this in 1.2.8a, but I've expanded on it a bit. As some more detail, when calling another API script with ScriptCards via the --@ statement, it is now possible to include some meta script (SelectManager, Fetch) by inserting a deferral character into the meta call. For example, if I want to have ScriptCards call TokenMod as if the token for "Quej Gr'stra" (yes, I let Roll20 name my test NPCs) I could use something like this:   --@token-mod|{^& select Quej Gr'stra} _on showname The "^" in between { and & will prevent SelectManager from seeing the call when the ScriptCard script is processed, but the --@ statement will remove the deferral character so the command that will be sent by ScriptCards is:   !token-mod {& select Quej Gr'stra} --on showname With the deferral character removed, SelectManager will see the {& select ...} and do its magic. The deferral character is a setting that can be changed:   --#deferralcharacter|% Will make % the deferral character for future --@ statements in the running script. There are currentl three supported Meta script structures: {^&...} for SelectManager, @^(...) and *^(...) for fetch, where the ^ in the structures here represents the placement of the deferral character. Please note that while I have tested the SelectManager deferrals, I have not done extensive testing with the Fetch deferrals, so if you run into issues let me know and i'll correct them. w00t! That's awesome, Kurt! Thanks for working this in!
1622075847

Edited 1622075859
Does Scriptcards handle templates like Powercards does?
Trying to use Kurt's lightning bolt as a dragonborn's breath weapon but I can't get the visuals to work.  Am I missing something?  I am upgraded to the latest version of scriptcards. !script {{   --/|Lightning Breath script. Can be changed to other line-based spells by updating these parameters:   --&spellName|Lightning Breath      --/|Prompt for the spell level. Update this to account for the minimum level of the spell   --=SpellLevel|1   --&spellDamageDieType|6   --&damageType|lightning   --&saveType|dexterity      --/|Source Token is the caster, and target token is the "end of the line". Can be a non-creature (no represents) token.   --#sourcetoken|@{selected|token_id}   --#targettoken|@{target|token_id}   --/|Note: because the spell will be cast at a min level of 3, we use 5 here to get the total dice (5+3=8)   --C[*S:level]|1:>HowManyDice;2|2:>HowManyDice;2|3:>HowManyDice;2|4:>HowManyDice;2|5:>HowManyDice;2|6:>HowManyDice;3|7:>HowManyDice;3|8:>HowManyDice;3|9:>HowManyDice;3|10:>HowManyDice;3|11:>HowManyDice;4|12:>HowManyDice;4|13:>HowManyDice;4|14:>HowManyDice;4|15:>HowManyDice;4|16:>HowManyDice;5|17:>HowManyDice;5|18:>HowManyDice;5|19:>HowManyDice;5|20:>HowManyDice;5   --:HowManyDice|   --&spellL0DamageDice|[%1%]      --/|Get all of the tokens on the page so we can cache their positions   --~|array;pagetokens;alltokens;@{target|token_id}   --#leftsub|Save DC @{selected|spell_save_dc}   --#rightsub|Dragonborn Ability   --#title|[&spellName]   -->Available|   --@roll20AM|_audio,play,nomenu|Thunder   --#emoteText|@{selected|token_name} inhales deeply and unleashes her lightning breath.   --/|Calculate damage based on spell slot.   --=DamageDice|[&spellL0DamageDice]   --=Damage|[$DamageDice.Total]d[&spellDamageDieType]   --=HalfDamage|[$Damage.Total] \ 2   --=DoubleDamage|[$Damage.Total] * 2   --=QuarterDamage|[$Damage.Total] \ 4   --/|Since we want to be able to hover over a roll and see the dice details, output the rolled damage at the   --/|top of the card. If all critters make their save, the half damage roll won't contain the details.   --+|[c][b]Damage Roll: [/b][$Damage][/c]   --+|       --/|Create an array to hold the tokens that are intersected by the line.   --~|array;define;tokensHit;      --/|Call the "checkForTokenHits" subroutine. The passed parameter will be the per-space VFX. Leave blank for none.   -->checkForTokenHits|burn-holy   --/|The first item in the array will be a blank dummy item, so remove it.   --~|array;removeat;tokensHit;0      --/|Loop through the tokensHit tokens and roll saves for each one and apply damage   --~tokenid|array;getfirst;tokensHit   --?[&tokenid] -eq ArrayError|endOutput   --:loopDisplay|   --=SaveRoll|1d20 + [*[&tokenid]:[&saveType]_save_bonus]   --/|Compare the save roll to the save DC and either apply full or half damage   --?"[*[&tokenid]:npc_immunities]" -inc "[&damageType]"|Immune   --?"[*[&tokenid]:npc_resistances]" -inc "[&damageType]"|Resistant   --?"[*[&tokenid]:npc_vulnerabilities]" -inc "[&damageType]"|Vulnerable   --?[$SaveRoll.Total] -lt @{selected|spell_save_dc}|>ApplyDamageAlterbars;[&tokenid];1;-[$Damage.Total]|>ApplyDamageAlterbars;[&tokenid];1;-[$HalfDamage.Total]   --?[$SaveRoll.Total] -ge @{selected|spell_save_dc}|madeSave   --/|Here are various damage applications if the creature is immune, resistant, or vulnerable. In some cases, we will reuse output lines,   --/|for example, a resistant creature that fails its save will jump to "madeSave", since that is the correct damage amount. (half), while   --/|a vulnerable creature that makes its save will jump to "FailedSave" since that will be normal damage.   --/|Output a line for a failed saving throw (we will also jump here for a vulnerable creature that MAKES its save)   --:FailedSave|   --+[*[&tokenid]:t-name]:|Save [$SaveRoll] [r][$Damage] [&damageType][/r]   --^afterSave|      --:Immune|   --+[*[&tokenid]:t-name]:|is not effected by the spell!   --^afterSave|   --:Resistant|   --?[$SaveRoll.Total] -lt @{selected|spell_save_dc}|>ApplyDamageAlterbars;[&tokenid];3;-[$HalfDamage.Total]|>ApplyDamageAlterbars;[&tokenid];3;-[$QuarterDamage.Total]   --?[$SaveRoll.Total] -lt @{selected|spell_save_dc}|madeSave   --+[*[&tokenid]:t-name]:|Save [$SaveRoll] [r][$QuarterDamage] [&damageType][/r]   --^afterSave|   --:Vulnerable|   --?[$SaveRoll.Total] -lt @{selected|spell_save_dc}|>ApplyDamageAlterbars;[&tokenid];3;-[$DoubleDamage.Total]|>ApplyDamageAlterbars;[&tokenid];3;-[$Damage.Total]   --?[$SaveRoll.Total] -ge @{selected|spell_save_dc}|FailedSave   --+[*[&tokenid]:t-name]:|Save [$SaveRoll] [r][$DoubleDamage] [&damageType][/r]   --^afterSave|   --/|Output a line for a successful saving throw   --:madeSave|   --+[*[&tokenid]:t-name]:|Save [$SaveRoll] [r][$HalfDamage] [&damageType][/r]   --:afterSave|   --~tokenid|array;getnext;tokensHit   --?[&tokenid] -ne ArrayError|loopDisplay   --:endOutput|      --X|      --:ApplyDamageTokenmod|Parameters are tokenid;bar#;amount   --@token-mod|_ignore-selected _ids [%1%] _set bar[%2%]_value|[%3%]   --<|       --:ApplyDamageAlterbars|Parameters are tokenid;bar#;amount   --@alter|_target|[%1%] _bar|[%2%] _amount|-[%3%] _show|none   --<|      --:checkForTokenHits|Y as %1% for VFX   -->createTokenLookup|   --=X1|[*S:t-left] \ 70  --=Y1|[*S:t-top] \ 70   --=X2|[*T:t-left] \ 70  --=Y2|[*T:t-top] \ 70   --?[$X1] -lt [$X2]|=SX;1|=SX;-1   --?[$Y1] -lt [$Y2]|=SY;1|=SY;-1   --=DX|[$X2] - [$X1] {ABS}   --=DY|[$Y2] - [$Y1] {ABS}   --=ERR|[$DX] - [$DY]   --=Y|[$Y1.Total]       --=X|[$X1.Total]   --%L|1;50 -->checkTokens|[$X];[$Y] --/|IF we passed a visual effect specifier in %1%, create a point VFX in the square --?"X[%1%]X" -ne "XX" |[       --=VX|[$X] * 70 + 35      --=VY|[$Y] * 70 + 35      --vpoint|[$VX] [$VY] [%1%] --]| --?[$X.Total] -eq [$X2.Total] -and [$Y.Total] -eq [$Y2.Total]|%! --=E2|[$ERR.Total] * 2 --=NDY|[$DY] {NEGATE} --?[$E2] -gt [$NDY]|[  --=ERR|[$ERR] - [$DY]  --=X|[$X] + [$SX]  --]| --?[$E2] -lt [$DX]|[  --=ERR|[$ERR] + [$DX]  --=Y|[$Y] + [$SY]  --]|   --%|   --/|Remove the caster from the list of hit tokens   --~|array;remove;tokensHit;@{selected|token_id}   --<|   --/|Reads the variables created by createTokenLookup to find any tokens that occupy a given space.   --:checkTokens|x;y   --?"X[&tok[%1%]-[%2%]]X" -ne "XX"|[   --~split|string;split;!;[&tok[%1%]-[%2%]]   --%P|1;[$splitCount.Total];1     --=var|split[&P] --?"X[&[$var.RollText]]X" -eq "XX"|% --~exists|array;indexof;tokensHit;[&[$var.RollText]]     --?[&exists] -ne ArrayError|skipAdd --?[&[$var.RollText]] -eq ArrayError|skipAdd     --~|array;add;tokensHit;[&[$var.RollText]] --:skipAdd|   --%|   --<|      --/|Creates a series of string variables with names like 'tok12-15' which represent the various squares that are   --/|occupied by tokens on the page. Handle 1x1, 2x2, and 3x3 tokens by simply adding extra squares in the appropriate   --/|pattern around the center point location. The result is that if there are two tokens at 12,15, the tok12-15 string   --/|will contain something like "-asln34njfn2nafd!-sdnfklaserfs" (IDs separated by exclamation points) that we can use to   --/|quickly evaluate hits by essentially asking "what is in square 12x15" by just reading the variable.   --:createTokenLookup|   --~tokenid|array;getfirst;alltokens   --:tokenSetupLoop|     --?[&tokenid] -eq ArrayError|endSetupLoop     --=tLeft|[*[&tokenid]:t-left] - 1 \ 70 --=tTop|[*[&tokenid]:t-top] - 1 \ 70 --=tWidth|[*[&tokenid]:t-width] --?[$tWidth] -eq 70|[    --&tok[$tLeft]-[$tTop]|+[&tokenid]!   --/+[*[&tokenid]:character_name]|At [$tLeft],[$tTop] : [&tok[$tLeft.Total]-[$tTop.Total]] --]| --?[$tWidth] -eq 140|[    --=NX|[$tLeft] + 1   --=NY|[$tTop] + 1   --&tok[$tLeft]-[$tTop]|+[&tokenid]!   --&tok[$tLeft]-[$NY]|+[&tokenid]!   --&tok[$NX]-[$tTop]|+[&tokenid]!   --&tok[$NX]-[$NY]|+[&tokenid]! --]| --?[$tWidth] -eq 210|[    --=PX|[$tLeft] - 1   --=PY|[$tTop] - 1   --=NX|[$tLeft] + 1   --=NY|[$tTop] + 1     --&tok[$tLeft]-[$tTop]|+[&tokenid]!     --&tok[$PX]-[$PY]|+[&tokenid]!   --&tok[$tLeft]-[$PY]|+[&tokenid]!   --&tok[$NX]-[$PY]|+[&tokenid]!     --&tok[$PX]-[$tTop]|+[&tokenid]!   --&tok[$NX]-[$tTop]|+[&tokenid]!     --&tok[$PX]-[$NY]|+[&tokenid]!     --&tok[$tLeft]-[$NY]|+[&tokenid]!     --&tok[$NX]-[$NY]|+[&tokenid]! --]| --~tokenid|array;getnext;alltokens --^tokenSetupLoop| --:endSetupLoop|   --<|   --:Available|   --=Available|[*S:class_resource]   --?[$Available] -eq 0|OutofBreath   --=Breathleft| [$Available] - 1   --@setattr|_charid [*S:character_id] _class_resource|[$Breathleft] _silent   --<|   --:OutofBreath|   --#emoteText|@{selected|token_name} inhales deeply and attempts her breath weapon, but she is all out of breath.   --X|    }}
1622108342
Kurt J.
Pro
API Scripter
Justin G. said: Does Scriptcards handle templates like Powercards does? It does now, but templates were really a workaround in PowerCards for not being able to do any real processing/scripting.
1622108437
Kurt J.
Pro
API Scripter
Justin G. said: Trying to use Kurt's lightning bolt as a dragonborn's breath weapon but I can't get the visuals to work.  Am I missing something?  I am upgraded to the latest version of scriptcards. When using --Vpoint, make sure the player ribbon is on the page your are viewing, or set the --#activepage| setting. The oher --v commands accept tokens so pull the page from them, but since point doesn't it uses the activepage or (if not set) the player ribbon page.
Is there a way to incorporate a sheet's roll template into a scriptcard?  How about apply a texture or image to the title bar?
1622153740

Edited 1622154804
Kurt J.
Pro
API Scripter
I got a question on how to do the equivalent of --format (from PowerCards) in ScriptCards. Here is the way I do it. Create a macro for each character in the game. In that macro, specify the colors, fonts, etc. you want, so essentially it is a template script. End the script with --ssettings|@{selected|character_name}. For example, here are three different scripts. I would have a different character selected when running each one: !script {{ --#title|Testing - Run with Character 1 --#titlecardbackground|#a32cc4 --#oddrowbackground|#e39ff6 --#evenrowbackground|#b65fcf --+Odd Row|Odd Row --+Even Row|Even Row --ssettings|@{selected|character_name} }} !script {{ --#title|Testing - Run with Character 2 --#titlecardbackground|#a32cc4 --#oddrowbackground|#33ee33 --#evenrowbackground|#99FF99 --+Odd Row|Odd Row --+Even Row|Even Row --ssettings|@{selected|character_name} }} !script {{ --#title|Testing - Run with Character 3 --#titlecardbackground|#bda55d --#oddrowbackground|#dfc98a --#evenrowbackground|#e3b778 --+Odd Row|Odd Row --+Even Row|Even Row --ssettings|@{selected|character_name} }} This saves three different settings groups named after the character that was selected when the macro was run. Now, in "generic" macros that can be run by any player, include the following line: --lsettings|@{selected|character_name} which will load the settings saved for that character. For example: !scriptcard {{ --lsettings|@{selected|character_name} --#title|Longsword --#leftsub|Melee Attack --#sourceToken|@{selected|token_id} --#targetToken|@{target|token_id} --#emoteText|@{selected|token_name} attacks @{target|token_name} --=TargetAC|@{target|npc_ac} --?[$TargetAC.Total] -gt 0|DoneWithAC --=TargetAC|@{target|ac} --:DoneWithAC| --=AttackRoll|1d20 + @{selected|strength_mod} [STR] + @{selected|pb} [PROF] --+Attack|@{selected|token_name} rolls [$AttackRoll] vs AC [$TargetAC]. --?[$AttackRoll.Base] -eq 20|Crit --?[$AttackRoll.Base] -eq 1|Fumble --?[$AttackRoll.Total] -ge [$TargetAC.Total]|Hit --+Miss|The attack missed. --^Final| --:Fumble| --+Fumble!|The attack went horribly wrong. --^Final| --:Hit| --=Damage|1d8 + @{selected|strength_mod} [STR] --+Hit!|The attack hit @{target|token_name} for [$Damage] slashing damage. --@alter|_target|@{target|token_id} _bar|3 _amount|-[$Damage] --^Final| --:Crit| --=Damage|1d8 + @{selected|strength_mod} [STR] + 1d8 [CRIT] --+Critical Hit!|The attack hit @{target|token_name} for [$Damage] slashing damage. --@alter|_target|@{target|token_id} _bar|3 _amount|-[$Damage] --:Final| }} I've bolded the only update I made to the Longsword macro to make it load the saved format for whatever character ran it. Loading a non-existent format won't cause and problems - it will just use the default settings. Here is the longsword macro run for the three characters above (note that I do not claim to have picked GOOD colors :)) Also note that Title is a setting, so when I took these screenshots I had --l after --# for title. I moved it around in the script above :)
I was hoping to simplify basic attacks with templates.  Thanks. Kurt J. said: Justin G. said: Does Scriptcards handle templates like Powercards does? It does now, but templates were really a workaround in PowerCards for not being able to do any real processing/scripting.
I knew I was screwing something up.  Thanks. Kurt J. said: Justin G. said: Trying to use Kurt's lightning bolt as a dragonborn's breath weapon but I can't get the visuals to work.  Am I missing something?  I am upgraded to the latest version of scriptcards. When using --Vpoint, make sure the player ribbon is on the page your are viewing, or set the --#activepage| setting. The oher --v commands accept tokens so pull the page from them, but since point doesn't it uses the activepage or (if not set) the player ribbon page.
1622164304
Kurt J.
Pro
API Scripter
Justin G. said: I was hoping to simplify basic attacks with templates.  Thanks. Kurt J. said: Justin G. said: Does Scriptcards handle templates like Powercards does? It does now, but templates were really a workaround in PowerCards for not being able to do any real processing/scripting. Sorry, that should have said not instead of now ;)
I have this macro for bless remove and want to add  --@setattr|_charid [*S:character_id] _repeating_savemod_$0_global_save_active_flag|0 _silent to my powercard but it need to for use the 3 targets and can't figure out the syntax.  The above work for the single source with the script but I don't know how to change it for the 3 targets. Any ideas?  !token-mod --ids @{target|1|token_id} @{target|2|token_id} @{target|3|token_id} --set statusmarkers|-x-blessed !script {{ --#title|Condition Blessed --#leftsub|@{target|1|character_name}, @{target|2|character_name}, @{target|3|character_name} --#titlecardbackground|#990000 --#evenrowbackground|#B6AB91 --#oddrowbackground|#CEC7B6 --+[sm width=25px]x-blessed[/sm]|[b] You no longer hold favor with the Gods and your blessing has faded![/b] --+| }}
1622212288
timmaugh
Pro
API Scripter
You are hard-coding three targeting calls, but you don't want to hard-code three ChatSetAttr statements, each getting a different target token id? Well, you can do it in a single line with meta-scripts... in this case SelectManager, ZeroFrame, and Fetch:  --@forselected(!)|setattr _charid @!(selected.represents) _repeating_savemod_$0_global_save_active_flag|0 _silent {^& select @{target|1|token_id}, @{target|2|token_id}, @{target|3|token_id}} That relies on the built-in ScriptCards deferral character Kurt just added (^) to break up the {& select...} syntax token. That means that those tokens will be added to the downstream message ( forselected ). It also utilizes the ability to declare a deferral character for forselected so that certain constructions aren't detected until the downstream-downstream messages. In other words, you have a chain of three messages: ScriptCards ====> forselected ========>setattr Currently, your top-level SC will not have an array of selected tokens, since you're including targeting statements. When it runs forselected, it will un-escape the {& select ...} syntax token, so that for *that* message, you will now have an array of 3 tokens selected. For each of them, it will send a command to ChatSetAttr and un-escape the command line each time so that the Fetch construction of @(selected.represents) is detected. (BTW, if your repeating element is not always the first item in that list... by this point you've included Fetch, so you could use a Fetch construction to retrieve it by pattern matching, ad hoc in those last ChatSetAttr calls.)
1622213724

Edited 1622213798
I am trying to create a skill roll card and I am having trouble pulling in values.  What I currently have is a card that set an attribute with a button and goes to a separate macro to run the skill.   !scriptcard {{ --sourceToken|@{selected|token_id} --#titlefontsize|1.8em --#buttonfontsize|medium --#title|Skill Name Here --&Skill|@{selected|ActiveSkill} --+Skill:|[&Skill] --=Modifier|?{Modifier?|None,0|Minor Bonus,2|Major Bonus,5|Minor Penalty,-2|Major Penalty,-5} --+Modifier|[$Modifier] --=DC|?{DC:|} --+DC:|[$DC] --=SkillCheck|1d20 [Roll] + @{selected|[&Skill]} [Skill] --+Skill Check:|[$SkillCheck] }} I thought about creating two attributes with one button but I can't figure out how to have setattr adjust two attributes off the same button. I know the problem is trying to pull &Skill into the roll variable but I really can't figure out how to make it work.  I could do it pretty easily in one card with a roll query, but my players have a think for buttons. Any help would be appreciated.
I need some help understanding the --i command.  Kurt created a great magic missile script that I am trying to modify for creating mass healing word.  In his script he uses the --i command in the following way:   -->BuildAndAskTargets|[$MissileCount.Total] [...]   --:BuildAndAskTargets|     --&TargetString|     --=targetCount|1   --:TargetLoop|     --&TargetString|+t;target[$targetCount.Total];Missile [$targetCount.Total] Target     --=targetCount|[$targetCount.Total] + 1     --?[$targetCount.Total] -le [%1%]|>AddSeparator     --?[$targetCount.Total] -le [%1%]|TargetLoop     --iPlease click the button below to select magic missile targets. The same target can be selected multiple times;Select [%1%] Targets|[&TargetString]   --/|   --<| As I understand it, the script calls the gosub, passing a count for the missiles, the sub then nulls out [&TargetString], starts targetCount at 1 then begins the loop.  The loop opens &TargetString with "+t;target[$targetCount.Total];Missile [$targetCount.Total] Target", adds 1 to the counter, plugs in the separator "||" if the loop is not completed and returns to add the next in the sequence until the last target/missile is selected.  The confusion arises with the placement of the --i command, the contents of [&TargetString] and its later use.  According to the program logic, there is NO outside input inside the loop.  Appearances are that the --i command comes into play AFTER the loop is completed and then REPLACES the contents of [&TargetString] with the first target selected in the --i command then, rather than looping for another target, drops to the return from gosub command taking it out of the procedure. (I have no idea what the purpose of the comment command was...)  This is, of course, not what happens when the script is played. I get it that the --i command is seen by the parser first regardless of its sequence in the script but that just complicates things further as the loop would seem to overwrite any entries from the --i command in [&TargetString]. Somehow --i knows how many t-type tokens to wait for (with the only indication being inside the button element], adds their token_id to [&TargetString] in a manner that is orchestrated by the loop without the two interfering with each other.  All of this is even further muddled by the fact that the script uses the string to fire the missiles despite the fact that [&TargetString] is never called again outside the gosub nor is any parameter passed out of the gosub upon the return.  I have read and reread the wiki and either am too stupid to understand it (most probable reason) or missing some important info on the procedure. Is there a way to set up and explain an example that might make understanding the process of the --i command more understandable? Help!
1622219973
timmaugh
Pro
API Scripter
Brien V.  said: I am trying to create a skill roll card and I am having trouble pulling in values.  What I currently have is a card that set an attribute with a button and goes to a separate macro to run the skill.   !scriptcard {{ --sourceToken|@{selected|token_id} --#titlefontsize|1.8em --#buttonfontsize|medium --#title|Skill Name Here --&Skill|@{selected|ActiveSkill} --+Skill:|[&Skill] --=Modifier|?{Modifier?|None,0|Minor Bonus,2|Major Bonus,5|Minor Penalty,-2|Major Penalty,-5} --+Modifier|[$Modifier] --=DC|?{DC:|} --+DC:|[$DC] --=SkillCheck|1d20 [Roll] + @{selected|[&Skill]} [Skill] --+Skill Check:|[$SkillCheck] }} I thought about creating two attributes with one button but I can't figure out how to have setattr adjust two attributes off the same button. I know the problem is trying to pull &Skill into the roll variable but I really can't figure out how to make it work.  I could do it pretty easily in one card with a roll query, but my players have a think for buttons. Any help would be appreciated. I think what you're running into is that the @{selected|...} construction is being detected at the first pass of the macro (before ScriptCard can populate that data for you). It resolves before SC receives the message, and at that point, SC hasn't replaced that text for the value. You can use a Fetch construction to solve this, as it allows you to leverage Roll20 attribute retrievals within the Fetch construction:  @(selected.@{selected|ActiveSkill}) That becomes... @(selected.JazzHands) ...by the time Fetch sees it, which becomes... 15 ...by the time it reaches ScriptCards. (That's one heckuva JazzHands skill, I must say.) Fetch is available in the 1-click.
1622220942
timmaugh
Pro
API Scripter
Michael C. said: As I understand it, the script calls the gosub, passing a count for the missiles, the sub then nulls out [&TargetString], starts targetCount at 1 then begins the loop.  The loop opens &TargetString with "+t;target[$targetCount.Total];Missile [$targetCount.Total] Target", adds 1 to the counter, plugs in the separator "||" if the loop is not completed and returns to add the next in the sequence until the last target/missile is selected.  The confusion arises with the placement of the --i command, the contents of [&TargetString] and its later use.  According to the program logic, there is NO outside input inside the loop.  Appearances are that the --i command comes into play AFTER the loop is completed and then REPLACES the contents of [&TargetString] with the first target selected in the --i command then, rather than looping for another target, drops to the return from gosub command taking it out of the procedure. (I have no idea what the purpose of the comment command was...)  Targeting only happens (those syntax structures are only detected and asked for) at the top level of a macro running... you send the message the Roll20 parser detects the formations and comes back to you to ask for the tokens to target. They don't work if the API sends the targeting call since there is no player to go back to -- the API sent the message. Effectively, that is the problem of ScriptCards building a Targeting list ad hoc and then sending it to chat. That is an API sending the chat message -- there is no one to go back to. To get around this, you build the number of targeting statements you want, and the macro puts those into the command line for a chat button. The chat button, when clicked, starts a new message. Since a person clicks that button, that message allows for those Targeting statements to be resolved. In effect, the loop isn't getting outside input for every answer of the Targeting calls... the loop is building the list of Targeting calls *to ask for*... but that doesn't happen until you click the button. Does that make sense?
@tim - Um, well, no.  I think I lack some architecture knowledge here. The API runs outside the chat then sends information to the chat where the actual "calculations" are performed by Roll20 internal programming? The submission to the chat is the last function that the API can perform as there is no method of returning to the API to complete any further processes?  So, here the API creates a list of, say 6, open string variables then passes it to the chat to ask for information to put in the variables through the --i command which is subsequently processed by the chat? So, in reality, the --i command is the last command performed by the chat/script?  (Regardless of its placement in the script?)  So the --i statement knows how many times to ask because the loop has performed that many operations, formatted them and forwards filling the string variable to the chat?  Ok, I think I get it.  Maybe.  Sort of. Ok, so I tried to modify Kurt's script to only ask for token ids to process:  --:BuildAndAskTargets|    --&TargetString|    --=targetCount|1    --:TargetLoop|      --&TargetString|+t;target[$targetCount.Total] --+|[&TargetString]      --=targetCount|[$targetCount.Total] + 1      --?[$targetCount.Total] -le 6|>AddSeparator      --?[$targetCount.Total] -le 6|TargetLoop      --iPlease click the button below to select characters to heal. The same target can be selected multiple times;Select 6 Targets|[&TargetString] --+|[&TargetString]   --/| --+|Ending String: [&TargetString]   --<|   --:AddSeparator|     --&TargetString|+||   --<| It seemed to work fine until it requested 6 targets through the --i command but only let me select one target and then errored out. "Not a valid target id."  Looking at [&TargetString] I get: t;target1||t;target2||t;target3||t;target4||t;target5||t;target6   What am I doing wrong?
1622223788
Richard M.
Pro
Sheet Author
Apologies if this has already been answered, but I've tripped over a problem with referencing token_id in my code. It was a weird one becuase it only seemed to affect one token. Following a hunch, I did a quick check, and it turns out that the id contains a double-dash '--' and it breaks the code. Anyone able to offer up a workaround? Thanks
1622223956
David M.
Pro
API Scripter
I don't have a bullet proof solution, Richard, but you might try deleting the token and pulling out a new copy of it. That should generate a new tokenid.
1622224756
Richard M.
Pro
Sheet Author
Thanks, I was afraid that might be the answer. Damn you, randomly generated IDs! Unfortunately, when the code trips over it it stops the sandbox as well so I had to restart it. Looks like it's just bad luck, probably won't happen again...
1622226587
Kurt J.
Pro
API Scripter
Michael C. said: @tim - Um, well, no.  I think I lack some architecture knowledge here. The API runs outside the chat then sends information to the chat where the actual "calculations" are performed by Roll20 internal programming? The submission to the chat is the last function that the API can perform as there is no method of returning to the API to complete any further processes?  So, here the API creates a list of, say 6, open string variables then passes it to the chat to ask for information to put in the variables through the --i command which is subsequently processed by the chat? So, in reality, the --i command is the last command performed by the chat/script?  (Regardless of its placement in the script?)  So the --i statement knows how many times to ask because the loop has performed that many operations, formatted them and forwards filling the string variable to the chat?  Ok, I think I get it.  Maybe.  Sort of. Ok, so I tried to modify Kurt's script to only ask for token ids to process:  --:BuildAndAskTargets|    --&TargetString|    --=targetCount|1    --:TargetLoop|      --&TargetString|+t;target[$targetCount.Total] --+|[&TargetString]      --=targetCount|[$targetCount.Total] + 1      --?[$targetCount.Total] -le 6|>AddSeparator      --?[$targetCount.Total] -le 6|TargetLoop      --iPlease click the button below to select characters to heal. The same target can be selected multiple times;Select 6 Targets|[&TargetString] --+|[&TargetString]   --/| --+|Ending String: [&TargetString]   --<|   --:AddSeparator|     --&TargetString|+||   --<| It seemed to work fine until it requested 6 targets through the --i command but only let me select one target and then errored out. "Not a valid target id."  Looking at [&TargetString] I get: t;target1||t;target2||t;target3||t;target4||t;target5||t;target6   What am I doing wrong? Your targetString entries are missing a parameter. There are three parameters involved in asking the --i command for a target: t - indicating that we want a target (as opposed to "q" for a query) variableName - What variable we'll store the resulting target into targetidentifier - What Roll20 will prompt you for when asking for the target Currently your code is only supplying the first two (t;token1 then t;token2, etc.) This means that the targetidentifier will be "undefined" since it doesn't exist. Further, this means that the button that the --i command builds will contain six statements all asking for the same target (@{target|undefined|token_id}. Much like repeated roll queries, the Roll20 UI won't ask for the same thing more than once, so it returns all six values with whatever you picked. The simplest thing to do is simply duplicate the variable name parameter for the targetidentifier: --&TargetString|+t;target[$targetCount.Total];target[$targetCount.Total] With this change, your original code all works. I added some output of each of the target token IDs: !script {{ --:BuildAndAskTargets| --&TargetString| --=targetCount|1 --:TargetLoop| --&TargetString|+t;target[$targetCount.Total];target[$targetCount.Total] --+|[&TargetString] --=targetCount|[$targetCount.Total] + 1 --?[$targetCount.Total] -le 6|>AddSeparator --?[$targetCount.Total] -le 6|TargetLoop --+|[&TargetString] --iPlease click the button below to select characters to heal. The same target can be selected multiple times;Select 6 Targets|[&TargetString] --/| --+|Ending String: [&TargetString] --+Target1|[&target1] --+Target2|[&target2] --+Target3|[&target3] --+Target4|[&target4] --+Target5|[&target5] --+Target6|[&target6] --X| --:AddSeparator| --&TargetString|+|| --<| }}
timmaugh said: I think what you're running into is that the @{selected|...} construction is being detected at the first pass of the macro (before ScriptCard can populate that data for you). It resolves before SC receives the message, and at that point, SC hasn't replaced that text for the value. You can use a Fetch construction to solve this, as it allows you to leverage Roll20 attribute retrievals within the Fetch construction:  @(selected.@{selected|ActiveSkill}) That becomes... @(selected.JazzHands) ...by the time Fetch sees it, which becomes... 15 ...by the time it reaches ScriptCards. (That's one heckuva JazzHands skill, I must say.) Fetch is available in the 1-click. So would I use the @(selected.@{selected|ActiveSkill}) in place of the @{selected|[&Skill]}? 
1622230713

Edited 1622230852
timmaugh
Pro
API Scripter
EDIT: It looks like while I was typing this, Kurt helped with your actual ScriptCards code, Michael. This message still helps to explain what I was saying about the processing order. Michael C. said: @tim - Um, well, no.  I think I lack some architecture knowledge here. The API runs outside the chat then sends information to the chat where the actual "calculations" are performed by Roll20 internal programming?  No worries, it can be a bit odd to wrap your head around in the abstract. See if this helps: The user sends input (blue). This can be typing in the chat window, running a macro, clicking a button, etc., but it definitely comes from the user's action. Roll20 receives that message and parses the command line (green). It looks to see if the user who initiated the message has any tokens selected, and adds them to the message (provided the message doesn't contain an @{target...} statement). It resolves targeting requests (if present) by asking the user which tokens to target. It resolves any token or sheet-item requests like @{selected|token_id}, @{target|1|hp}, etc. It resolves roll queries by asking the user who initiated the message for input. It handles inline rolls. These things are actually handled in a particular order , but for now what is important is that they are executed at this step. If the message is not an API message (yellow), you will see the result hit the chat window. (This is a little simplified, but in terms of the noticed effect, is accurate.) If the message IS an API message, then it is handed to the scripts in order, one after another (pink). Each script checks to see if it needs to do anything. Each script gets the message as it stood when the previous message finished with it. That means by the time the message gets to the scripts, those interrogatives (like roll queries and targeting statements) have already been resolved. If a script wants to build a *new* list of targeting requests, it now needs a way to resolve those. Sounds like it needs to send a new message, right, so that it can give the Roll20 parsers (green) a chance to request that new targeting information? But what happens if it sends the message through the chat interface? The "user" of this new message is the API, not an actual player. There are no tokens "selected" for this player (the API), and there is no one for the Roll20 parsers to ask to pick targets to satisfy the new targeting statements. That is way a script-generated (or "API-generated") message doesn't have an array of selected tokens, and why those secondary targeting statements will never resolve. To get around this, scripts like ScriptCards (or InsertArg) will build a command line for a new message that includes some number of targeting statements, but then output that command line in button format for the user to click on. When the user clicks the button, that counts as the user initiating the message, so the Roll20 parsers know where to look for selected tokens and/or who to ask for roll queries and targeting statements. So in the code you pasted, above, the targeting requests are built into a button's command line, and that is output. That is the end of that message. When you click the button and answer the targeting requests, you are initiating a new, user-generated message with the new data. I believe the particular command line is also built (in this case) so that when that message reaches the API (pink), ScriptCards detects some flag that tells it to reengage and pick up further processing. (That's speculation about ScriptCards, not having the full macro in front of me... but the above is all accurate as far as *why* the targeting statements have to pass through a button to be resolved.)