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

January 29 (4 years ago)

Edited February 12 (3 years ago)
Kurt J.
Pro
API Scripter

ScriptCards allows you to create powerful macros that produce a card-style output to the game chat window similar to PowerCards (see the next post in this thread for some background info). The major difference is that ScriptCards is actually a scripting language interpreter that includes variables, loops, procedures (with parameters) and its own dice roll parser.

The first few posts in this thread contain the following:

This Post contains basic information about the ScriptCards script
The Second Post contains some background information on ScriptCards vs PowerCards
The Third Post is reserved for a FAQ (Frequently Asked Questions) section

Links

Wiki Documentation: https://wiki.roll20.net/Script:ScriptCards

Development on GitHub: https://github.com/kjaegers/ScriptCards/tree/main/ScriptCards_API

YouTube Overview and Demonstration: https://www.youtube.com/watch?v=hyR7Jnq4mQM

YouTube Deep-Dive on Magic Missile: https://www.youtube.com/watch?v=u50xvNzS9Zk

New: Discord Server https://discord.gg/jSB4wTNpXb (Updated link 2/12/2022)

Current Version (OneClick): 1.4.0e

Current Version (Development): 1.6.1

Note: This post finally became too big to edit :) The update links have been moved down a couple of posts. Most discussion and development now takes place on the Discord server listed above. Please join us to talk about upcoming features, fixes, and other tidbits.

General Overview

NOTE: ScriptCards has evolved to the point where it would not be possible to document it in a forum post. Please see the ScriptCards WIKI entry for complete documentation. The information below should be treated as an introductory overview.

ScriptCards is a feature-rich scripting language built as a Roll20 API script and accessible via the Roll20 chat window and macro system. The normal ScriptCards output is a formatted "card" to the game chat window in a style similar to the D&D 4E Power Cards format (but there is nothing system-specific in ScriptCards). The output is customizable, and entirely optional. Scripts can perform game object manipulation and never display anything if desired.


(ScriptCards output example)

The ScriptCards language supports variables, looping, conditional statements, branching, functions/subroutines, persistence of data items, object modification, reentrant functionality and much, much more. It includes its own dice roll parser with a number of different rolling options.

January 29 (4 years ago)

Edited April 06 (4 years ago)
Kurt J.
Pro
API Scripter

Some Background Information

Many of you probably know me as the guy that has been updating and maintaining the PowerCards API script for the last couple of years. One of the things I’ve always wanted to do was address some of the use cases that are just simply not possible/practical with PowerCards, such as:

  •           The ability to use the results of one roll within another roll
  •           The ability to make formatting and other single-use options conditional
  •           Actual branching and looping

At first, I considered continuing to attempt to modify PowerCards to add some of these capabilities, but the things that prevent them from happening are pretty fundamentally baked into the DNA of PowerCards. Modifying those underpinnings would require breaking changes to PowerCards, rendering existing content people are using in games unusable.

To prevent that, I decided on starting from scratch with the intent of a scripting language as the base for the API script. Both PowerCards and ScriptCards can be installed in the same Roll20 game and live happily side by side.

January 29 (4 years ago)

Edited February 11 (3 years ago)
Kurt J.
Pro
API Scripter

Development/Release Update Index

1.4.7: (XdY!h and XdY!l formats) 1.4.7 Update Notes

1.4.2: (Math functions, bug fixes) 1.4.2 Update Notes

1.4.0: (pagetokens performance, array sort) 1.4.0 Update Notes (d)

1.3.9a/b/c: (Angle function, Repeating Section Performance) 1.3.9a Update Notes (b) (c)

1.3.9: (HR code, Title Shadow, findability, array setatindex) 1.3.9 Update Notes

1.3.8: (Bug fixes, get raw date) 1.3.8 Update Notes

1.3.7: (Button background images, dumpvariables function) 1.3.7 Update Notes

1.3.6b: (Bug fix, buttontextcolor options) 1.3.6b Update Notes

1.3.6a: (International character support in variable names) 1.3.6a Update Notes

1.3.6: (title card backgrounds & gradients, no-highlight rolls) 1.3.6 Update Notes

1.3.5: (Date functions, find token inits, readsetting function) 1.3.5 Update Notes

1.3.1: (Referencing/Replacement Rewrite) 1.3.1 Update Notes

1.2.9: (More Deferral, Point Custom FX, pixel distance, replaceall, trim, executionlimit) 1.2.9 Update Notes

1.2.8a: (SelectManager Deferral Support) 1.2.8a Update Notes

1.2.8: (Point VFX, Roll Parser Math Funcs) 1.2.8 Update Notes

1.2.7: (For..Next, Statement Block, Data Statements) 1.2.7 Update Notes

1.2.3: (Inline Roll Semi-Support, lower/upper/title case) 1.2.3 Update Notes

1.2.2: (#activepage, [*C:] (campaign) and [*P:] (page) attributes: 1.2.2 Update Notes

1.2.1: (URL Attributes, Non-Branching Conditionals): 1.2.1 Update Notes

1.1.19: New Roll Formula, Button Formatting, Status Markers, Array Updates: 1.1.19ACE

1.1.18: Errors & Warnings, GM Text, SheetButtons, Reentrant Scripts: 1.1.18 Update Notes

1.1.15: Persistable Array: 1.1.15 Update Notes

1.1.14: Token Array Functions: 1.1.14 Update Notes

1.1.13: Bug Fixes and Stringify Arrays: 1.1.13 Update Notes

1.1.12 (Mislabeled 1.1.2): New Roll Syntaxes, Turn Tracker Support, Arrays: 1.1.12 Update Notes

1.0.8: Table Markup, Custom VFX, Token Attributes: 1.0.8 Update Notes 

1.0.2: -ninc Operator, br formating, Info Request (--i) Support : 1.0.2 Update Notes

1.0.0: Predefined Player Strings, Case (--c) Statement, Procedure Library Support: 1.0.0 Update Notes

0.0.15: Comments (--/), Modulo operator, rdump, Function Groups: 0.0.15 Update Notes

0.0.14: Referencing Updates, #NoMinMaxHilight, getselected function: 0.0.14 Update Notes

0.0.13: Bug Fixes, Repeating Sections (--r), and Functions (--~): 0.0.13 Update NotesA

0.0.11: Button Customization, Dice Fonts, Whisper Support: 0.0.11 Update NotesA

0.0.10: New Settings, String Variables, VFX, Echo (--e), Buttons w/API code: 0.0.10 Update NotesAB

0.0.8: Storage (--s and --l), Rollable Tables, Multipart Conditionals: 0.0.8 Update Notes

Script Sharing Index

Please see Craven's "ScriptCard API Working and Sharing" post, as he has gathered and indexed a large number of ScriptCards scripts in one place.

If others pop up in different locations, I'll link to them here.


January 30 (4 years ago)
keithcurtis
Forum Champion
Marketplace Creator
API Scripter

Interesting. These are the things I originally thought Powercards was for, but was always either disappointed or (more likely) confused. This looks very intriguing!

This looks SUPER cool. I think maybe this is the incentive I need to take the plunge and figure this powercard-type stuff out.

January 30 (4 years ago)

Edited January 30 (4 years ago)
David M.
Pro
API Scripter
Loops and function calls in macros, in addition to conditionals? Nice! Can't wait to try it out!
January 30 (4 years ago)
Kurt J.
Pro
API Scripter

I updated the GIST (no version number change) to remove a couple of log lines I was using for debugging that would output the content of each row to the console. That spam should be gone if you re-import the script.

January 30 (4 years ago)
David M.
Pro
API Scripter

Looks like the Magic Missile example above never includes the first missile in the total damage. However, I got it to work by initializing a value of 0 to the MissileDamage roll variable (bolded below) prior to the first call to the FireMissile procedure.

 !scriptcard  {{ 
  --#title|Magic Missile
  --#leftsub|Slot level ?{Spell Slot Level?|1|2|3|4|5|6|7|8|9}
  --#rightsub|Ranged Attack (120ft)

  --=MissileCount|?{Spell Slot Level?} + 2
  --=DisplayCount|1
  --=MissileDamage|0

  --:MissileLoop|
  -->FireMissile|
  --=DisplayCount|[$DisplayCount] + 1
  --?[$DisplayCount] -le [$MissileCount]|MissileLoop
  --+Total|Total damage is [$MissileDamage]
  --X|

  --:FireMissile|
  --=ThisMissile|1d4 + 1
  --=MissileDamage|[$MissileDamage] + [$ThisMissile]
  --+Missile|[$DisplayCount.Total] Hits for [$ThisMissile] [b]force[/b] damage
  --<|
}}

EDIT: Also works if I just declare it but put no value for the variable (defaults to 0).

--=MissileDamage|


January 30 (4 years ago)
Kurt J.
Pro
API Scripter

Good catch :) I've updated the Wiki version of the example and will update the first post here as well.

January 31 (4 years ago)

Edited January 31 (4 years ago)
David M.
Pro
API Scripter

Played around with this a little bit again today. Really neat, Kurt!

I decided to try it out with the 5e Barbarian Path of Wild Magic "Wild surge" feature. I know this could be done with rollable tables and RecursiveTable or similar api to handle the rolls within some of the table entries, but this was more of a syntax study project for me with functions, formatting, and whatnot. I figured I'd share it here in case somebody wanted to use it or just wanted another practical example.

Simple enough to use. Select the barbarian token and run the macro. Rolls 1d8 against the surge table, checks the result, and possibly makes more rolls prior to output (these were put into the individual functions to keep the overhead low).

 !scriptcard  {{ 
  --:___Formatting___
  --#title|Wild Surge
  --#leftsub|Path of Wild Magic Feature
  --#titleCardBackground|#932729
  --#oddRowBackground|#CEC7B6
  --#evenRowBackground|#B6AB91
  
  --:___Primary Rolls___
  --=DC|8 + @{selected|pb} + @{selected|constitution_mod}
  --=SurgeRoll|1d8

  --:___Conditionals___
  --?[$SurgeRoll] -eq 1| >Roll_1
  --?[$SurgeRoll] -eq 2| >Roll_2
  --?[$SurgeRoll] -eq 3| >Roll_3
  --?[$SurgeRoll] -eq 4| >Roll_4
  --?[$SurgeRoll] -eq 5| >Roll_5
  --?[$SurgeRoll] -eq 6| >Roll_6
  --?[$SurgeRoll] -eq 7| >Roll_7
  --?[$SurgeRoll] -eq 8| >Roll_8
  --X|___Exit Macro___

  --:___Functions___
  --:Roll_1|
      --=NecroDam|1d12
      --=TempHP|1d12
      --+[c]**~~Shadow Tendrils~~|**[/c]
      --+|Shadowy tendrils lash around you. 
      --+|[j]Each creature of your choice that you can see within 30 feet of you must succeed on a **[#990000]Constitution saving throw (DC [$DC.Total])[/#]** or take [$NecroDam] necrotic damage.[/j]
      --+|You also gain [$TempHP] temporary hit points.
      --<|

  --:Roll_2|
      --+[c]**~~Teleport~~|**[/c]
      --+|[j]**You teleport up to 30 feet** to an unoccupied space you can see.[/j]
      --+Ongoing Effect|[j]Until your rage ends, you can use this effect again on each of your turns as a bonus action.[/j]
      --<|

  --:Roll_3|
      --=ForceDam|1d6
      --+[c]**~~Intangible Spirit~~|**[/c]
      --+|[j]An intangible spirit, which looks like a **flumph** or a **pixie** (your choice), appears within 5 feet of one creature of your choice that you can see within 30 feet of you.[/j]
      --+|[j]At the end of the current turn, the spirit explodes, and each creature within 5 feet of it must succeed on a **[#990000]Dexterity saving throw (DC [$DC.Total])[/#]** or take [$ForceDam] force damage.[/j] 
      --+Ongoing Effect|[j]Until your rage ends, you can use this effect again, summoning another spirit, on each of your turns as a bonus action.[/j]
      --<|

  --:Roll_4|
      --+[c]**~~Force Weapon~~|**[/c]
      --+|[j]Magic infuses one weapon of your choice that you are holding.[/j]
      --+|[j]Until your rage ends, the **weapon's damage type changes to force, and it gains the light and thrown properties**, with a normal range of 20 feet and a long range of 60 feet.[/j]
      --+|[j]If the weapon leaves your hand, the weapon reappears in your hand at the end of the current turn.[/j]
      --<|

  --:Roll_5|
      --+[c]**~~Retributive Strike~~|**[/c]
      --+Ongoing Effect|[j]Whenever a creature hits you with an attack roll before your rage ends, that creature takes **[#990000]1d6 force damage[/#]**, as magic lashes out in retribution.[/j]
      --<|

  --:Roll_6|
      --+[c]**~~Protective Aura~~|**[/c]
      --+Ongoing Effect|[j]Until your rage ends, you are surrounded by multi colored, protective lights. You gain a **[#990000]+1 bonus to AC[/#]**, and while within 10 feet of you, your allies gain the same bonus.[/j]
      --<|

  --:Roll_7|
      --+[c]**~~Entangling Aura~~|**[/c]
      --+|[j]Flowers and vines temporarily grow around you.[/j]
      --+Ongoing Effect|[j]Until your rage ends, the ground within 15 feet of you is **[#990000]difficult terrain[/#]** for your enemies.[/j]
      --<|

  --:Roll_8|
      --=RadiantDam|1d6
      --+[c]**~~Radiant Bolt~~|**[/c]
      --+|[j]A bolt of light shoots from your chest.[/j]
      --+|[j]Another creature of your choice that you can see within 30 feet of you must succeed on a **[#990000]Constitution saving throw (DC [$DC.Total])[/#]** or take [$RadiantDam] radiant damage and be blinded until the start of your next turn.[/j]
      --+Ongoing Effect|[j]Until your rage ends, you can use this effect again on each of your turns as a bonus action.[/j]
      --<|
}}

Some sample output


January 31 (4 years ago)

I've been playing with this script all day yesterday, and am really loving it.  The ability to have conditionals and subroutines in a macro is a large enhancement for Roll20's scripting language.  It also appears that one could develop simple looping, which I'll be testing out soon.  

BTW, the Code link on your WIKI page is a dead-end link.  

January 31 (4 years ago)
Kurt J.
Pro
API Scripter


Will M. said:

I've been playing with this script all day yesterday, and am really loving it.  The ability to have conditionals and subroutines in a macro is a large enhancement for Roll20's scripting language.  It also appears that one could develop simple looping, which I'll be testing out soon.  

BTW, the Code link on your WIKI page is a dead-end link.  


Looks like the code element is a built-in part of the script Wiki template, and always wants to point to somewhere on the Roll20 GITHUB. I couldn't find a way to point it to the GIST, but I did manage to get it to not show up to remove confusion.

January 31 (4 years ago)
GiGs
Pro
Sheet Author
API Scripter

This looks very cool. Your video was a very good tutorial.

January 31 (4 years ago)

This looks AWESOME....!!!!
Cant Wait to implement...

January 31 (4 years ago)
Kurt J.
Pro
API Scripter

Thanks everyone that has checked it out. I've had a lot of fun putting this together, and I've submitted a pull request to get it up on OneClick (hopefully this week).

February 01 (4 years ago)
David M.
Pro
API Scripter

Can procedures be called from other procedures, or is it limited to one branch level?

Simple example: Create a roll variable "Var" initialized to 0. Call procedure "TestProc" that rolls a 1d2 and on a roll of 1, call a subprocedure "AddToVar" (via bolded line below) that increments Var by one. Then return output. The following never increments the counter "Var", which makes me think we might be limited to one level of branching? (...or I goofed in the syntax somewhere)

!scriptcard  {{ 
  --#title|Test

--:Main
  --=Var|0
  -->TestProc|
  --+Value of "Var"|[$Var]
  --X|Exit macro

--:TestProc|
  --=Temp|1d2
  --+Roll|[$Temp]
  --?[$Temp.Total] -eq 1|>AddToVar
  --<|

--:AddToVar
  --=Var|[$Var] +1
  --<|
}}

If not, is there a way to update a roll variable directly from a query?

I tried the following with no luck:

--?[$Temp.total] -eq 1|=Var|[$Var] + 1
February 01 (4 years ago)

Edited February 01 (4 years ago)
Kurt J.
Pro
API Scripter


David M. said:

Can procedures be called from other procedures, or is it limited to one branch level?

Simple example: Create a roll variable "Var" initialized to 0. Call procedure "TestProc" that rolls a 1d2 and on a roll of 1, call a subprocedure "AddToVar" (via bolded line below) that increments Var by one. Then return output. The following never increments the counter "Var", which makes me think we might be limited to one level of branching? (...or I goofed in the syntax somewhere)

!scriptcard  {{ 
  --#title|Test

--:Main
  --=Var|0
  -->TestProc|
  --+Value of "Var"|[$Var]
  --X|Exit macro

--:TestProc|
  --=Temp|1d2
  --+Roll|[$Temp]
  --?[$Temp.Total] -eq 1|>AddToVar
  --<|

--:AddToVar
  --=Var|[$Var] +1
  --<|
}}

If not, is there a way to update a roll variable directly from a query?

I tried the following with no luck:

--?[$Temp.total] -eq 1|=Var|[$Var] + 1

Nested procedure calls is supported. The issue above is that the --:AddToVar line is missing the trailing | so the line is being skipped (and therefore not recognized by the procedure call as a legitimate label). If you add a | to the end of that line it works as expected for me. (the same will be true of --:Main, but since it is never branched to it doesn't end up hurting anything).

When nesting procedure calls, a return stack is built that can support (theoretically) any depth of nesting. A parameter stack is also built, so if you pass "A;B;C" to Procedure1 which calls Procedure2 and passes "D;E;F" when you return from Procedure2 to Procedure1 the "D;E;F" parameters are popped off the stack and the current parameter set becomes "A;B;C" again.

For the second part, conditionals ONLY support branching (direct or procedure). they currently don't support an alternative statement type when true.

February 01 (4 years ago)
David M.
Pro
API Scripter

Perfect, I was hoping it was just a syntax issue. Thanks!

February 01 (4 years ago)

Edited February 01 (4 years ago)
Kurt J.
Pro
API Scripter

You can also use recursion:

!scriptcard {{
  --#title|Recursion Test
  --=BaseValue|0
  --=RollCount|0
  --=MaxValue|1000
  --+Info|Going to roll d10s until we reach 1000 or higher!

  -->AddIt|
  --+Results|It took [$RollCount.Total] rolls to reach [$BaseValue.Total]
  --X|

  --:AddIt|
  --=BaseValue|[$BaseValue] + 1d10
  --=RollCount|[$RollCount] + 1
  --?[$BaseValue] -lt [$MaxValue]|>AddIt
  --<|
}}



Probably wouldn't be necessary unless the card was really complicated, but it can be done :)

I pushed the max number up to 1,000,000, resulting in 182,148 recursive die rolls and the sandbox didn't crash or timeout :) It did take ~10 seconds to complete though :)

February 01 (4 years ago)

Edited February 01 (4 years ago)

I really like ScriptCards and see a lot of potential.  I have had an issue with making API calls (--@) as the script doesn't always evaluate the variables I pass it correctly.  I'll work on getting a simple example to demonstrate the problem.  


Also - What happens if you put the card into an endless loop and how do you interrupt the code at that point?  I'm guessing restarting the API Sandbox is your best bet.  


February 01 (4 years ago)

Edited February 01 (4 years ago)

I believe I found a bug associated with making API calls when using the API command (--@).  If you make more than one API call, ScriptCards uses the last command and calls it equal to the number of total API calls.  For example:

!scriptcard {{
  --#title|Heal
  --@modbattr|_name @{selected|character_name} _HP|1
  --@modbattr|_name @{selected|character_name} _HP|2
  --@modbattr|_name @{selected|character_name} _HP|3
}}

modbattr is a command from the ChatSetAttr API script which I use to adjust character-sheet attributes.  I placed debug code in the script to log the actual commands being sent to the API and I get this as a result:

"!modbattr  --name BB --HP|3"
"!modbattr  --name BB --HP|3"
"!modbattr  --name BB --HP|3"


The ScriptCards code should increase the token HP by 1, 2, and 3 for a total of 6.  What actually happens is the token HP is increased by 3, 3, and 3 for a total of 9.  This is verified by both the debug msg (log()) and the observed increase in the tokens HP to 9.  I'm guessing that you wrote this assuming the user would issue only one API command per card.  

Update:  I think the bug has something to do with the setTimeout() function, which causes the code to run asynchronously.  I'm guessing that because it is calling the 3 functions in rapid succession, it is using stored memory from the last call and executing the 3 calls against the last set of data in memory.  I modified your code to run the sendChat outside of the setTimeout() function fixes the problem for me.  This is around line 215 of your script.   

Will


February 01 (4 years ago)

Edited February 01 (4 years ago)
Kurt J.
Pro
API Scripter


Will M. said:

I believe I found a bug associated with making API calls when using the API command (--@).  If you make more than one API call, ScriptCards uses the last command and calls it equal to the number of total API calls.  For example:

!scriptcard {{
  --#title|Heal
  --@modbattr|_name @{selected|character_name} _HP|1
  --@modbattr|_name @{selected|character_name} _HP|2
  --@modbattr|_name @{selected|character_name} _HP|3
}}

modbattr is a command from the ChatSetAttr API script which I use to adjust character-sheet attributes.  I placed debug code in the script to log the actual commands being sent to the API and I get this as a result:

"!modbattr  --name BB --HP|3"
"!modbattr  --name BB --HP|3"
"!modbattr  --name BB --HP|3"


The ScriptCards code should increase the token HP by 1, 2, and 3 for a total of 6.  What actually happens is the token HP is increased by 3, 3, and 3 for a total of 9.  This is verified by both the debug msg (log()) and the observed increase in the tokens HP to 9.  I'm guessing that you wrote this assuming the user would issue only one API command per card.  

Hope this makes sense.

Will


I see what is happening. The setTimeout appears to be the culprit. If I just simply call sendChat without the setTimeout construct it works as expected. I'll make some updates in the next version.

As far as putting the script into an endless loop, you could certainly do that, and your sandbox will detect and endless loop and stop on its own.

Update: I've updated the development GIST with a fix for the multi API call issue, and updated the code on my pull request, so this fix should make it to the OneClick version that should go up tomorrow.

February 02 (4 years ago)

This looks like a lot of fun!

I started playing around with the problem I was trying to solve at the moment. I'm trying to determine which values to use in a DC Heroes unarmed melee attack depending on the skill level of the characters attacking and defending, and then passing the values to the Megs API written by GiGs.

However I keep crashing the sandbox. 

I am able to write a macro that gets the values from the selected and targeted tokens:

 	!scriptcard  {{
 --#title|Unarmed Melee Attack
 --=SMA|@{selected|skill_martial-artist}
  --+Martial Artist|[$SMA]  
 --=SDEX|@{selected|dex} 
 --+Attacker Dex|[$SDEX]
 --=TMA|@{target|skill_martial-artist}
  --+ Target Martial Artist|[$TMA]  
 --=TDEX|@{target|dex} 
 --+Target Dex|[$TDEX] 
 }}

But my attempts at evaluating the Dex attribute and Martial Arts skill and using the higher value crashes the API. Here is one attempt, I've also tried skipping the "=" declarations and get the values from the token in the "?" declaration:

	!scriptcard  {{
 --#title|Unarmed Melee Attack
 --=MA|@{selected|skill_martial-artist}
  --+Martial Artist|[$MA]  
 --=DEX|@{selected|dex} 
 --+Dex|[$DEX]
 --?|[$DEX] -lt [$MA]|UseMA
 --:UseMA
 --+You attack using your| [$MA] Martial Artis skill
 --X
 --:UseDex
 --+You attack using your| [$DEX] Dexterity attribute
  }}

Also my attempts at passing values to the Megs API crash the sandbox:

!scriptcard  {{
  --#title|Unarmed Melee Attack
  --#sourceToken|@{selected|token_id}
  --#targetToken|@{target|token_id}
  --#emoteText|@{selected|token_name} attacks @{target|token_name}
  --=AV|@{selected|dex}
  --=EV|@{selected|body}
  --=OV|@{target|dex}
  --=RV|@{target|body}
  --@megs|_av:[$AV] _ev:[$EV] _ov:[$OV] _rv:[$RV]
  }}
February 02 (4 years ago)
Kurt J.
Pro
API Scripter


Marius said:

This looks like a lot of fun!

I started playing around with the problem I was trying to solve at the moment. I'm trying to determine which values to use in a DC Heroes unarmed melee attack depending on the skill level of the characters attacking and defending, and then passing the values to the Megs API written by GiGs.

However I keep crashing the sandbox. 

I am able to write a macro that gets the values from the selected and targeted tokens:

 	!scriptcard  {{
 --#title|Unarmed Melee Attack
 --=SMA|@{selected|skill_martial-artist}
  --+Martial Artist|[$SMA]  
 --=SDEX|@{selected|dex} 
 --+Attacker Dex|[$SDEX]
 --=TMA|@{target|skill_martial-artist}
  --+ Target Martial Artist|[$TMA]  
 --=TDEX|@{target|dex} 
 --+Target Dex|[$TDEX] 
 }}

But my attempts at evaluating the Dex attribute and Martial Arts skill and using the higher value crashes the API. Here is one attempt, I've also tried skipping the "=" declarations and get the values from the token in the "?" declaration:

	!scriptcard  {{
 --#title|Unarmed Melee Attack
 --=MA|@{selected|skill_martial-artist}
  --+Martial Artist|[$MA]  
 --=DEX|@{selected|dex} 
 --+Dex|[$DEX]
 --?|[$DEX] -lt [$MA]|UseMA
 --:UseMA
 --+You attack using your| [$MA] Martial Artis skill
 --X
 --:UseDex
 --+You attack using your| [$DEX] Dexterity attribute
  }}

Also my attempts at passing values to the Megs API crash the sandbox:

!scriptcard  {{
  --#title|Unarmed Melee Attack
  --#sourceToken|@{selected|token_id}
  --#targetToken|@{target|token_id}
  --#emoteText|@{selected|token_name} attacks @{target|token_name}
  --=AV|@{selected|dex}
  --=EV|@{selected|body}
  --=OV|@{target|dex}
  --=RV|@{target|body}
  --@megs|_av:[$AV] _ev:[$EV] _ov:[$OV] _rv:[$RV]
  }}


The issue with the second script is that your conditional line has an extra vertical bar before the condition:

--?|[$DEX] -lt [$MA]|UseMA

should be

--?[$DEX] -lt [$MA]|UseMA


I don't get any negative effects running the second one. What is the sandbox error message when it crashes?

I have updated the GIST and repo for OneClick to handle empty conditions gracefully instead of crashing.

February 02 (4 years ago)

Thank you!

So now this code:

!scriptcard  {{
  --#title|Unarmed Melee Attack
  --#sourceToken|@{selected|token_id}
  --#targetToken|@{target|token_id}
  --#emoteText|@{selected|token_name} attacks @{target|token_name}
  --?@{selected|dex} -lt @{selected|skill_martial-artist}|MA
  --:MA|
  --=AVM|@{selected|skill_martial-artist}
  --=EV|@{selected|body}
  --=OV|@{target|dex}
  --=RV|@{target|body}
  --+megs|_av:[$AVM] _ev:[$EV] _ov:[$OV] _rv:[$RV]
  --^Final|
  --:Dex|
  --=AVD|@{selected|dex}
  --=EV|@{selected|body}
  --=OV|@{target|dex}
  --=RV|@{target|body}
  --@megs|_av:[$AVD] _ev:[$EV] _ov:[$OV] _rv:[$RV]
  --^Final|
  --:Final|
  }}

Produces this result:

While changing the "+" to "@" gives this result:

And this crash-report:

For reference, the error message generated was: TypeError: Cannot read property 'id' of undefined
TypeError: Cannot read property 'id' of undefined
    at getSender (apiscript.js:82:38)
    at handleInput (apiscript.js:273:28)
    at eval (eval at <anonymous> (/home/node/d20-api-server/api.js:154:1), <anonymous>:65:16)
    at Object.publish (eval at <anonymous> (/home/node/d20-api-server/api.js:154:1), <anonymous>:70:8)
    at /home/node/d20-api-server/api.js:1662:12
    at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560
    at hc (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:39:147)
    at Kd (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:546)
    at Id.Mb (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:489)
    at Zd.Ld.Mb (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:94:425)


For reference, running "!megs --av:4 --ev:3 --ov:9 --rv:8" gives this (intended) result:


February 02 (4 years ago)
Kurt J.
Pro
API Scripter

This looks like the megs API is trying to evaluate who sent the message and coming up with nothing, then trying to look up the ID on that nothing. These functions:

getSender (apiscript.js:82:38)
    at handleInput (apiscript.js:273:28)

(getSender and handleInput) don't exist in ScriptCards, so they are likely coming from megs.

The sendChat that is used to call the api passes along the msg.who value for the sender.



February 02 (4 years ago)

Edited February 02 (4 years ago)

This looks so cool and naturally I saw it after I did a near complete macro rewrite for my campaign. :)

I do have a couple questions about syntax: 

Is it possible to do math in conditionals? For example, does this work?

  --?[$AttackRoll] -ge @{target|bar2} + 10|Crit

Secondly, what is the format for button commands? 

  --+What did you do?|[button]Fumble::~GenericMacro|FumbleRoll[/button]

This command seems to output the button fine, but then doesn't execute the macro correctly for the Powercard. 


February 02 (4 years ago)
David M.
Pro
API Scripter

On a related note, is there currently support for AND/OR logic for conditionals? This doesn't seem to work.

  --?[$Roll1] -eq 1 AND [$Roll2] -eq 1|DoSomething
February 02 (4 years ago)
Kurt J.
Pro
API Scripter


Erik M. said:

This looks so cool and naturally I saw it after I did a near complete macro rewrite for my campaign. :)

I do have a couple questions about syntax: 

Is it possible to do math in conditionals? For example, does this work?

  --?[$AttackRoll] -ge @{target|bar2} + 10|Crit

Secondly, what is the format for button commands? 

  --+What did you do?|[button]Fumble::~GenericMacro|FumbleRoll[/button]

This command seems to output the button fine, but then doesn't execute the macro correctly for the Powercard. 


Math is only supported in variable assignment statements (--=) so you would need to break it into two lines and assign a variable to compare against.

I've run API commands with the button controls, but I'll experiment with other uses and see what might be happening. The button code is very simple, though... it just replaces the text with [Text](Action). You might be running into the chat server messing with the result and need to use the escape sequences to hide the character references from the macro.




February 02 (4 years ago)
Kurt J.
Pro
API Scripter


David M. said:

On a related note, is there currently support for AND/OR logic for conditionals? This doesn't seem to work.

  --?[$Roll1] -eq 1 AND [$Roll2] -eq 1|DoSomething


AND and OR is on my list for the next version update (coming soon) along with a few other features as well.

February 02 (4 years ago)
David M.
Pro
API Scripter

Sweet, thanks!

February 02 (4 years ago)
Kurt J.
Pro
API Scripter


David M. said:

Sweet, thanks!

Found a bug in the -inc code while working on adding and/or. it wasn't returning true if the inclusion started at the first character of the string (so "Hello -inc He" was returning false (incorrectly), while "Hello -inc ello" was returning true (as it should) .

I have a little more testing and documenting to do and I'll get a new version up on the GIST this evening.


February 03 (4 years ago)

Edited February 03 (4 years ago)
Kurt J.
Pro
API Scripter

ScriptCards version 0.0.8 is on the Development GIST

I have released a new version of ScriptCards to the public GIST. The following updates have been made since 0.0.5:

  • Added two new statement types : --S and --L to save and load groups of settings or roll variables. The syntax is "--Ssettings|GroupName" or --Srollvariables|GroupName" to save, and "--Lsettings|GroupName" or "--Lrollvariables|GroupName" to load. Saving settings saves all current settings that are different from their defaults (things like background colors, fonts, etc.) under the given name. Saving roll variables saves all currently defined variables. The groups are separate (MyStuff could exist as both settings and rollvariables and wouldn't collide). When loading rollvariables, the stored roll variables are added to any variables already on the card. If an existing variable has the same name as a loaded variable, it will be overwritten. When loading settings, any setting loaded as part of the group can be overridden by simply re-setting it with a --# statement. The idea behind the stored settings is to function as a replacement for the --format tag in PowerCards, allowing you to save named formats (using @{selected|token_name} for character names, for example). and loading them to customize the appearance of the card on a per-character basis. Stored items persist between cards, and between roll20 sessions.
  • Added support statement : !sc-liststoredsettings will produce a card listing all of your stored setting groups with buttons to click to see the details of each group.
  • Added support for rollable tables in --= statements. If the roll equation contains a rollable table in the format [T#tablename] where tablename is the case-sensitive name of the table in your game, two new properties will be set on the roll variable - .tableEntryText and .tableEntryImgURL. Proper weighting of table items is taken into account when performing the roll.
  • Added support for multi-part  conditionals using -and and -or. Multi-part conditionals are evaluated left to right with a running result value, so T and F or T will return true (T and F will be F, but F or T will result in true at the end). See the wiki for more details.
  • Corrected a bug that would duplicate the same API call parameters if multiple API calls were in a script.
  • Corrected a bug in the -inc conditional operator that was not recognizing the first character of the lefthand string (ie, "Hello" -inc "Hell" would be false, while "Hello" -inc "ell" would be true).
  • Empty conditionals (--?|) will no longer crash the sandbox. They won't work, but they won't crash the sandbox :)


Some details on rollable tables. Given this table:


This script:

!scriptcard {{
 --=SpellIcon|[T#SpellTokens]
 --+Spell Name|[$SpellIcon.tableEntryText]
 --+Image|[r][img width=128][$SpellIcon.tableEntryImgURL][/img][/r]
}}

Will produce output like this:





February 03 (4 years ago)


Kurt J. said:

This looks like the megs API is trying to evaluate who sent the message and coming up with nothing, then trying to look up the ID on that nothing. These functions:

getSender (apiscript.js:82:38)
    at handleInput (apiscript.js:273:28)

(getSender and handleInput) don't exist in ScriptCards, so they are likely coming from megs.

The sendChat that is used to call the api passes along the msg.who value for the sender.



Would this be fixable on the Scriptcards end of things? The MEGS issue is probably not affecting anyone else, but if some kind of api-as/api-subsitution was possible that might be applicable across a number of APIs? I'm way out of my depth here, but I believe Tokenmod and CombatMaster do something like this?

I'm also looking forward to playing around with rollable tables, went to bed thinking about how I could name characters based on tables and npc-types last night...


February 03 (4 years ago)
Kurt J.
Pro
API Scripter


Marius said:


Kurt J. said:

This looks like the megs API is trying to evaluate who sent the message and coming up with nothing, then trying to look up the ID on that nothing. These functions:

getSender (apiscript.js:82:38)
    at handleInput (apiscript.js:273:28)

(getSender and handleInput) don't exist in ScriptCards, so they are likely coming from megs.

The sendChat that is used to call the api passes along the msg.who value for the sender.



Would this be fixable on the Scriptcards end of things? The MEGS issue is probably not affecting anyone else, but if some kind of api-as/api-subsitution was possible that might be applicable across a number of APIs? I'm way out of my depth here, but I believe Tokenmod and CombatMaster do something like this?

I'm also looking forward to playing around with rollable tables, went to bed thinking about how I could name characters based on tables and npc-types last night...


I tried looking for the code for Megs based on your post above, but both of the github links lead to empty pages. It is unlikely anything I do on the scriptcards side would help, but I'd need to see the Megs code to know for sure.The API isn't capable of passing along certain information (selected tokens, the player ID of the message sender), so if an API script relies on that information it can't be called from other scripts.

Token-Mod checks to see if the caller is a GM, but also includes a settable option to allow non-GMs to use the --ids command, which allows it to be called working around those restrictions.


February 03 (4 years ago)


Kurt J. said:

I tried looking for the code for Megs based on your post above, but both of the github links lead to empty pages. It is unlikely anything I do on the scriptcards side would help, but I'd need to see the Megs code to know for sure.The API isn't capable of passing along certain information (selected tokens, the player ID of the message sender), so if an API script relies on that information it can't be called from other scripts.

Token-Mod checks to see if the caller is a GM, but also includes a settable option to allow non-GMs to use the --ids command, which allows it to be called working around those restrictions.



It was moved here: https://gist.github.com/birdbrainiac/4a18d202ef43ab5fee938facecedb09e

February 03 (4 years ago)
GiGs
Pro
Sheet Author
API Scripter

Alternatively, just let me know what i need to change in MEGS to work with scriptcards.

February 03 (4 years ago)
Kurt J.
Pro
API Scripter


GiGs said:

Alternatively, just let me know what i need to change in MEGS to work with scriptcards.


I think the only thing that would need to change is in this function:

    const getSender = msg => {
        const character = findObjs({ type: 'character', name: msg.who })[0],
            player = getObj('player', msg.playerid);

        if (character) return 'character|'+character.id;
        else return 'player|'+player.id;
    };

When using sendChat, the SpeakingAs parameter fills in msg.who, but msg.playerid will always be "API" (I haven't found a way to change that).

ScriptCards (and powercards) just pass along whatever they got for msg.who so if I'm reading things right, the only time the crash indicated above would happen is when the GM (who's msg.who value doesn't equal a character name) runs something that calls !megs via the API. In that case the character lookup will fail by name (for example, my msg.who is "Kurt J (GM)" which isn't a valid character name) and the script will try looking up a player by ID, which will also result in undefined since playerid will be API, which isn't a valid player.

Modifying the return portion should account for these possibilities and just return whatever it got for msg.who if it can't find a character or player with a matching name.

        if (character) return 'character|'+character.id;
        if (player) return 'player|'+player.id;
        return msg.who;

It looks like the only place the sender is used is as the sendChat speakingAs parameter for the final output, so it might look a little weird if a GM runs it, but it should not impact the sandbox.

February 03 (4 years ago)
GiGs
Pro
Sheet Author
API Scripter

Thanks, I'll keeep that in mind for future scripts, I hadnt considered the possibility of people running my scripts via another script.

February 03 (4 years ago)

Edited February 03 (4 years ago)


Kurt J. said:


GiGs said:

Alternatively, just let me know what i need to change in MEGS to work with scriptcards.


I think the only thing that would need to change is in this function:

    const getSender = msg => {
        const character = findObjs({ type: 'character', name: msg.who })[0],
            player = getObj('player', msg.playerid);

        if (character) return 'character|'+character.id;
        else return 'player|'+player.id;
    };

When using sendChat, the SpeakingAs parameter fills in msg.who, but msg.playerid will always be "API" (I haven't found a way to change that).

ScriptCards (and powercards) just pass along whatever they got for msg.who so if I'm reading things right, the only time the crash indicated above would happen is when the GM (who's msg.who value doesn't equal a character name) runs something that calls !megs via the API. In that case the character lookup will fail by name (for example, my msg.who is "Kurt J (GM)" which isn't a valid character name) and the script will try looking up a player by ID, which will also result in undefined since playerid will be API, which isn't a valid player.

Modifying the return portion should account for these possibilities and just return whatever it got for msg.who if it can't find a character or player with a matching name.

        if (character) return 'character|'+character.id;
        if (player) return 'player|'+player.id;
        return msg.who;

It looks like the only place the sender is used is as the sendChat speakingAs parameter for the final output, so it might look a little weird if a GM runs it, but it should not impact the sandbox.


This works! Tested it in my game now. 

February 03 (4 years ago)
David M.
Pro
API Scripter

Excited about rollable table image support! Very cool. Some comments/questions:

1) I noticed that it does not seem to handle table names that include a dash (like the default "new-table" name). Haven't tried other special characters. NBD if we just have to remember to name appropriately.

2) Is there support for multiple table images on a single line? If so, I haven't figured out the syntax. Example would be for concisely displaying custom dice graphics without spamming the chat with very "tall" cards for games with large dice pools.

3) Related dice pool subject: When trying to get dice pools with a variable number of dice to output to a single line (ignoring graphics for now), it seems like I have to explicitly check for each potential number of dice. A simple example:

!scriptcard {{ --=NumDice|?{How Many Dice?|1} --+NumDice=|[$NumDice] --?[$NumDice.Total] -eq 1|>RollAndOutput1 --?[$NumDice.Total] -eq 2|>RollAndOutput2 --?[$NumDice.Total] -eq 3|>RollAndOutput3 --?[$NumDice.Total] -gt 3|>TooManyDice --X| --:TooManyDice| --+Results|Many dice, Much sad --<| --:RollAndOutput1| --=R1|1d6 --+Results|[$R1] --<| --:RollAndOutput2| --=R1|1d6 --=R2|1d6 --+Results|[$R1] [$R2] --<| --:RollAndOutput3| --=R1|1d6 --=R2|1d6 --=R3|1d6 --+Results|[$R1] [$R2] [$R3] --<| }}

This isn't too bad with small dice pools, but can get crazy with larger pools and/or multiple pools with subsequent comparisons, etc. Loops and recursion work perfectly for variable dice (ala the Magic Missile example) as long as we output to separate lines, but I haven't figured out a way to do it with more concise output. Any thoughts?

Having a blast playing around with this, btw! Another tool in the utility belt. BatCards!

February 03 (4 years ago)

Edited February 03 (4 years ago)
David M.
Pro
API Scripter

Hmm, looks like Rolls can be dynamically named, e.g.

--=i|1
--=Roll[$i.Total]|1d6

This might be the trick!

February 03 (4 years ago)

Edited February 03 (4 years ago)
David M.
Pro
API Scripter

Almost there! Think I'm doing something stupid with the conditionals in the Output branch, as the macro below tries to output all three lines, when I only want one.


Trying to query for arbitrary number of dice, then roll them (dynamically creating Roll names in a recursive loop) and then output all in a single line.

I haven't figured out how to avoid the brute force explicit conditionals in the output branch yet, but it's more concise code than it was before (when you take out the debug output). Any tips on creating single-line output for any number of dice without making a huge number of conditionals would be appreciated :) Some kind of BuildOutput procedure that could append rolls and/or text?

!scriptcard {{
  --:Query and assign NumDice|
      --=NumDice|?{How Many Dice?|1}
                  --+debug_NumDice=|[$NumDice.Total]

  --:Initialize counter and call RollDiceLoop|
      --=i|1
      -->RollDiceLoop|

  --:Output|
      --+[#990000]Output[/#]|
      --?[$NumDice.Total] -eq 1|--+Rolls|[$Roll1]
      --?[$NumDice.Total] -eq 2|--+Rolls|[$Roll1] [$Roll2]
      --?[$NumDice.Total] -eq 3|--+Rolls|[$Roll1] [$Roll2]  [$Roll3]
  --X| Exit macro

  --:RollDiceLoop|
      --=Roll[$i.Total]|1d6
                  --+debugLoop_start|
                  --+debug_i|[$i]
                  --+debug_nested_Roll_i|[$Roll[$i.Total]]
      --=i|[$i] + 1
      --?[$i.Total] -le [$NumDice]|RollDiceLoop
  --<|
}}
February 03 (4 years ago)
Kurt J.
Pro
API Scripter


David M. said:

Almost there! Think I'm doing something stupid with the conditionals in the Output branch, as the macro below tries to output all three lines, when I only want one.


Trying to query for arbitrary number of dice, then roll them (dynamically creating Roll names in a recursive loop) and then output all in a single line.

I haven't figured out how to avoid the brute force explicit conditionals in the output branch yet, but more concise code than it was before (when you take out the debug output). Any tips on creating single-line output for any number of dice without making a huge number of conditionals would be appreciated :) Some kind of BuildOutput procedure that could append rolls and/or text?

!scriptcard {{
  --:Query and assign NumDice|
      --=NumDice|?{How Many Dice?|1}
                  --+debug_NumDice=|[$NumDice.Total]

  --:Initialize counter and call RollDiceLoop|
      --=i|1
      -->RollDiceLoop|

  --:Output|
      --+[#990000]Output[/#]|
      --?[$NumDice.Total] -eq 1|--+Rolls|[$Roll1]
      --?[$NumDice.Total] -eq 2|--+Rolls|[$Roll1] [$Roll2]
      --?[$NumDice.Total] -eq 3|--+Rolls|[$Roll1] [$Roll2]  [$Roll3]
  --X| Exit macro

  --:RollDiceLoop|
      --=Roll[$i.Total]|1d6
                  --+debugLoop_start|
                  --+debug_i|[$i]
                  --+debug_nested_Roll_i|[$Roll[$i.Total]]
      --=i|[$i] + 1
      --?[$i.Total] -le [$NumDice]|RollDiceLoop
  --<|
}}

Last night/early this morning I was working on another update, which I think you'll like. The new version will add string variable support (like roll variables, but they don't do any rolling), making what you are trying to do much easier (I had it roll 1500d6 and output each result as a test). I've also added a false branch option for conditionals, support for vfx, a couple new settings and a pass-through echo statement.

Here is a quick script using the new string variables:

!scriptcard {{
  --=NumDice|?{How Many Dice?|1}
  --+Rolling|[$NumDice.Total]d6
  
  --=DieCount|0
  --:Loop|
  --=DieCount|[$DieCount] + 1
  -->RollADie|
  --?[$DieCount] -lt [$NumDice]|Loop
  --+Results|[&DieSummary]
  --X|

  --:RollADie|
  --=ThisRoll|1d6
  --&DieSummary|+ [$ThisRoll]
  --<|
}}
and the result:

The update should be up on the GIST later tonight (I'll post about it with full details and update the wiki).

February 03 (4 years ago)
David M.
Pro
API Scripter

High five!

February 03 (4 years ago)
David M.
Pro
API Scripter

Looking at stored settings: is there a way to delete them?

February 03 (4 years ago)
Kurt J.
Pro
API Scripter


David M. said:

Looking at stored settings: is there a way to delete them?


This functionality will also be in the tonight's release.

February 03 (4 years ago)

Edited February 03 (4 years ago)
Kurt J.
Pro
API Scripter

ScriptCards Version 0.0.10 is up on the Development GIST

  • Added two new card settings: hideTitleCard and hideCard. Setting either to a non-zero value (the default) will cause either the title portion of the card (with the title and subtitle)  or the whole card itself will not be output. 
  • Added support for string variables (--&): Sting variables are maintained as a separate list from Roll Variables and function in most of the same ways. The biggest difference is that string variables do not attempt to do roll evaluation when setting them. A string variable can be directly set:

    --&MyString|Hello

    or text can be appended to a string variable by prefixing the content with a "+" sign:

    --&MyString|+ World

    String variables can be referenced with the syntax [&variablename] and do not support any properties (like .Total, etc from roll variables).
  • Added Visual Effects statement type (--V): The tag portion of the statement can be either "token" or "betweentokens", and the content portion is a list of parameters separated by spaces. For "token" effects, the parameters are SouceTokenID and EffectType ( --Vtoken|@{selected|token_id} burst-fire ). For "betweentokens" effects, the parameters are SourceTokenID, TargetTokenID, and EffectType ( --Vbetweentokens|@{selected|token_id} @{target|token_id} beam-magic ). The effect will play on the page that the source token is on. The EffectType specifiers follow the "shape"-"element" type system used in the FX dropdown (shapes like burst, nova, beam, breath, and elements like fire, magic, acid, poison).
  • Added an Echo statement type (--E): This is a simple statement that executes a sendChat command. The tag portion of the line is used as the speakingAs parameter and the content portion is used as the content of the message. Normal parsing occurs on the content and tags takes place before exeuction. For example:

    --eA ghost:|/em hovers around @{selected|character_name}

  • Conditionals now support an If False branch:  In a conditional, after the branch for true you can add a vertical bar (|) and a branch for a false result. None, one, or both branches can be gosub branches, and gosub branches still accept parameters as normal in both cases.
  • Deletion of Settings Groups: The !sc-liststoredsettings command now also provides a button next to each setting group to allow them to be deleted.

The Wiki page has been updated to reflect these changes.

February 04 (4 years ago)
David M.
Pro
API Scripter

v10 looks awesome!

Question about conditional text output syntax. Tried a few variations, but not getting expected results. I'm probably doing something stupid.

With this syntax, the text always displays regardless of what value I set to "Roll" 

!scriptcard {{
  --+Test|
  --=Roll|0
  --?[Roll.Total] -eq 1|--+This shouldn't display|
}}

With this syntax, it never displays regardless of roll value

!scriptcard {{
  --+Test|
  --=Roll|1
  --?[Roll.Total] -eq 1|+This should display|
}}

Is conditional direct text supported, or do I need to call a procedure or a goto?

Having trouble with If/else combined with string variable assignment (so many pipes | maybe causing issues?), and also with passing different params to the same procedure to allow re-use, but it's late and I need some sleep so I'll save those for later :) Sorry for being such a pain!

February 04 (4 years ago)
Kurt J.
Pro
API Scripter


David M. said:

v10 looks awesome!

Question about conditional text output syntax. Tried a few variations, but not getting expected results. I'm probably doing something stupid.

With this syntax, the text always displays regardless of what value I set to "Roll" 

!scriptcard {{
  --+Test|
  --=Roll|0
  --?[Roll.Total] -eq 1|--+This shouldn't display|
}}

With this syntax, it never displays regardless of roll value

!scriptcard {{
  --+Test|
  --=Roll|1
  --?[Roll.Total] -eq 1|+This should display|
}}

Is conditional direct text supported, or do I need to call a procedure or a goto?

Having trouble with If/else combined with string variable assignment (so many pipes | maybe causing issues?), and also with passing different params to the same procedure to allow re-use, but it's late and I need some sleep so I'll save those for later :) Sorry for being such a pain!

Conditionals only support branching, not conditional execution of other statement types. This was intentional to avoid confusion because line breaks are ignored by the script parser (same as PowerCards)... It was not uncommon for people to ask why something like:


--?? $Attack.base == 20 ??|--One|Do Something --Two|Do something else --Three|Yet another thing

Would run Two and Three even if Attack.base wasn't 20. Requiring branching add a little complexity when you only want to do one thing, but I think makes it more obvious what is going to execute. 



February 04 (4 years ago)
David M.
Pro
API Scripter

Got it, thanks for the clarification!