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

Scritpcard API Working and Sharing.

1618761745

Edited 1629489963
Please only post working scripts . Troubleshooting post in this forum   Script-scriptcards-my-spiritual-successor-to-powercards If you have working ScriptCards and wish to share the code please post here. Post the game it's for example D&D 5E, the code, Description of what it does and if possible a screenshot the the output. Also Thank you Kurt for all your hard work and everyone willing to share.    Index thanks to David M and Thank you to all who contribute to this thread. You could save people hours and inspire others. I have 7000 hours into roll20 and a lot of that time is improving things for my players.   Here's what we have so far. Utilities Spellbook  -  link DM Toolkit :  Character/Party Info -  link UDL Party Report  -  link Party Spawn  -  link     (Notes on future proofing) -  link to Spawn script thread Monster Knowledge  -  link 5e Page Report  - link  5e Display Passive Perception for All Tokens on Page   -  link Heal Everyone by Kurt J  -link Scriptcard Format Utility by Will M Ver.08  -link Health Check  -link System-specific 5e Mob Attacks  -  link 5e Saving Throws  -  link 5e Skill Checks  -  link 5e Turn Undead  -  link 5e Thunderwave  -  link 5e Conjure Animals  -  link 5e Vampiric Touch D&D 5e Spell  -  link 5e Bag Of Tricks Magic Item  -  link 5e Lightning Bolt (Easily changeable for other line-based spells)  - link 5e Condition Marker and Marker Legend  - link 5e Cantrip Poison Spray spell  -link 5e Frost Fingers  -link 5e Monk Flurry of Blows with Way of the Open Fist  -link 5e Shove Attack action -  Link 5e Heal Everyone  -link Tricks/tips/algorithms Displaying multiple rollable table image results on a single line  -  link Sort Die Rolls  -  link Items D&D 5e Dawnbringer  -link
1619127891

Edited 1627940896
SpellBook version 2.0 This is still a work in progress, but I'll update this post as it matures.  Basic functionality I'm going for: Lists all spells for a selected character, indicating which ones are prepared, require concentration and can be cast as ritual Provides buttons to 1) see details, 2) prepare/toggle 3) cast Next Steps Add Slots remaining/max to level header Add "At higher levels" to spell description details Add ability to cast both attack and non-attack spells and auto-deduct from spell counts Add ability to toggle prepare flag (and limit prepared spells to max available) Better support sorcerers (Sorcery Points) Continue to clean up the look of the cards (font and color suggestions welcome) Add options to whisper spell description to GM or other players !scriptcard {{ --/|Script Name : Spellbook --/|Version : 2.0 --/|Requires SC : 1.3.7+, --/|Author : Will M. --/|Description : Spellbook utility, allows user to see prepared spells, remaining slots, --/| spell details, and even cast some spells --#reentrant|Spellbook --#titlefontsize|1.2em --#subtitlefontsize|1.0em --#titlecardbackground|#800080 --#titlefontface|Tahoma --#bodyfontface|Tahoma --#tableborderradius|3px --#buttonfontsize|small --#buttontextcolor|#800080 --#buttonbordercolor|#FFFFFF --#buttonbackground|#FFFFFF --#oddRowBackground|#FFFFFF --#evenRowBackground|#FFFFFF --#whisper|self --#sourceToken|@{selected|token_id} --#title|Spell Book --#leftsub|@{selected|character_name} (@{selected|caster_level}) --#debug|0 --+Spell Attack Bonus: |[b][*S:spell_attack_bonus][/b] --+Spell Save DC: |[b][*S:spell_save_dc][/b] --&SCA|[*S:spellcasting_ability] --~SCA|string;substring;3;3;[&SCA] --+Spell Casting Ability: |[b][&SCA][/b] -->REPORTSPELLS|cantrip -->REPORTSPELLS|1 -->REPORTSPELLS|2 -->REPORTSPELLS|3 -->REPORTSPELLS|4 -->REPORTSPELLS|5 -->REPORTSPELLS|6 -->REPORTSPELLS|7 -->REPORTSPELLS|8 -->REPORTSPELLS|9 --X| DONE --:REPORTSPELLS|Parameter: Level --&zLvl|[%1%] --Rfirst|@{selected|character_id};repeating_spell-[&zLvl] --?"[*R:spellname]" -eq NoRepeatingAttributeLoaded|Done --&STblStyle1|"width:100%;text-align:center;padding:5px;border-spacing:0px;border-collapse:collapse;text-shadow: 1px 1px 3px purple;border: 1px dashed purple;" --&LvlDesc|Cantrip --&zLvlSlots| --?[&zLvl] -eq cantrip|SKIPCANTRIP --&LvlDesc|Level [&zLvl] --=SlotsTotal|[*S:lvl[&zLvl]_slots_total] --=SlotsExpended|[*S:lvl[&zLvl]_slots_expended] --&zLvlSlots|Slots [b][$SlotsExpended.Total][/b] of [b][$SlotsTotal.Total][/b] remaining --:SKIPCANTRIP| --&STbl|[t style=[&STblStyle1]][tr][td][&LvlDesc][/td][td][&zLvlSlots][/td][/tr][/t] --+|[&STbl] --:DisplayLoop| --?"[*R:spellname]" -eq NoRepeatingAttributeLoaded|Done --&zRIT|[r] --?"[*R:spellritual]" -inc "Yes"|ENDRIT --&zRIT| --:ENDRIT| --&zCON|[c] --?"[*R:spellconcentration]" -inc "concentration=1"|ENDCON --&zCON| --:ENDCON| --?[&zLvl] -eq cantrip -or [*R:spellprepared] -eq 1|PREPARED --+|⬜️[rbutton]🔎[*R:spellname]::SPELLDETAILS;[*R:spellname]\repeating_spell-[&zLvl]\spellname[/rbutton] [i][*R:innate] [&zCON][&zRIT][/i] --^ENDIF-1| --:PREPARED| --+|✅[rbutton]🔎[*R:spellname]::SPELLDETAILS;[*R:spellname]\repeating_spell-[&zLvl]\spellname[/rbutton] [i][*R:innate] [&zCON][&zRIT][/i] --:ENDIF-1| --Rnext| -->DisplayLoop| --:Done| --<| --:SPELLDETAILS| --/+ReEntryVal|[&reentryval] --~rArgs|string;split;\;[&reentryval] --/+Split|[&rArgs]: [&rArgs1], [&rArgs2], [&rArgs3] --Rfind|@{selected|character_id};[&rArgs1];[&rArgs2];[&rArgs3] --Rdump| --#title|[*R:spellname] [*R:innate] --#leftsub|@{selected|character_name} (@{selected|caster_level}) --#rightsub|[*R:spellschool] [*R:spelllevel] --#oddRowBackground|#eeeeee --#evenRowBackground|#ffffff --+Casting Time:|[*R:spellcastingtime] --+Range:|[*R:spellrange] --+Target:|[*R:spelltarget] --&zSCV|V --?"[*R:spellcomp_v]" -inc "v=1"|ENDSCV --&zSCV| --:ENDSCV| --&zSCS|S --?"[*R:spellcomp_s]" -inc "s=1"|ENDSCS --&zSCS| --:ENDSCS| --&zSCM|M --?"[*R:spellcomp_m]" -inc "m=1"|ENDSCM --&zSCM| --:ENDSCM| --+Components:|[&zSCV][&zSCS][&zSCM] [i]([*R:spellcomp_materials])[/i] --+Duration:|[*R:spellduration] --+|[*R:spelldescription] --~Len|string;length;[*R:spellathigherlevels] --?[$Len] -le 5|END_HV_CHECK --+|[b][i]At Higher Levels.[/i][/b][*R:spellathigherlevels] --:END_HV_CHECK| --+|[c][sheetbutton]💫 Cast Spell 🧙::@{selected|character_name}::[&rArgs2]_[*R:xxxActionIDxxxx]_spell[/sheetbutton][/c] --+|[c][b]Spell Save DC[/b] @{selected|spell_save_dc}[/c] --X| --<| --:PREPARESPELL| --#title|Prepare Spell Toggle --+NOT YET SUPPORTED| --X| --<| }}
That looks pretty amazing.  I might yoink it for future sessions.  Sadly theres no way to get this scripts chat output to fire CRL triggers right?  I know that CRL ignores groupinit and groupcheck api's.  
1619146803

Edited 1619147016
DM Eddie said: That looks pretty amazing.  I might yoink it for future sessions.  Sadly theres no way to get this scripts chat output to fire CRL triggers right?  I know that CRL ignores groupinit and groupcheck api's.   I'm not familiar with the term "CRL triggers"?  I do know that there is an example on the main ScriptCards thread showing how to do a Fireball, which I assume would include a group Dex check.  Explain a little more of what your looking to automate. I did just figure out how to initiate Attack based spells.  It's in the code I just posted.
Customizeable Roll Listener is an API that sits in the background and will fire events for you when certain things are entered into chat.  I currently use it for critical successes on the "atkdmg" 5e OGL templates and critical fumbles on the same template.
How would you use CRL with a script like SpellBook?
Thats what I was saying, I can't use scriptcards or powercards api cause I need my players to use sheet templates for chat cause I need the roll in the game not in the sandbox for it to work.  
This looks great! Set it up for my spellcasting players now, will test it next session (thursday). Will M. said: SpellBook version 0.3 This is still a work in progress, but I'll update this post as it matures.  Basic functionality I'm going for: Lists all spells for a selected character, indicating which ones are prepared, require concentration and can be cast as ritual Provides buttons to 1) see details, 2) prepare/toggle 3) cast Next Steps Add Slots remaining/max to level header Add "At higher levels" to spell description details Add ability to cast both attack and non-attack spells and auto-deduct from spell counts Add ability to toggle prepare flag (and limit prepared spells to max available) Better support sorcerers (Sorcery Points) Continue to clean up the look of the cards (font and color suggestions welcome) Add SoundFX options Add options to whisper spell description to GM or other players
1619893767

Edited 1620228816
DM Toolkit:  Character/Party Info Version 1.5 Update 5.5.2021:  Added UDL Report /w Page Properties.  Added small button at bottom of subcards to redisplay top memu.  Cleaned up the menu card.   Update 5.3.2021:  Added a basic Party UDL Report and replaced emoji graphics with HTML Escape Codes The following Scriptcard macro is my goto kit for reviewing player and party info.  Will report on any page token assigned to a player.  With it you can view: Party Info: Party Health Party Funds Party Resources Character Details: Character Sheet summary Attacks Features and Traits  Proficiencies Spell Book /w  details and ability to cast Inventory  Resources (Class, other and Repeating) Tools and Custom Skills Future Enhancements: Include NPCs option Include a Page Statistics report Inlcude a UDL report ( Page settings , Player Tokens , Other Tokens) Add small button somewhere on every subcard to display the top level card again.  Improve card look Include a report of all map tokens option Ability to adjust things like resources or prepared spells Requirements :  Scriptcards 1.2.2 or better. Select at least one token on the map. !scriptcard {{ --:___Formatting___| --:TOP| --#reentrant|CharReports --#title|Party/Char Reports --#titleCardBackground|#03038a --#oddRowBackground|#d8d8e6 --#evenRowBackground|#FFFFFF --#buttonbackground|#FFFFFF --#buttontextcolor|#000000 --#buttonbordercolor|#FFFFFF --#bodyFontSize|11px --#whisper|gm --#debug|1 --~tokencnt|array;pagetokens;alltokens;@{selected|token_id} --/|Loop through all of the tokens in "alltokens" --~TokenId|array;getfirst;alltokens --&CharId|[*[&TokenId]:t-represents] --?[&TokenId] -eq ArrayError|ENDLOOP --+|[c][b]Party Reports[/b][/c] --+|[c][rbutton]💗::PARTY_HEALTH_REPORT;[&CharId]\[&TokenId]\[/rbutton] [rbutton]🔠::PARTY_RESOURCES_REPORT;[&CharId]\[&TokenId]\[/rbutton] [rbutton]💰::PARTY_FUNDS_REPORT;[&CharId]\[&TokenId]\[/rbutton] [rbutton]👓::PARTY_UDL_REPORT[/rbutton] [/c] --&TblStyle1|"width:100%;text-align:left;padding:1px;border-spacing:1px;border-collapse:collapse;text-shadow: 0px 0px 0px black;border: 0px dashed black;" --&tbl|[t style=[&TblStyle1]] --:LOOPCHECK| --&CharId|[*[&TokenId]:t-represents] --/+Debug|[*[&TokenId]:t-name] --/|Skip targets that are not on the token layer or that don't represent creatures --?[*[&TokenId]:t-layer] -ne objects|CONTINUE --?"[*[&TokenId]:npc]" -eq 1|CONTINUE --?"[*[&TokenId]:t-represents]" -inc "-"|START --^CONTINUE| --:START| --&CharId|[*[&TokenId]:t-represents] -->SHORT_NAME|[*[&CharId]:character_name] --/+Debug|[&gSN] --&tbl|+ [tr][td style="width:100%;text-align:left;background-color:#d8d8e6"][b] [*[&CharId]:character_name][/b][/td][/tr] [tr][td style="width:100%;text-align:right;background-color:#ffffff"] [rbutton]📃::CHAR_DETAILS_REPORT;[&CharId]\[&TokenId]\[/rbutton] [rbutton]🏹::ATTACKS_REPORT;[&CharId]\[&TokenId]\[/rbutton] [rbutton]🎓::FEATURES_REPORT;[&CharId]\[&TokenId]\[/rbutton] [rbutton]🧗::PROF_REPORT;[&CharId]\[&TokenId]\[/rbutton] [rbutton]💫::SPELLBOOK_REPORT;[&CharId]\[&TokenId]\[/rbutton] [rbutton]🎒::INV_REPORT;[&CharId]\[&TokenId]\[/rbutton] [rbutton]🔠::RESOURCES_REPORT;[&CharId]\[&TokenId]\[/rbutton] [rbutton]🔨::TOOLS_REPORT;[&CharId]\[&TokenId]\[/rbutton] [/td][/tr] --:CONTINUE| --~TokenId|array;getnext;alltokens --?[&TokenId] -ne ArrayError|LOOPCHECK --:ENDLOOP| --&tbl|+ [/t] --+|[&tbl] --X| --/|================== Party Lighting Report ======================= --:PARTY_UDL_REPORT| (UDL_) --#title|UDL Lighting Report --#leftsub| --#rightsub| --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --#sourcetoken|@{selected|token_id} --#activepage|[*S:t-pageid] --&UDLEnabled|❌ --&DLModeEnabled|❌ --&ExpModeEnabled|❌ --&LUonDrop|❌ --&ForceLOS|❌ --&RestrictMvmt|❌ --&GlobalLight|❌ --&ForceLightRefresh|❌ --&LLFoW|❌ --&LLLigting|❌ --?"[*P:dynamic_lighting_enabled]" -ne "true"|UDL1_END --&UDLEnabled|💡 --:UDL1_END| --?"[*P:daylight_mode_enabled]" -ne "true"|UDL2_END --&DLModeEnabled|💡 --:UDL2_END| --?"[*P:explorer_mode]" -ne "basic"|UDL3_END --&ExpModeEnabled|💡 --:UDL3_END| --?"[*P:lightupdatedrop]" -ne "true"|UDL4_END --&LUonDrop|💡 --:UDL4_END| --?"[*P:lightenforcelos]" -ne "true"|UDL5_END --&ForceLOS|💡 --:UDL5_END| --?"[*P:lightrestrictmove]" -ne "true"|UDL6_END --&RestrictMvmt|💡 --:UDL6_END| --?"[*P:lightglobalillum]" -ne "true"|UDL7_END --&GlobalLight|💡 --:UDL7_END| --?"[*P:force_lighting_refresh]" -ne "true"|UDL8_END --&ForceLightRefresh|💡 --:UDL8_END| --?"[*P:showdarkness]" -ne "true"|UDL9_END --&LLFoW|💡 --:UDL9_END| --?"[*P:showlighting]" -ne "true"|UDLA_END --&LLLigting|💡 --:UDLA_END| --&Tbl|[t style="width:100%;"] --&Tbl|+ [tr][td style="text-align:center"][b][*P:name][/b][/td][/tr] --&Tbl|+ [tr][td style="text-align:center"][i](W:[*P:width] x H:[*P:height] Units:[*P:scale_units] #:[*P:scale_number])[/i][/td][/tr][/t] --+|[&Tbl] --&Tbl|[t style="width:100%"] --&Tbl|+ [tr][td]UDL[/td][td][&UDLEnabled][/td][td]Daylight Mode[/td][td][&DLModeEnabled][/td][/tr] --&Tbl|+ [tr][td]Explore[/td][td][&ExpModeEnabled][/td][td]Drop Mode[/td][td][&LUonDrop][/td][/tr] --&Tbl|+ [tr][td]Restrict Mvmt[/td][td][&RestrictMvmt][/td][td]GM Opacity[/td][td][*P:fog_opacity][/td][/tr] --&Tbl|+ [tr][td]Force LOS[/td][td][&ForceLOS][/td][td]Force Refresh[/td][td][&ForceLightRefresh][/td][/tr] --&Tbl|+ [tr][td]Global Illum[/td][td][&GlobalLight][/td][td][/td][td][/td][/tr] --&Tbl|+ [tr][td]FoW (LL)[/td][td][&LLFoW][/td][td]Legacy Lighting[/td][td][&LLLigting][/td][/tr] --&Tbl|+ [/t] --+|[&Tbl] --/+/UDL Enabled?| [*P:dynamic_lighting_enabled] --/+/Daylight Mode?| [*P:daylight_mode_enabled] --/+/Explorer Mode?| [*P:explorer_mode] --/+/Update on Drop?|[*P:lightupdatedrop] --/+/Force LOS?|[*P:lightenforcelos] --/+/Restrict Movement?|[*P:lightrestrictmove] --/+/Fog(LL)/GM Darkness(UDL) Opacity|[*P:fog_opacity] --/+/Global Light?|[*P:lightglobalillum] --/+/Force Light Refresh?|[*P:force_lighting_refresh] --/|Loop through all of the tokens in "alltokens" --~tokencnt|array;pagetokens;alltokens;@{selected|token_id} --~TokenId|array;getfirst;alltokens --?[&TokenId] -eq ArrayError|UDL_ENDLOOP --:UDL_LOOPCHECK| --&CharId|[*[&TokenId]:t-represents] --/|I added a flag in my player character sheets called PlayerCharacter and set it to 1 for all player controlled objects (themselves and their npc companions) --?"[*[&TokenId]:playercharacter]" -eq 1|UDL_PC --/|Otherwise - Skip targets that are not on the token layer or that don't represent characters --?[*[&TokenId]:t-layer] -ne objects|UDL_CONTINUE --?"[*[&TokenId]:t-represents]" -ninc "-"|UDL_CONTINUE --?"[*[&TokenId]:npc]" -eq 1|UDL_CONTINUE --:UDL_PC| --&CharId|[*[&TokenId]:t-represents] --/|Default icons to red X --&Vis|❌ --&NightVis|❌ --&BrightLight|❌ --&LowLight|❌ --/|Update Emoji icons based on UDL settings --?"[*[&TokenId]:t-has_bright_light_vision]" -ne "true"|NO_BLV --&Vis|👓 --:NO_BLV| --?"[*[&TokenId]:t-has_night_vision]" -ne "true"|NO_NV --&NightVis|🌙 --:NO_NV| --?"[*[&TokenId]:t-emits_bright_light]" -ne "true"|NO_BL --&BrightLight|💡 --:NO_BL| --?"[*[&TokenId]:t-emits_low_light]" -ne "true"|NO_LL --&LowLight|🕯 --:NO_LL| --+|[c][b] [*[&CharId]:character_name][/b] [/c] --+|[t style="width:100%"][tr][td style="width:50%;text-align:left"]Vision[/td] [td style="width:30%;text-align:center"][&Vis][/td][td style="width:10%;text-align:center"][/td][/tr] [tr][td style="width:50%;text-align:left"]Night Vision[/td] [td style="width:30%;text-align:center"][&NightVis][/td] [td style="width:20%;text-align:right"][*[&TokenId]:t-night_vision_distance] ft.[/td][/tr] [tr][td style="width:50%"][l]Emits Light[/l] [r][i]Bright[/i][/r][/td] [td style="width:30%;text-align:center"][&BrightLight][/td] [td style="width:20%;text-align:right"][*[&TokenId]:t-bright_light_distance] ft.[/td][/tr] [tr][td style="width:50%;text-align:right"][i]Low[/i][/td] [td style="width:30%;text-align:center"][&LowLight][/td] [td style="width:20%;text-align:right"][*[&TokenId]:t-low_light_distance] ft.[/td][/tr][/t] --:UDL_CONTINUE| --~TokenId|array;getnext;alltokens --?[&TokenId] -ne ArrayError|UDL_LOOPCHECK --:UDL_ENDLOOP| -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| --:UDL_PAGE_SETTINGS| Future addition --<| --:UDL_PLAYER_CONTROLLEDBY_NAMES| Future addition --<| --/|================== Party Health Report ======================= --:PARTY_HEALTH_REPORT| (PH_) --~Arg|string;split;\;[&reentryval] --&CharId|[&Arg1] --&TokenId|[&Arg2] --#title|Party Health --#leftsub| --#rightsub| --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --~tokencnt|array;pagetokens;alltokens;@{selected|token_id} --/|Loop through all of the tokens in "alltokens" --~TokenId|array;getfirst;alltokens --&CharId|[*[&TokenId]:t-represents] --?[&TokenId] -eq ArrayError|PH_ENDLOOP --&tbl|[t cellpadding="15" border="1" style="width:100%"][tr][td style="width:20%;text-align:left"][b]Char[/b][/td][td style="width:15%;text-align:center"][b]AC[/b][/td][td style="width:15%;text-align:center"][b]PP[/b][/td][td style="width:30%;text-align:center"][b]HP/Max[/b][/td][td style="width:20%;text-align:center"][b]Mad Lvl[/b][/td] [/tr] --:PH_LOOPCHECK| --&CharId|[*[&TokenId]:t-represents] --/|Skip targets that are not on the token layer or that don't represent creatures --?[*[&TokenId]:t-layer] -ne objects|PH_CONTINUE --?"[*[&TokenId]:t-represents]" -ninc "-"|PH_CONTINUE --?"[*[&TokenId]:npc]" -eq 1|PH_CONTINUE --&CharId|[*[&TokenId]:t-represents] -->SHORT_NAME|[*[&CharId]:character_name] --&tbl|+ [tr][td style="width:20%;text-align:left"][b][&gSN][/b][/td][td style="width:15%;text-align:center"][*[&CharId]:ac][/td][td style="width:15%;text-align:center"][*[&CharId]:passive_wisdom][/td][td style="width:30%;text-align:center"][*[&CharId]:hp] / [*[&CharId]:hp^][/td][td style="width:20%;text-align:center"][*[&CharId]:madness_level][/td] [/tr] --:PH_CONTINUE| --~TokenId|array;getnext;alltokens --?[&TokenId] -ne ArrayError|PH_LOOPCHECK --:PH_ENDLOOP| --&tbl|[&tbl] [/t] --+|[&tbl] -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| --<| --/|================== Party Funds Report ======================= --:PARTY_FUNDS_REPORT| (PF_) --~Arg|string;split;\;[&reentryval] --&CharId|[&Arg1] --&TokenId|[&Arg2] --#title|Party Funds --#leftsub| --#rightsub| --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --~tokencnt|array;pagetokens;alltokens;@{selected|token_id} --/|Loop through all of the tokens in "alltokens" --~TokenId|array;getfirst;alltokens --&CharId|[*[&TokenId]:t-represents] --=GTtlGP|0 --=TtlCP|0 --=TtlSP|0 --=TtlEP|0 --=TtlGP|0 --=TtlPP|0 --?[&TokenId] -eq ArrayError|PF_ENDLOOP --&tbl|[t cellpadding="15" border="1" style="width:100%"][tr][td style="width:12%;text-align:left"][b]Name[/b][/td][td style="width:14%;text-align:right"][b]cp[/b][/td][td style="width:14%";text-align:right"][r][b]sp[/b][/r][/td][td style="width:14%;text-align:right"][b]ep[/b][/td][td style="width:14%;text-align:right"][b]gp[/b][/td][td style="width:14%;text-align:right"][b]pp[/b][/td][td style="width:18%;text-align:right"][b]Ttl gp[/b][/td][/tr] --:PF_LOOPCHECK| --&CharId|[*[&TokenId]:t-represents] --/|Skip targets that are not on the token layer or that don't represent creatures --?[*[&TokenId]:t-layer] -ne objects|PF_CONTINUE --?"[*[&TokenId]:t-represents]" -ninc "-"|PF_CONTINUE --?"[*[&TokenId]:npc]" -eq 1|PF_CONTINUE --&CharId|[*[&TokenId]:t-represents] -->SHORT_NAME|[*[&CharId]:character_name] --=STtlGP|[*[&CharId]:cp] / 100 --=STtlGP|[*[&CharId]:sp] / 10 + [$STtlGP] --=STtlGP|[*[&CharId]:ep] / 2 + [$STtlGP] --=STtlGP|[*[&CharId]:gp] + [$STtlGP] --=STtlGP|[*[&CharId]:pp]*10 + [$STtlGP] --~STtlGP|math;round;[$STtlGP] --=GTtlGP|[$GTtlGP] + [$STtlGP] --=TtlCP|[*[&CharId]:cp] + [$TtlCP] --=TtlSP|[*[&CharId]:sp] + [$TtlSP] --=TtlEP|[*[&CharId]:ep] + [$TtlEP] --=TtlGP|[*[&CharId]:gp] + [$TtlGP] --=TtlPP|[*[&CharId]:pp] + [$TtlPP] --&tbl|+ [tr][td style="width:12%;text-align:left"][&gSN][/td][td style="width:14%;text-align:right"][*[&CharId]:cp][/td][td style="width:14%;text-align:right"][*[&CharId]:sp][/td][td style="width:14%;text-align:right"][*[&CharId]:ep][/td][td style="width:14%;text-align:right"][*[&CharId]:gp][/td][td style="width:14%;text-align:right"][*[&CharId]:pp][/td][td style="width:18%;text-align:right"][b][$STtlGP.Total][/b][/td][/tr] --:PF_CONTINUE| --~TokenId|array;getnext;alltokens --?[&TokenId] -ne ArrayError|PF_LOOPCHECK --:PF_ENDLOOP| --&tbl|+ [tr][td style="width:12%;text-align:right"][b]Total:[/b][/td][td style="width:14%;text-align:right"][b][$TtlCP.Total][/b][/td][td style="width:14%;text-align:right"][b][$TtlSP.Total][/b][/td][td style="width:14%;text-align:right"][b][$TtlEP.Total][/b][/td][td style="width:14%;text-align:right"][b][$TtlGP.Total][/b][/td][td style="width:14%;text-align:right"][b][$TtlPP.Total][/b][/td][td style="width:18%;text-align:right"][b][$GTtlGP.Total][/b][/td][/tr] --&tbl|[&tbl] [/t] --+|[&tbl] -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| --<| --/|================== Party Resources Report ======================= --:PARTY_RESOURCES_REPORT| (PR_) --~Arg|string;split;\;[&reentryval] --&CharId|[&Arg1] --&TokenId|[&Arg2] --#title|Party Resources --#leftsub| --#rightsub| --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --~tokencnt|array;pagetokens;alltokens;@{selected|token_id} --/|Loop through all of the tokens in "alltokens" --~TokenId|array;getfirst;alltokens --&CharId|[*[&TokenId]:t-represents] --?[&TokenId] -eq ArrayError|PR_ENDLOOP --&tbl|[t cellpadding="15" border="1" style="width:100%"][tr][td style="width:15%;text-align:left"][b]Char[/b][/td][td style="width:45%;text-align:left"][b]Resource[/b][/td][td style="width:20%;text-align:center"][b]Avail[/b][/td][td style="width:20%;text-align:center"][b]Total[/b][/td][/tr] --:PR_LOOPCHECK| --&CharId|[*[&TokenId]:t-represents] --/|Skip targets that are not on the token layer or that don't represent creatures --?[*[&TokenId]:t-layer] -ne objects|PR_CONTINUE --?"[*[&TokenId]:t-represents]" -ninc "-"|PR_CONTINUE --?"[*[&TokenId]:npc]" -eq 1|PR_CONTINUE --&CharId|[*[&TokenId]:t-represents] -->SHORT_NAME|[*[&CharId]:character_name] --&tbl|+ [tr][td style="width:15%;text-align:left"][&gSN][/td][td style="width:45%;text-align:left"][*[&CharId]:class_resource_name][/td][td style="width:20%;text-align:center"][*[&CharId]:class_resource][/td][td style="width:20%;text-align:center"][*[&CharId]:class_resource^][/td][/tr] --&tbl|+ [tr][td style="width:15%;text-align:left"][/td][td style="width:45%;text-align:left"][*[&CharId]:other_resource_name][/td][td style="width:20%;text-align:center"][*[&CharId]:other_resource][/td][td style="width:20%;text-align:center"][*[&CharId]:other_resource^][/td][/tr] --:PR_CONTINUE| --~TokenId|array;getnext;alltokens --?[&TokenId] -ne ArrayError|PR_LOOPCHECK --:PR_ENDLOOP| --&tbl|[&tbl] [/t] --+|[&tbl] -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| --<| --/|================== Character Details Report ======================= --:CHAR_DETAILS_REPORT| CDR_ --~Arg|string;split;\;[&reentryval] --&CharId|[&Arg1] --&TokenId|[&Arg2] --#title|[*[&TokenId]:t-name] --#rightsub|[*[&CharId]:race] --#oddRowBackground|#ffffff --#evenRowBackground|#ffffff --&t|[*[&CharId]:class]-[*[&CharId]:base_level] --?"[*[&CharId]:multiclass1_flag]" -eq "0"|CDR_DONE1 --&t|+ /[*[&CharId]:multiclass1] - [*[&CharId]:multiclass1_lvl] --?"[*[&CharId]:multiclass2_flag]" -eq "0"|CDR_DONE1 --&t|+ /[*[&CharId]:multiclass2] - [*[&CharId]:multiclass2_lvl] --?"[*[&CharId]:multiclass3_flag]" -eq "0"|CDR_DONE1 --&t|+ /[*[&CharId]:multiclass3] - [*[&CharId]:multiclass3_lvl] --:CDR_DONE1| --#leftsub|[&t] --+|[t style="border:2px solid black;width:100%"][tr style="background-color:#d8d8e6"][td style="width:15%;text-align:center"][b]Str[/b][/td] [td style="width:15%;text-align:center"][b]Dex[/b][/td] [td style="width:15%;text-align:center"][b]Con[/b][/td][td style="width:15%;text-align:center"][b]Int[/b][/td] [td style="width:15%;text-align:center"][b]Wis[/b][/td][td style="width:15%;text-align:center"][b]Cha[/b][/td][/tr] [tr style="border:1px solid black"] [td style="width:15%;text-align:center"][*[&CharId]:strength] ([*[&CharId]:strength_mod])[/td] [td style="width:15%;text-align:center"][*[&CharId]:dexterity] ([*[&CharId]:dexterity_mod])[/td] [td style="width:15%;text-align:center"][*[&CharId]:constitution] ([*[&CharId]:constitution_mod])[/td][td style="width:15%;text-align:center"][*[&CharId]:intelligence] ([*[&CharId]:intelligence_mod])[/td] [td style="width:15%;text-align:center"][*[&CharId]:wisdom] ([*[&CharId]:wisdom_mod])[/td][td style="width:15%;text-align:center"][*[&CharId]:charisma] ([*[&CharId]:charisma_mod])[/td][/tr][/t] --+|[t style="border:0px solid black;width:96%"] [tr][td style="width:25%;text-align:right"][b]AC: [/b] [/td][td style="width:20%;text-align:center"][*[&CharId]:ac][/td] [td style="width:25%;text-align:right"][b]HP: [/b] [/td][td style="width:20%;text-align:center"][*[&CharId]:hp]/[*[&CharId]:hp^][/td][/tr] [tr][td style="width:25%;text-align:right"][b]Speed: [/b] [/td][td style="width:20%;text-align:center"][*[&CharId]:speed][/td] [td style="width:25%;text-align:right"][b]PP: [/b] [/td][td style="width:20%;text-align:center"][*[&CharId]:passive_wisdom][/td][/tr] [tr][td style="width:25%;text-align:right"][b]Init B.: [/b] [/td][td style="width:20%;text-align:center"][*[&CharId]:initiative_bonus][/td] [td style="width:25%;text-align:right"][b]Prof B.: [/b] [/td][td style="width:20%;text-align:center"][*[&CharId]:pb][/td][/tr][/t] --/| Strength based saves/skills --+|[t style="border:1px solid black;width:100%"] [tr style="background-color:#d8d8e6"][td colspan=4 style="width:100%;text-align:center"][b]Strength [i](Save:[*[&CharId]:strength_save_bonus])[/i][/b][/td][/tr] [tr][td colspan=4 style="width:100%;text-align:center"]Athletics: [*[&CharId]:athletics_bonus][/td][/tr][/t] --/| Dex based saves/skills --+|[t style="border:1px solid black;width:100%"] [tr style="background-color:#d8d8e6"][td colspan=4 style="width:100%;text-align:center"][b]Dexterity [i](Save:[*[&CharId]:dexterity_save_bonus])[/i][/b][/td][/tr] [tr][td style="width:40%;text-align:right"]Acrobatics:[/td] [td style="width:10%;text-align:center"] [*[&CharId]:acrobatics_bonus][/td] [td style="width:40%;text-align:right"]SoH:[/td] [td style="width:10%;text-align:center"][*[&CharId]:sleight_of_hand_bonus][/td][/tr] [tr][td colspan=4 style="width:100%;text-align:center"]Stealth: [*[&CharId]:stealth_bonus][/td][/tr][/t] --/| Con based saves/skills --+|[t style="border:1px solid black;width:100%"] [tr style="background-color:#d8d8e6"][td colspan=4 style="width:100%;text-align:center"][b]Constitution [i](Save:[*[&CharId]:constitution_save_bonus])[/i][/b][/td][/tr][/t] --/| Intel based saves/skills --+|[t style="border:1px solid black;width:100%"] [tr style="background-color:#d8d8e6"][td colspan=4 style="width:100%;text-align:center"][b]Intelligence [i](Save:[*[&CharId]:intelligence_save_bonus])[/i][/b][/td][/tr] [tr][td style="width:40%;text-align:right"]Arcana:[/td] [td style="width:10%;text-align:center"] [*[&CharId]:arcana_bonus][/td] [td style="width:40%;text-align:right"]History:[/td] [td style="width:10%;text-align:center"] [*[&CharId]:history_bonus][/td][/tr] [tr][td style="width:40%;text-align:right"]Investigation:[/td] [td style="width:10%;text-align:center"] [*[&CharId]:investigation_bonus][/td] [td style="width:40%;text-align:right"]Nature:[/td] [td style="width:10%;text-align:center"] [*[&CharId]:nature_bonus][/td][/tr] [tr][td colspan=4 style="width:100%;text-align:center"]Religion: [*[&CharId]:religion_bonus][/td][/tr][/t] --/| Wisdom based saves/skills --+|[t style="border:1px solid black;width:100%"] [tr style="background-color:#d8d8e6"][td colspan=4 style="width:100%;text-align:center"][b]Wisdom [i](Save:[*[&CharId]:wisdom_save_bonus])[/i][/b][/td][/tr] [tr][td style="width:40%;text-align:right"]Animal Hand:[/td] [td style="width:10%;text-align:center"] [*[&CharId]:animal_handling_bonus][/td] [td style="width:40%;text-align:right"]Insight:[/td] [td style="width:10%;text-align:center"] [*[&CharId]:insight_bonus][/td][/tr] [tr][td style="width:40%;text-align:right"]Medicine:[/td] [td style="width:10%;text-align:center"] [*[&CharId]:medicine_bonus][/td] [td style="width:40%;text-align:right"]Perception:[/td] [td style="width:10%;text-align:center"] [*[&CharId]:perception_bonus][/td][/tr] [tr][td colspan=4 style="width:100%;text-align:center"]Survival: [*[&CharId]:survival_bonus][/td][/tr][/t] --/| Charisma based saves/skills --+|[t style="border:1px solid black;width:100%"] [tr style="background-color:#d8d8e6"][td colspan=4 style="width:100%;text-align:center"][b]Charisma [i](Save:[*[&CharId]:charisma_save_bonus])[/i][/b][/td][/tr] [tr][td style="width:40%;text-align:right"]Deciption:[/td] [td style="width:10%;text-align:center"] [*[&CharId]:deception_bonus][/td] [td style="width:40%;text-align:right"]Intimidation:[/td] [td style="width:10%;text-align:center"] [*[&CharId]:intimidation_bonus][/td][/tr] [tr][td style="width:40%;text-align:right"]Performance:[/td] [td style="width:10%;text-align:center"] [*[&CharId]:performance_bonus][/td] [td style="width:40%;text-align:right"]persuasion:[/td] [td style="width:10%;text-align:center"] [*[&CharId]:persuasion_bonus][/td][/tr][/t] --/| ===== Global Attack Modifiers --&tbl|[t style="width:100%;text-align:center"][tr style="background-color:#d8d8e6"][td colspan=2][b][c] Global Modifiers [/c][/b][/td][/tr] --Rfirst|[&CharId];repeating_tohitmod --:CDR_LOOP1| --?"[*R:global_attack_active_flag]" -eq "1"|>CDR_ADDGM;[*R:global_attack_name](Atk);[*R:global_attack_roll]; --Rnext| --?"[*R:global_attack_name]" -ne "NoRepeatingAttributeLoaded"|CDR_LOOP1 --/| ===== Global Save Modifiers --Rfirst|[&CharId];repeating_savemod --:CDR_LOOP2| --?"[*R:global_save_active_flag]" -eq "1"|>CDR_ADDGM;[*R:global_save_name](Sav);[*R:global_save_roll] --Rnext| --?"[*R:global_save_name]" -ne "NoRepeatingAttributeLoaded"|CDR_LOOP2 --/| ===== Global Skill Modifiers --Rfirst|[&CharId];repeating_skillmod --:CDR_LOOP3| --?"[*R:global_skill_active_flag]" -eq "1"|>CDR_ADDGM;[*R:global_skill_name](Skl);[*R:global_skill_roll] --Rnext| --?"[*R:global_skill_name]" -ne "NoRepeatingAttributeLoaded"|CDR_LOOP3 --/| ===== Global AC Modifiers --Rfirst|[&CharId];repeating_acmod --:CDR_LOOP4| --?"[*R:global_ac_active_flag]" -eq "1"|>CDR_ADDGM;[*R:global_ac_name](AC);[*R:global_ac_val] --Rnext| --?"[*R:global_ac_name]" -ne "NoRepeatingAttributeLoaded"|CDR_LOOP4 --/| ===== Global Damage Modifiers --Rfirst|[&CharId];repeating_damagemod --:CDR_LOOP5| --?"[*R:global_damage_active_flag]" -eq "1"|>CDR_ADDGM;[*R:global_damage_name](Dmg);[*R:global_damage_damage] --Rnext| --?"[*R:global_damage_name]" -ne "NoRepeatingAttributeLoaded"|CDR_LOOP5 --+|[&tbl] [/t] -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| --:CDR_ADDGM| --&tbl|+ [tr][td style="text-align:left"][%1%][/td] [td style="text-align:right"]([%2%])[/td][/tr] --<| --<| --:ATTACKS_REPORT| (ATK_) --~Arg|string;split;\;[&reentryval] --&CharId|[&Arg1] --&TokenId|[&Arg2] --#title|Attacks --#leftsub|[*[&TokenId]:t-name] --#rightsub| --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --Rfirst|[&CharId];repeating_attack --rDump| --&tbl| --:ATK_LOOP_TOP| --?"[*R:name]" -eq NoRepeatingAttributeLoaded|ATK_LOOP_END --&tbl|+ [tr][td style="width:60%;text-align:left"][rbutton][*R:atkname]::ATTACK_DETAILS;[&CharId]\[&TokenId]\[*R:atkname]\1[/rbutton][/td][td style="width:10%;text-align:center"][*R:atkbonus][/td][td style="width:30%;text-align:center"][*R:atkdmgtype][/td][/tr] --Rnext| --^ATK_LOOP_TOP|Back to top of loop --:ATK_LOOP_END| --&tbl|[t border="1" style="width:100%"][tr][td style="width:60%;text-align:left"][b]Attack[/b][/td][td style="width:10%;text-align:center"][b]Bonus[/b][/td][td style="width:30%;text-align:center"][b]Dmg[/b][/td][/tr][&tbl][/t] --+|[&tbl] -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| --<| --/|================== Attack Details ======================= --:ATTACK_DETAILS| (ATKD_) --~Arg|string;split;\;[&reentryval] --/+Debug Args| [$ArgCount] [&Arg1] [&Arg2] [&Arg3] [&Arg4] --&CharId|[&Arg1] --&TokenId|[&Arg2] --&AtkName|[&Arg3] --#title|Attack Details --#leftsub|[*[&TokenId]:t-name] --#rightsub|[&AtkName] --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --Rfind|[&CharId];[&AtkName];repeating_attack;atkname --rDump| --?"[*R:atkname]" -eq NoRepeatingAttributeLoaded|ATKD_DONE --+Bonus:| [*R:atkbonus] to Hit --+Damage:| [*R:atkdmgtype] --+Type:| [*R:dmgtype] --+Range:| [*R:atkrange] --/+rollbase:| [*R:rollbase] --+Desc:| [*R:atk_desc] --:ATKD_DONE| -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| Exit --<| --/|================== Spellbook Report ======================= --:SPELLBOOK_REPORT| (SB_) --/+Debug|ReentryVal: [&reentryval] --~Arg|string;split;\;[&reentryval] --&CharId|[&Arg1] --&TokenId|[&Arg2] --#title|Spell Book --#leftsub|[*[&TokenId]:t-name] [*[&CharId]:caster_level] --#rightsub| --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --+Spell Attack Bonus: |[b][*[&CharId]:spell_attack_bonus][/b] --+Spell Save DC: |[b][*[&CharId]:spell_save_dc][/b] --&SCA|[*[&CharId]:spellcasting_ability] --~SCA|string;substring;3;3;[&SCA] --+Spell Casting Ability: |[b][&SCA][/b] -->REPORTSPELLS|cantrip -->REPORTSPELLS|1 -->REPORTSPELLS|2 -->REPORTSPELLS|3 -->REPORTSPELLS|4 -->REPORTSPELLS|5 -->REPORTSPELLS|6 -->REPORTSPELLS|7 -->REPORTSPELLS|8 -->REPORTSPELLS|9 -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| DONE --:REPORTSPELLS|Parameter: Level --&zLvl|[%1%] --Rfirst|[*[&CharId]:character_id];repeating_spell-[&zLvl] --?"[*R:spellname]" -eq NoRepeatingAttributeLoaded|SB_DONE --&STblStyle1|"width:100%;text-align:center;padding:5px;border-spacing:0px;border-collapse:collapse;text-shadow: 1px 1px 3px purple;border: 1px dashed purple;" --&LvlDesc|Cantrip --&zLvlSlots| --?[&zLvl] -eq cantrip|SB_SKIPCANTRIP --&LvlDesc|Level [&zLvl] --=SlotsTotal|[*[&CharId]:lvl[&zLvl]_slots_total] --=SlotsExpended|[*[&CharId]:lvl[&zLvl]_slots_expended] --&zLvlSlots|Slots [b][$SlotsExpended.Total][/b] of [b][$SlotsTotal.Total][/b] remaining --:SB_SKIPCANTRIP| --&STbl|[t style=[&STblStyle1]][tr][td][&LvlDesc][/td][td][&zLvlSlots][/td][/tr][/t] --+|[&STbl] --:SB_DISPLAYLOOP| --?"[*R:spellname]" -eq NoRepeatingAttributeLoaded|SB_DONE --&zRIT|[r] --?"[*R:spellritual]" -inc "Yes"|SB_ENDRIT --&zRIT| --:SB_ENDRIT| --&zCON|[c] --?"[*R:spellconcentration]" -inc "concentration=1"|SB_ENDCON --&zCON| --:SB_ENDCON| --?[&zLvl] -eq cantrip -or [*R:spellprepared] -eq 1|SB_PREPARED --+|⬜[rbutton]🔎[*R:spellname]::SPELL_DETAILS;[*R:spellname]\repeating_spell-[&zLvl]\spellname[/rbutton] [i][*R:innate] [&zCON][&zRIT][/i] --^SB_ENDIF-1| --:SB_PREPARED| --+|✅[rbutton]🔎[*R:spellname]::SPELL_DETAILS;[*R:spellname]\repeating_spell-[&zLvl]\spellname[/rbutton] [i][*R:innate] [&zCON][&zRIT][/i] --:SB_ENDIF-1| --Rnext| --^SB_DISPLAYLOOP| --:SB_DONE| --<|Return --/|================== Spell Details ======================= --:SPELL_DETAILS| (SBD_) --/+ReEntryVal|[&reentryval] --~rArgs|string;split;\;[&reentryval] --/+Split|[&rArgs]: [&rArgs1], [&rArgs2], [&rArgs3] --Rfind|[*[&CharId]:character_id];[&rArgs1];[&rArgs2];[&rArgs3] --Rdump| --#title|[*R:spellname] [*R:innate] --#leftsub|[*[&CharId]:character_name] ([*[&CharId]:caster_level]) --#rightsub|[*R:spellschool] [*R:spelllevel] --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --+Casting Time:|[*R:spellcastingtime] --+Range:|[*R:spellrange] --+Target:|[*R:spelltarget] --&zSCV|V --?"[*R:spellcomp_v]" -inc "v=1"|SBD_ENDSCV --&zSCV| --:SBD_ENDSCV| --&zSCS|S --?"[*R:spellcomp_s]" -inc "s=1"|SBD_ENDSCS --&zSCS| --:SBD_ENDSCS| --&zSCM|M --?"[*R:spellcomp_m]" -inc "m=1"|SBD_ENDSCM --&zSCM| --:SBD_ENDSCM| --+Components:|[&zSCV][&zSCS][&zSCM] [i]([*R:spellcomp_materials])[/i] --+Duration:|[*R:spellduration] --+|[*R:spelldescription] --~Len|string;length;[*R:spellathigherlevels] --?[$Len] -le 5|SBD_END_HV_CHECK --+|[b][i]At Higher Levels.[/i][/b][*R:spellathigherlevels] --:SBD_END_HV_CHECK| --+|[c][sheetbutton]💫 Cast Spell 🧙::[*[&CharId]:character_name]::[&rArgs2]_[*R:xxxActionIDxxxx]_spell[/sheetbutton][/c] --+|[c][b]Spell Save DC[/b] [*[&CharId]:spell_save_dc][/c] -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| --<| --/|================== Charcter Features Report ======================= --:FEATURES_REPORT| (FTR_) --/+Debug|ReentryVal: [&reentryval] --~Arg|string;split;\;[&reentryval] --&CharId|[&Arg1] --&TokenId|[&Arg2] --#title|Features and Traits --#leftsub|[*[&TokenId]:t-name] --#rightsub| --#hidecard|0 --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --Rfirst|[&CharId];repeating_traits --rDump| --&C| --&R| --&F| --&BG| --&O| --:FTR_LOOP_TOP| --?"[*R:name]" -eq NoRepeatingAttributeLoaded|FTR_LOOP_END --/+OUTPUT|[*R:output] --&FName|[*R:name] --~FName|string;replace;:;+;[&FName] --/+Source|[*R:source] CLASS; RACIAL; FEAT; BACKGROUND --/+Source_Type|[*R:source_type] --/+Description|[*R:description] --C[*R:source]|CLASS:FTR_CLASS|RACIAL:FTR_RACIAL|FEAT:FTR_FEAT|BACKGROUND:FTR_BG| --&O|+ [tr][td][rbutton][*R:name]::FEATURE_DETAILS;[&CharId]\[&TokenId]\[*R:name][/rbutton]([*R:source])[/td][td][r][i][*R:source_type][/i][/r][/td][/tr] --^FTR_CONTINUE| --:FTR_CLASS| --&C|+ [tr][td][rbutton][*R:name]::FEATURE_DETAILS;[&CharId]\[&TokenId]\[&FName][/rbutton][/td][td][r][i][*R:source_type][/i][/r][/td][/tr] --^FTR_CONTINUE| --:FTR_RACIAL| --&R|+ [tr][td][rbutton][*R:name]::FEATURE_DETAILS;[&CharId]\[&TokenId]\[*R:name][/rbutton][/td][td][r][i][*R:source_type][/i][/r][/td][/tr] --^FTR_CONTINUE| --:FTR_FEAT| --&F|+ [tr][td][rbutton][*R:name]::FEATURE_DETAILS;[&CharId]\[&TokenId]\[*R:name][/rbutton][/td][td][r][i][*R:source_type][/i][/r][/td][/tr] --^FTR_CONTINUE| --:FTR_BG| --&BG|+ [tr][td][rbutton][*R:name]::FEATURE_DETAILS;[&CharId]\[&TokenId]\[*R:name][/rbutton][/td][td][r][i][*R:source_type][/i][/r][/td][/tr] --^FTR_CONTINUE| --:FTR_CONTINUE| --Rnext| --^FTR_LOOP_TOP|Back to top of loop --:FTR_LOOP_END| --+|[c][b]Class[/b][/c] --+|[t style="width:100%"][&C][/t] --+|[c][b]Racial[/b][/c] --+|[t style="width:100%"][&R][/t] --+|[c][b]Feats[/b][/c] --+|[t style="width:100%"][&F][/t] --+|[c][b]Background[/b][/c] --+|[t style="width:100%"][&BG][/t] --+|[c][b]Other[/b][/c] --+|[t style="width:100%"][&O][/t] -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| --<| --/|================== Charcter Feature Details ======================= --:FEATURE_DETAILS| (FTRD_) --~Arg|string;split;\;[&reentryval] --/+Debug Args| [$ArgCount] [&Arg1] [&Arg2] [&Arg3] --&CharId|[&Arg1] --&TokenId|[&Arg2] --&FtrName|[&Arg3] --~FtrName|string;replace;+;:;[&FtrName] --#title|Feature Details --#leftsub|[*[&TokenId]:t-name] --#rightsub|[&FtrName] --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --Rfind|[&CharId];[&FtrName];repeating_traits;name --rDump| --?"[*R:name]" -eq NoRepeatingAttributeLoaded|FTRD_DONE --+Source:| [*R:source] --+Source type:| [*R:source_type] --+Desc:| [*R:description] --+Flags:| Options:[*R:options_flag] Display:[*R:display_flag] --:FTRD_DONE| -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| Exit --<| --/|================== Proficencies Report ======================= --:PROF_REPORT| (PRF_) --~Arg|string;split;\;[&reentryval] --&CharId|[&Arg1] --&TokenId|[&Arg2] --#title|Proficencies --#leftsub|[*[&TokenId]:t-name] --#rightsub| --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --/| Push 6 character character_name into [&gSN] --Rfirst|[&CharId];repeating_proficiencies --rDump| --&L| --&W| --&A| --&O| --:PRF_LOOP_TOP| --?"[*R:name]" -eq NoRepeatingAttributeLoaded|PRF_LOOP_END --C[*R:prof_type]|LANGUAGE:PRF_LANG|WEAPON:PRF_WEAPON|ARMOR:PRF_ARMOR| --&O|+ [*R:name]([*R:prof_type]), --^PRF_CONTINUE| --:PRF_LANG| --&L|+ [*R:name], --^PRF_CONTINUE| --:PRF_WEAPON| --&W|+ [*R:name], --^PRF_CONTINUE| --:PRF_ARMOR| --&A|+ [*R:name], --^PRF_CONTINUE| --:PRF_CONTINUE| --Rnext| --^PRF_LOOP_TOP|Back to top of loop --:PRF_LOOP_END| --~Len|string;length;[&A] --=Len|[$Len.Total] - 1 --~Len|math;max;0,[$Len.Total] --~A|string;Left;[$Len.Total];[&A] --~Len|string;length;[&W] --=Len|[$Len.Total] - 1 --~Len|math;max;0,[$Len.Total] --~W|string;Left;[$Len.Total];[&W] --~Len|string;length;[&L] --=Len|[$Len.Total] - 1 --~Len|math;max;0,[$Len.Total] --~L|string;Left;[$Len.Total];[&L] --~Len|string;length;[&O] --=Len|[$Len.Total] - 1 --~Len|math;max;0,[$Len.Total] --~O|string;Left;[$Len.Total];[&O] --+|[t style="width:90%"][tr][td style="width:25%"][b]Armor[/b][/td][td style="width:75%"][&A][/td][/tr][/t] --+|[t style="width:90%"][tr][td style="width:25%"][b]Weapon[/b][/td][td style="width:75%"][&W][/td][/tr][/t] --+|[t style="width:90%"][tr][td style="width:25%"][b]Language[/b][/td][td style="width:75%"][&L][/td][/tr][/t] --+|[t style="width:90%"][tr][td style="width:25%"][b]Other[/b][/td][td style="width:75%"][&O][/td][/tr][/t] -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| --<| --/|================== Charcter Inventory Report ======================= --:INV_REPORT| (INV_) --~Arg|string;split;\;[&reentryval] --&CharId|[&Arg1] --&TokenId|[&Arg2] --#title|Inventory --#leftsub|[*[&TokenId]:t-name] --#rightsub| --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --Rfirst|[&CharId];repeating_inventory --rDump| --+|[c][b]Money[/b][/c] --=TtlGP|[*[&CharId]:cp] / 100 --=TtlGP|[*[&CharId]:sp] / 10 + [$TtlGP] --=TtlGP|[*[&CharId]:ep] / 2 + [$TtlGP] --=TtlGP|[*[&CharId]:gp] + [$TtlGP] --=TtlGP|[*[&CharId]:pp]*10 + [$TtlGP] --=TtlGP|[$TtlGP]*100 --~TtlGP|math;round;[$TtlGP] --=TtlGP|[$TtlGP]/100 --&tbl|[t style="width:90%;text-align:right"][tr][td style="width:15%;text-align:right"]cp[/td][td style="width:15%";text-align:right]sp[/td][td style="width:15%;text-align:right"]ep[/td][td style="width:15%;text-align:right"]gp[/td][td style="width:15%;text-align:right"]pp[/td][td style="width:25%;text-align:right"]Ttl(gp)[/td][/tr] --&tbl|+ [tr][td style="text-align:right"][*[&CharId]:cp][/td][td style="text-align:right"][*[&CharId]:sp][/td][td style="text-align:right"][*[&CharId]:ep][/td][td style="text-align:right"][*[&CharId]:gp][/td][td style="text-align:right"][*[&CharId]:pp][/td][td style="text-align:right"][$TtlGP.Total][/td][/tr][/t] --+|[&tbl] --&tbl| --+|[c][b]Items[/b][/c] --=ItemWt|0 --:INV_LOOP_TOP| --?"[*R:name]" -eq NoRepeatingAttributeLoaded|INV_LOOP_END --&E|🎒 --?[*R:equipped] -ne 1|INV_NOTEQUIPPED --&E|✋ --:INV_NOTEQUIPPED| --&tbl|+ [tr][td style="width:60%"][rbutton][*R:itemname]::INV_DETAILS;[&CharId]\[&TokenId]\[*R:itemname][/rbutton][/td][td style="width:13%;text-align:center"][*R:itemcount][/td][td style="width:13%;text-align:center"][&E][/td][td style="text-align:right;width:14%"][*R:itemweight][/td][/tr] --Rnext| --^INV_LOOP_TOP|Back to top of loop --:INV_LOOP_END| --=CC|15 * [*[&TokenId]:strength] --&CC|[$CC.Total] --&tbl|+ [tr][td style="text-align:left;width:60%"][b]Carrying: [$CC.Total]lbs[/b][/td][td][/td][td style="text-align:right;width:13%"][b]Total:[/b][/td][td style="text-align:right;width:14%"][r][b][*[&CharId]:weighttotal][/b][/r][/td][/tr] --&tbl|[t style="width:90%"][tr][td style="width:60%"][b]Item Name[/b][/td][td style="width:13%;text-align:center"][b]Cnt[/b][/td][td style="width:13%;text-align:center"][b]Eq[/b][/td][td style="text-align:center;width:14%"][r][b]Lbs[/b][/r][/td][/tr][&tbl][/t] --+|[&tbl] -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| --<| --/|================== Inv Details Report ======================= --:INV_DETAILS| (INVD_) --~Arg|string;split;\;[&reentryval] --/+Debug Args| [$ArgCount] [&Arg1] [&Arg2] [&Arg3] --&CharId|[&Arg1] --&TokenId|[&Arg2] --&ItemName|[&Arg3] --#title|Inventory Item Info --#leftsub|[*[&TokenId]:t-name] --#rightsub|[&ItemName] --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --Rfind|[&CharId];[&ItemName];repeating_inventory;name --rDump| --?"[*R:name]" -eq NoRepeatingAttributeLoaded|INVD_DONE --+Count:| [*R:count] --+Weight:| [*R:weight] --+Properties:| [*R:properties] --+Modifiers:| [*R:modifiers] --+Content:| [*R:content] --:INVD_DONE| -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| Exit --<| --/|================== Resource Summary Report ======================= --:RESOURCES_REPORT| RES_ --~Arg|string;split;\;[&reentryval] --&CharId|[&Arg1] --&TokenId|[&Arg2] --#title|Resources --#leftsub|[*[&TokenId]:t-name] --#rightsub| --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --/| First get the Class and Other Resources --&tbl|[t style="width:98%"][tr][td style="width:55%;text-align:left"][b]Resource[/b][/td][td style="width:15%";text-align:right][b]Total[/b][/td][td style="width:15%;text-align:right"][b]Exp[/b][/td][td style="width:15%;text-align:right"][b]Rem[/b][/td][/tr] --=ResExp|[*[&CharId]:class_resource] --=ResTotal|[*[&CharId]:class_resource^] --=ResRem|[$ResTotal]-[$ResExp] --&tbl|+ [tr style="background-color:#FFFFFF"][td style="width:55%;text-align:left"][*[&CharId]:class_resource_name][/td][td style="width:15%;text-align:right"][$ResTotal.Total][/td][td style="width:15%;text-align:right"][$ResExp.Total][/td][td style="width:15%;text-align:right"][$ResRem.Total][/td][/tr] --=ResExp|[*[&CharId]:other_resource] --=ResTotal|[*[&CharId]:other_resource^] --=ResRem|[$ResTotal]-[$ResExp] --&tbl|+ [tr style="background-color:#d8d8e6"][td style="width:55%;text-align:left"][*[&CharId]:other_resource_name][/td][td style="width:15%;text-align:right"][$ResTotal.Total][/td][td style="width:15%;text-align:right"][$ResExp.Total][/td][td style="width:15%;text-align:right"][$ResRem.Total][/td][/tr] --/| Then get the repeating resources --Rfirst|[&CharId];repeating_resource --rDump| --:RES_LOOP_TOP| --?"[*R:resource_left_name]" -eq NoRepeatingAttributeLoaded|RES_LOOP_END --=ResExp|[*R:resource_left] --=ResTotal|[*[&CharId]:resource_left^] --=ResRem|[$ResTotal]-[$ResExp] --&tbl|+ [tr style="background-color:#FFFFFF"][td style="width:55%;text-align:left"][*R:resource_left_name][/td][td style="width:15%;text-align:right"][$ResTotal.Total][/td][td style="width:15%;text-align:right"][$ResExp.Total][/td][td style="width:15%;text-align:right"][$ResRem.Total][/td][/tr] --=ResExp|[*R:resource_right] --=ResTotal|[*[&CharId]:resource_right^] --=ResRem|[$ResTotal]-[$ResExp] --&tbl|+ [tr style="background-color:#d8d8e6"][td style="width:55%;text-align:left"][*R:resource_right_name][/td][td style="width:15%;text-align:right"][$ResTotal.Total][/td][td style="width:15%;text-align:right"][$ResExp.Total][/td][td style="width:15%;text-align:right"][$ResRem.Total][/td][/tr] --Rnext| --^RES_LOOP_TOP|Back to top of loop --:RES_LOOP_END| --+|[C][&tbl][/C] -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| --<| --/|================== Tools Summary Report ======================= --:TOOLS_REPORT| TOOL_ --~Arg|string;split;\;[&reentryval] --&CharId|[&Arg1] --&TokenId|[&Arg2] --#title|Tools/Custom Skills --#leftsub|[*[&TokenId]:t-name] --#rightsub| --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --Rfirst|[&CharId];repeating_tool --rDump| --:TOOL_LOOP_TOP| --?"[*R:name]" -eq NoRepeatingAttributeLoaded|TOOL_LOOP_END --+[*R:toolname]|[*R:toolbonus_base] --Rnext| --^TOOL_LOOP_TOP|Back to top of loop --:TOOL_LOOP_END| -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| --<| --/|================== Page Tokens Report ======================= --:PAGE_TOKENS_REPORT| PT_ --#title|Token Summary --#leftsub| --#rightsub| --#oddRowBackground|#d8d8e6 --#evenRowBackground|#ffffff --&tbl| --~tokencnt|array;pagetokens;alltokens;@{selected|token_id} --/|Loop through all of the tokens in "alltokens" --~TokenId|array;getfirst;alltokens --&CharId|[*[&TokenId]:t-represents] --?[&TokenId] -eq ArrayError|PT_ENDLOOP --:PT_LOOPCHECK| --&CharId|[*[&TokenId]:t-represents] --/|Skip targets that are not on the token layer or that don't represent creatures --&tbl|+ [tr][td style="width:50%;text-align:left"][b][*[&TokenId]:t-name][/b][/td] [td style="width:50%;text-align:left"][*[&TokenId]:t-layer][/td] [/tr] [tr] [td colspan=2 style="width:50%;text-align:center"] [*[&TokenId]:t-type] / [*[&TokenId]:t-subtype][/td] --:PT_CONTINUE| --~TokenId|array;getnext;alltokens --?[&TokenId] -ne ArrayError|PT_LOOPCHECK --:PT_ENDLOOP| --&tbl|[t][&tbl][/t] --+|[&tbl] -->TOP_BUTTON| Add Top Button to bottom right corner of card --X| --<| --/|================== Utility Functions ======================= --:SHORT_NAME|Shortens player name for reporting purposes (6 characters); Parameter:Character_Name --~gSN|string;left;6;[%1%] --<| Return --:TOP_BUTTON| --+|[r][rbutton]🔺::TOP;[&CharId][/rbutton][/r] --<| }}
@Will M - I can't imagine how much time and effort you put into that.  Really exceptional.
Thanks, it's been a fun project.  It came together a little at a time as I learned the ScriptCards language.  I figured posting some code like this helps people learn through examples.  BTW - The Madness Level on the Party Health is tied to a custom attribute I added to my Out of the Abyss character sheets. 
Great job and ty for sharing.
I've been working on a party !Spawn script: !script {{ --#title|Party Spawn --#hideCard|1 --#sourcetoken|@{selected|token_id} --=Size|[*S:t-width] / 70 --:BuildParty| --&PartyString|@{Lists|PCs} --&PartyString|+@{Lists|NPCs} --~PartyString|string;split;|;[&PartyString] --=Num|2 --=HOffset|[$Size] / 2 + [$Size] --=Increment|[$HOffset] --=VOffset|0 --:SpawnLoop| --~PartyString[$Num]|string;after;,;[&PartyString[$Num]] --~PartyString[$Num]|string;replace;,;;[&PartyString[$Num]] --@forselected|Spawn _name|[*[&PartyString[$Num]]:character_name] _offset|[$HOffset],[$VOffset] _layer|objects _size|[$Size],[$Size] --=Num|[$Num] + 1 --?[$VOffset] -eq [$Increment]|>HShift|>VShift --?[$Num] -le [$PartyStringCount]|SpawnLoop --X| --:HShift| --=HOffset|[$HOffset] + [$Size] --=VOffset|0 --<| --:VShift| --=VOffset|[$Increment] --<| }} This is also uses two other macros that create the lists: !setattr --name Lists --NPCs|%NPCs%\|@{target|NPC|token_name},@{target|NPC|character_id} !setattr --name Lists --PCs|%PCs%\|@{target|PC|token_name},@{target|PC|character_id}
I might have to grab that one - I assume your "Lists" is a utility character sheet you use to track campaign data.  I use one called Mule for storing macros and campaign attributes.
1620134457
David M.
Pro
API Scripter
Nice, Colin! To help future-proof your Spawn call (if you use linked bar values), you probably want to set the bar values to the current hp, ac, etc. along with the --KeepLink command. See this post  on the Spawn thread for an example and for more background info on why this is usually preferable, but basically otherwise you may end up overwriting current sheet values with those of the default token. 
1620140066

Edited 1620144355
UDL Party Report This script does a quick UDL report for your player characters on the current page.  I've added it to my DM Toolkit above as well.   I'll add "UDL Page Settings" and "Character Controlled By names" to the report when I figure out how to acquire these data elements.    !scriptcards {{ --#title|UDL Lighting --#leftsub| --#rightsub| --#oddRowBackground|#eeeeee --#evenRowBackground|#ffffff --/|Loop through all of the tokens in "alltokens" --~tokencnt|array;pagetokens;alltokens;@{selected|token_id} --~TokenId|array;getfirst;alltokens --?[&TokenId] -eq ArrayError|UDL_ENDLOOP --:UDL_LOOPCHECK| --&CharId|[*[&TokenId]:t-represents] --/I added a flag in my player character sheets called PlayerCharacter and set it to 1 for all player controlled objects (themselves and their npc companions) --?"[*[&TokenId]:playercharacter]" -eq 1|UDL_PC --/|Otherwise - Skip targets that are not on the token layer or that don't represent characters --?[*[&TokenId]:t-layer] -ne objects|UDL_CONTINUE --?"[*[&TokenId]:t-represents]" -ninc "-"|UDL_CONTINUE --?"[*[&TokenId]:npc]" -eq 1|UDL_CONTINUE --:UDL_PC| --&CharId|[*[&TokenId]:t-represents] --/|Default icons to red X --&Vis|❌ --&NightVis|❌ --&BrightLight|❌ --&LowLight|❌ --/|Update Emoji icons based on UDL settings --?"[*[&TokenId]:t-has_bright_light_vision]" -ne "true"|NO_BLV --&Vis|👓 --:NO_BLV| --?"[*[&TokenId]:t-has_night_vision]" -ne "true"|NO_NV --&NightVis|🌙 --:NO_NV| --?"[*[&TokenId]:t-emits_bright_light]" -ne "true"|NO_BL --&BrightLight|💡 --:NO_BL| --?"[*[&TokenId]:t-emits_low_light]" -ne "true"|NO_LL --&LowLight|🕯 --:NO_LL| --+|[c][b] [*[&CharId]:character_name][/b] [/c] --+|[t style="width:100%"][tr][td style="width:50%;text-align:left"]Vision[/td] [td style="width:30%;text-align:center"][&Vis][/td][td style="width:10%;text-align:center"][/td][/tr] [tr][td style="width:50%;text-align:left"]Night Vision[/td] [td style="width:30%;text-align:center"][&NightVis][/td] [td style="width:20%;text-align:right"][*[&TokenId]:t-night_vision_distance] ft.[/td][/tr] [tr][td style="width:50%"][l]Emits Light[/l] [r][i]Bright[/i][/r][/td] [td style="width:30%;text-align:center"][&BrightLight][/td] [td style="width:20%;text-align:right"][*[&TokenId]:t-bright_light_distance] ft.[/td][/tr] [tr][td style="width:50%;text-align:right"][i]Low[/i][/td] [td style="width:30%;text-align:center"][&LowLight][/td] [td style="width:20%;text-align:right"][*[&TokenId]:t-low_light_distance] ft.[/td][/tr][/t] --:UDL_CONTINUE| --~TokenId|array;getnext;alltokens --?[&TokenId] -ne ArrayError|UDL_LOOPCHECK --:UDL_ENDLOOP| --X| }}
This is my Script for rolling Saving Throws. !scriptcard {{ --#title|Skill Roll --#emoteText|@{selected|token_name} --#sourceToken|@{selected|token_id} --#leftsub|[*S:character_name] --#rightsub|Attempting to do something. --#titleFontColor|#FFFFFF --#titleCardBackground|#135A9C --#evenRowBackground|#B6AB91 --#evenRowFontColor|#000000 --#oddRowBackground|#CEC7B6 --#oddRowFontColor|#000000 --#emoteBackground|#FFFFFF --#tableBorderRadius|8px --:Initial variable population| --=strength_save_bonus|[*S:strength_save_bonus] --=dexterity_save_bonus|[*S:dexterity_save_bonus] --=constitution_save_bonus|[*S:constitution_save_bonus] --=intelligence_save_bonus|[*S:intelligence_save_bonus] --=wisdom_save_bonus|[*S:wisdom_save_bonus] --=charisma_save_bonus|[*S:charisma_save_bonus] --:Type| --&Type|?{Saving Throw Type?|Strength,strength|Dexterity,dexterity|Constition,constition|Intelligence,intelligence|Wisdom,wisdom|Charisma,charisma} --+Type of Save : |[b][&Type][/b] --:Bonus| --=BonusType|[$[&Type]_save_bonus] --+Bonus| [$BonusType] --:Advantage, Disadvantage, Normal| --&RollType|?{Advantage or Disadvantage?|Normal,1d20|Advantage,2d20kh1|Disadvantage,2d20kl1} --:Roll| --=Save|[&RollType] + [$BonusType][Bonus] --+Saving Throw is|[$Save] }}
1620710848

Edited 1621949763
Update added GM version with ability to select NPC.  Skill check script. Enjoy. !scriptcard {{ --#title|Skill Check --#emoteText|@{selected|token_name} --#sourceToken|@{selected|token_id} --#leftsub|[*S:character_name] --#rightsub| --#titleFontColor|#FFFFFF --#titleCardBackground|#616161 --#evenRowBackground|#B6AB91 --#evenRowFontColor|#000000 --#oddRowBackground|#CEC7B6 --#oddRowFontColor|#000000 --#emoteBackground|#FFFFFF --#tableBorderRadius|8px --:Initial variable population| --=acrobatics_bonus|[*S:acrobatics_bonus] --=animal_handling_bonus|[*S:animal_handling_bonus] --=arcana_bonus|[*S:arcana_bonus ] --=athletics_bonus|[*S:athletics_bonus] --=deception_bonus|[*S:deception_bonus] --=history_bonus|[*S:history_bonus] --=insight_bonus|[*S:insight_bonus] --=intimidation_bonus|[*S:intimidation_bonus] --=investigation_bonus|[*S:investigation_bonus] --=medicine_bonus|[*S:medicine_bonus] --=nature_bonus|[*S:nature_bonus] --=perception_bonus|[*S:perception_bonus] --=performance_bonus|[*S:performance_bonus] --=persuasion_bonus|[*S:persuasion_bonus] --=religion_bonus|[*S:religion_bonus] --=sleight_of_hand_bonus|[*S:sleight_of_hand_bonus] --=stealth_bonus|[*S:stealth_bonus] --=survival_bonus|[*S:survival_bonus] --:Type| --&Type|?{Saving Throw Type?|Acrobatics,acrobatics|Animal Handling,animal_handling|Arcana,arcana|Athletics,athletics|Deception,deception|History,history|Insight,insight|Intimidation,intimidation|Investigation,investigation|Medicine,medicine|Nature,nature|Perception,perception|Performance,performance|Persuasion,persuasion|Religion,religion|Sleight of Hand,sleight_of_hand|Stealth,stealth|Survival,survival} --+Type of Skill Check: |[b][&Type][/b] --:Bonus| --=BonusType|[$[&Type]_bonus] --+Bonus| [$BonusType] --:Advantage, Disadvantage, Normal| --&RollType|?{Advantage or Disadvantage?|Normal,1d20|Advantage,2d20kh1|Disadvantage,2d20kl1} --:Roll| --=Save|[&RollType] + [$BonusType][Bonus] --+Saving Throw is|[$Save] }} Skill Check for GM includes PC and NPC.  !scriptcard {{ --#title|Skill Check --#emoteText|@{selected|token_name} Skill Check --#sourceToken|@{selected|token_id} --#leftsub|[*S:character_name] --#rightsub| --#whisper|gm --#titleFontColor|#FFFFFF --#titleCardBackground|#616161 --#evenRowBackground|#B6AB91 --#evenRowFontColor|#000000 --#oddRowBackground|#CEC7B6 --#oddRowFontColor|#000000 --#emoteBackground|#FFFFFF --#tableBorderRadius|8px --&CharacterType|?{NPC?|No,1|Yes,2} --?[&CharacterType] -eq 2|Other --:Initial variable population| --+|[c] [b] Player Character Skill Check [/b] [/c] --=acrobatics_bonus|[*S:acrobatics_bonus] --=animal_handling_bonus|[*S:animal_handling_bonus] --=arcana_bonus|[*S:arcana_bonus ] --=athletics_bonus|[*S:athletics_bonus] --=deception_bonus|[*S:deception_bonus] --=history_bonus|[*S:history_bonus] --=insight_bonus|[*S:insight_bonus] --=intimidation_bonus|[*S:intimidation_bonus] --=investigation_bonus|[*S:investigation_bonus] --=medicine_bonus|[*S:medicine_bonus] --=nature_bonus|[*S:nature_bonus] --=perception_bonus|[*S:perception_bonus] --=performance_bonus|[*S:performance_bonus] --=persuasion_bonus|[*S:persuasion_bonus] --=religion_bonus|[*S:religion_bonus] --=sleight_of_hand_bonus|[*S:sleight_of_hand_bonus] --=stealth_bonus|[*S:stealth_bonus] --=survival_bonus|[*S:survival_bonus] --^Type| --:Other| --+|[c] [b] NPC Skill Check [/b] [/c] --=acrobatics_bonus|[*S:npcd_acrobatics] --=animal_handling_bonus|[*S:npcd_animal_handling] --=arcana_bonus|[*S:npcd_arcana] --=athletics_bonus|[*S:npcd_athletics] --=deception_bonus|[*S:npcd_deception] --=history_bonus|[*S:npcd_history] --=insight_bonus|[*S:npcd_insight] --=intimidation_bonus|[*S:npcd_intimidation] --=investigation_bonus|[*S:npcd_investigation] --=medicine_bonus|[*S:npcd_medicine] --=nature_bonus|[*S:npcd_nature] --=perception_bonus|[*S:npcd_perception] --=performance_bonus|[*S:npcd_performance] --=persuasion_bonus|[*S:npcd_persuasion] --=religion_bonus|[*S:npcd_religion] --=sleight_of_hand_bonus|[*S:npcd_sleight_of_hand] --=stealth_bonus|[*S:npcd_stealth] --=survival_bonus|[*S:npcd_survival] --:Type| --&Type|?{Saving Throw Type?|Acrobatics,acrobatics|Animal Handling,animal_handling|Arcana,arcana|Athletics,athletics|Deception,deception|History,history|Insight,insight|Intimidation,intimidation|Investigation,investigation|Medicine,medicine|Nature,nature|Perception,perception|Performance,performance|Persuasion,persuasion|Religion,religion|Sleight of Hand,sleight_of_hand|Stealth,stealth|Survival,survival} --+Type of Skill Check: |[b][&Type][/b] --:Bonus| --=BonusType|[$[&Type]_bonus] --+Bonus| [$BonusType] --:Advantage, Disadvantage, Normal| --&RollType|?{Advantage or Disadvantage?|Normal,1d20|Advantage,2d20kh1|Disadvantage,2d20kl1} --:Roll| --=Save|[&RollType] + [$BonusType][Bonus] --+Saving Throw is|[$Save] }}
1620733409

Edited 1620933023
David M.
Pro
API Scripter
Craven, thanks for starting this thread - it's a great idea! As more stuff is added and if you're willing, it would probably be helpful if there was a simple index in the first post with links to the macro post (possibly grouped if you wanted to make the effort). You can get the specific post link by clicking "Permalink" under the poster's name for the post in question. We as posters could help Craven out by adding the bullet point line in our posts, which Craven could simply copy and add to the index. After submitting, we could grab our permalink then edit our post and add the line. Here's what we have so far. Utilities Spellbook - link DM Toolkit :  Character/Party Info - link UDL Party Report -  link Party Spawn -  link     (Notes on future proofing) -  link to Spawn script thread Monster Knowledge -  link System-specific 5e Mob Attacks -  link 5e Saving Throws -  link 5e Skill Checks -  link 5e Turn Undead -  link 5e Thunderwave -  link 5e Conjure Animals -  link 5e Bag Of Tricks Magic Item  -  link 5e Vampiric Touch Spell  -  link 5e Display Passive Perception for All Tokens on Page   -  link Tricks/tips/algorithms Displaying multiple rollable table image results on a single line -  link Sort Die Rolls -  link
1620733631

Edited 1620733774
David M.
Pro
API Scripter
Displaying multiple rollable table image results on a single line - Alien TTRPG Example This example appends URLs to a string variable in a loop and displays the results to a single output line (have to prepend alignment and img size tags, then build URL strings, then append closing tag). Here's what I came up with for the Alien TTRPG. You roll a number of base dice, and a number of "stress" dice. Both count 6's as a success, while the stress dice can also add a failure for each roll of 1. Add successes & failures to determine overall result of the check.  Here's a couple of example checks, using rollable table graphics for the cool Alien dice and string building variables to put the dice on a single line. Here's the Scriptcard macro. I left several comments in the code to help decipher the syntax. !scriptcard {{ --#title|AlienTTRPG Rolls --#leftsub|Num Dice ?{Num Dice?|1} --#rightsub|Num Stress Dice ?{Num Stress Dice?|0} --:Initialize Roll Vars| --=NumDice|?{Num Dice?} --=NumStressDice|?{Num Stress Dice?} --=NumSuccess|0 --=NumFail|0 --:String Building Vars| Will store table graphics. Pre-pend opening format tag --&DieOutput|+[r] --&StressOutput|+[r] --:Base Dice Block| --+[#990000]BASE ROLLS[/#]| --=DieCount|0 --:BaseDiceLoop| --=DieCount|[$DieCount] + 1 -->RollBase| --?[$DieCount] -lt [$NumDice]|BaseDiceLoop --:Output Main Dice| but first append closing format tag --&DieOutput|+[/r] --+|[&DieOutput] --:Stress Dice Block| --+[#990000]STRESS ROLLS[/#]| --?[$NumStressDice] -eq 0|>NA --?[$NumStressDice] -eq 0|EvaluationBlock --=DieCount|0 --:StressLoop| -->RollStress| --=DieCount|[$DieCount] + 1 --?[$DieCount] -lt [$NumStressDice]|StressLoop --:Output Stress Dice| but first append closing format tag --&StressOutput|+[/r] --+|[&StressOutput] --:EvaluationBlock| --+[#990000]EVALUATION[/#]| --:Output Success and Failure counts| --+|[r][b]Successes=[$NumSuccess][/b][/r] --+|[r][b]Failures=[$NumFail][/b][/r] --:Compare rolls| --=Diff|[$NumSuccess] - [$NumFail] --+|[r][b]Difference[$Diff][/b][/r] --+[#990000]RESULT[/#]| --:Output Overall Success or Failure| --?[$Diff] -gt 0|OverallSuccess --?[$Diff] -le 0|OverallFailure --X| End macro --:FUNCTIONS| --:NA| --+|[b][r]N/A[/r][/b] --<| --:RollBase| --=ThisRoll|[T#AlienD6] --?[$ThisRoll.tableEntryValue] -eq 6|>AddSuccess --&DieOutput|+[img width=32][$ThisRoll.tableEntryImgURL][/img] --<| --:RollStress| --=ThisRoll|[T#AlienStressD6] --?[$ThisRoll.tableEntryValue] -eq 6|>AddSuccess --?[$ThisRoll.tableEntryValue] -eq 1|>AddFail --&StressOutput|+[img width=32][$ThisRoll.tableEntryImgURL][/img] --<| --:AddSuccess| --=NumSuccess|[$NumSuccess] + 1 --<| --:AddFail| --=NumFail|[$NumFail] + 1 --<| --:OverallSuccess| --+[c][#009900]~~~SUCCESS~~~[/#][/c]| --X| --<| --:OverallFailure| --+[c][#ff0000]~~~FAILURE~~~[/#][/c]| --X| }} Index Entry Displaying multiple rollable table image results on a single line - link
1620733948

Edited 1652889725
David M.
Pro
API Scripter
Bubble Sort Algorithm  The following takes a collection of die rolls and sorts them for display purposes. Currently hardcoded to 4 rolls, but could be generalized by adding loops, etc. !scriptcards {{ --=NumDice|4 --=Roll1|1d6 --=Roll2|1d6 --=Roll3|1d6 --=Roll4|1d6 --+Unsorted Rolls| --+Rolls|[$Roll1] [$Roll2] [$Roll3] [$Roll4] --:PERFORM A BUBBLE SORT| --=i|0 --=max_i|[$NumDice]-1 --:OuterLoop| --=i|[$i]+1 --=j|[$i] --:InnerLoop| --=j|[$j]+1 --?[$Roll[$i.Raw]] -gt [$Roll[$j.Raw]] |>BubbleUp;[$i.Raw];[$j.Raw] --?[$j.Raw] -lt [$NumDice.Raw]|InnerLoop --?[$i.Raw] -lt [$max_i.Raw]|OuterLoop --+Rolls sorted ascending| --+Rolls|[$Roll1] [$Roll2] [$Roll3] [$Roll4] --X| --:FUNCTIONS| --:BubbleUp| accepts i, j as parameters. Swaps Roll[i] & Roll[j] --=Temp|[$Roll[%2%]] --=Roll[%2%]|[$Roll[%1%]] --=Roll[%1%]|[$Temp] --<| }} Observation : the HiLow formatting is lost if a particular roll changes position. If you sort rolls, it might be best to remove HiLow formatting in your scriptcard to avoid potential confusion Index Entry Sort Die Rolls - link
1620734276

Edited 1623602302
David M.
Pro
API Scripter
5e Turn Undead API script dependencies: Scriptcards, Token-mod (with  Players can use --ids set to true!),  Radar  (just for show, doesn't really do anything mechanics-wise), and  SelectManager . Sharing a scriptcard below for 5e Turn Undead, using Kurt's Fireball card as a starting point. What it does: Finds all tokens on objects and gmlayer (for invisible undead) Filters for npc_type to affect only those with "undead" keywords Makes saves for affected tokens within range (note: Euclidean distance used - so Pythagorean theorem) and displays in chat with color-coded text for pass/fail Checks the cleric level (note: assumes single class!) to determine if failure will turn or destroy based on CR of the undead [Read this - Important!] Assigns a token condition marker on failure: "dead" marker for destroyed undead, and a custom "fear" marker to indicate turned. These will need to be changed based on the markers you have available (look for the conditional call to the AddConditionMarker procedure found within the FailedSave procedure) Creates a 30ft animated wavefront representing the burst of divine energy, using the Radar script (via SelectManager). Silent option to prevent radar chat results, and pingLife|0 to not produce visible "pings". This is optional and requires the Radar script and SelectManager to be installed. Example gif with a 5th level cleric (destroys CR 1/2 or lower) surrounded by skeletons (CR 1/4), Specters (CR 1), and an Ogre Zombie (CR 2).    Here's the code: (EDIT- updated to take the greater of the attributes "wisdom_save_bonus" and "npc_wis_save_base". If the latter is blank we do some substitution to ensure the former is used). Updates in bold. EDIT 2 - Here is a link to a one-off of this scriptcard that adds "Destroy" or "Turn" next to the creature save in the chat output. !script {{ --#title|@{selected|character_name} Turns Undead! --#leftsub|Save DC @{selected|spell_save_dc} --:(0) CREATE AN ANIMATED WAVEFRONT WITH RADAR SCRIPT| uses SelectManager to retain selected token --@forselected|radar_range|30ft _pinglife|0 _wavedelay|20 _wavespacing|10 _silent|true --:(1) DETERMINE CR OF UNDEAD THAT CAN BE DESTROYED| --=charLevel|@{selected|level} --?[$charLevel] -lt 5|>SetCRdestroy;0 --?[$charLevel] -ge 5 -and [$charLevel] -lt 8|>SetCRdestroy;0.5 --?[$charLevel] -ge 8 -and [$charLevel] -lt 11|>SetCRdestroy;1 --?[$charLevel] -ge 11 -and [$charLevel] -lt 14|>SetCRdestroy;2 --?[$charLevel] -ge 14 -and [$charLevel] -lt 17|>SetCRdestroy;3 --?[$charLevel] -ge 17|>SetCRdestroy;4 --:(2) GET ALL TOKENS INTO THE "allTokens" ARRAY| will have blank 1st element to be removed later --~|array;pagetokens;allTokens;@{selected|token_id} --:(3) CREATE THE "inRange" ARRAY TO HOLD TOKENS IN RANGE| --~|array;define;inRange; --:(4) PREP ARRAY FOR LOOP| if no array elements then end macro --~tokenid|array;getfirst;allTokens --?[&tokenid] -eq ArrayError|endOutput --:(5) FIND ALL TOKENS IN RANGE| --:RangeLoop| --:TOKEN MUST BE ON OBJECTS OR GMLAYER AND TYPE MUST INCLUDE UNDEAD| --?[*[&tokenid]:t-layer] -ne objects -and [*[&tokenid]:t-layer] -ne gmlayer|NextToken --?"[*[&tokenid]:npc_type]" -ninc "undead"|NextToken --:CHECK DISTANCE IN UNITS. 30ft is 6UNITS| --~dist|euclideandistance;@{selected|token_id};[&tokenid] --?[$dist] -gt 6|NextToken --:ADD TO THE "inRange" ARRAY| --~|array;add;inRange;[&tokenid] --:NextToken| --~tokenid|array;getnext;allTokens --?[&tokenid] -ne ArrayError|RangeLoop --:(6) REMOVE DUMMY FIRST ITEM IN inRange ARRAY| --~|array;removeat;inRange;0 --:(7) ROLL SAVES FOR EACH TOKEN IN RANGE| if fail, set a token condition marker to denote turned --~tokenid|array;getfirst;inRange --?[&tokenid] -eq ArrayError|End --:SaveLoop| -->GetSaveBonus|[&tokenid];wisdom;wis --=SaveRoll|1d20 + [$saveBonus] [BONUS] --?[$SaveRoll.Total] -ge @{selected|spell_save_dc}|>MadeSave|>FailedSave --~tokenid|array;getnext;inRange --?[&tokenid] -ne ArrayError|SaveLoop --:End| --X| --:PROCEDURES| --:SetCRdestroy| accepts CR as parameter --=CRdestroy|[%1%] --<| --:GetSaveBonus| accepts tokenid, full attribute name, short attribute name as parameters --:TAKE THE GREATER OF "attribute_save_bonus" OR "npc_attr_save"| --=bonus1|[*[%1%]:[%2%]_save_bonus] --&bonus2|[*[%1%]:npc_[%3%]_save_base] --:SOMETIMES "npc_attr_save_base" IS BLANK, SO SET TO -99. OTHERWISE USE ATTR VALUE| --?X[&bonus2] -eq "X"|>Set_npc_attr_save_bonus;-99|>Set_npc_attr_save_bonus;[&bonus2] --:FINALLY SET THE SAVE BONUS| --?[$bonus2] -gt [$bonus1]|>SetSaveBonus;[$bonus2]|>SetSaveBonus;[$bonus1] --<| --:Set_npc_attr_save_bonus| blank value is set to -99, otherwise use value stored in attribute --=bonus2|[%1%] --<| --:SetSaveBonus| --=saveBonus|[%1%] --<| --:MadeSave| --+[*[&tokenid]:character_name]:|[#009900][b]Made Save[/b][/#] [$SaveRoll] --<| --:FailedSave| add either a dead or fear condition marker to the token, depending on CR --+[*[&tokenid]:character_name]:|[#990000][b]Failed Save[/b][/#] [$SaveRoll] --=CR|[*[&tokenid]:npc_challenge] --?[$CR] -le [$CRdestroy]|>AddConditionMarker;[&tokenid];dead|>AddConditionMarker;[&tokenid];Fear::1510130 --<| --:AddConditionMarker| accepts tokenID and condition marker as parameter --@token-mod|_ignore-selected _ids [%1%] _set statusmarkers|[%2%] --<| }} Index Entry 5e Turn Undead - link
1620736845

Edited 1624646728
Yep, this is Thunderwave based on Kurt's Burning Hands script.  !script {{ --/|Burning Hands script. Can be changed to other 15' cone-based spells by updating these parameters. --/|larger cones can be defined by updating the array definitions for the diretions to include additional offsets. --/|cube shaped spells could be acocmodated in a similar way. --&spellName|Thunderwave --/|Note: because the spell will be cast at a min level of 1, we use 2 here to get the total dice (2+1=3) --&spellL0DamageDice|1 --/|Prompt for the spell level. Update this to account for the minimum level of the spell --=SpellLevel|?{Spell Slot Level?|1|2|3|4|5|6|7|8|9} --&spellDamageDieType|8 --&damageType|thunder --&saveType|constitution --/|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} -->GetAndCheckSlotInformation| -->DeductSpellSlot| --/|Get all of the tokens on the page so we can cache their positions --~|array;pagetokens;alltokens;@{selected|token_id} --#leftsub|Save DC @{selected|spell_save_dc} --#rightsub|Slot Level: [$SpellLevel] --#title|[&spellName] --/|Calculate damage based on spell slot. --=DamageDice|[$SpellLevel.Total] + [&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; -->createTokenLookup| --/|Prompt for a direction for hte cast, and define arrays that indicate the relative spaces that will be hit. --&direction|?{Direction|⬆ (UP),U|↗ (UP-RIGHT),UR|➡ (RIGHT),R|↘ (DOWN-RIGHT),DR|⬇ (DOWN),D|↙ (DOWN-LEFT),DL|⬅ (LEFT),L|&#x2196 (UP-LEFT);,UL|} --~|array;define;U;0,-1;0,-2;0,-3;-1,-1;-1,-2;-1,-3;1,-1;1,-2;1,-3 --~|array;define;D;0,1;0,2;0,3;-1,1;-1,2;-1,3;1,1;1,2;1,3 --~|array;define;R;1,0;2,0;3,0;1,-1;2,-1;3,-1;1,1;2,1;3,1 --~|array;define;L;-1,0;-2,0-;-3,0;-1,-1;-2,-1;-3,-1;-1,1;-2,1;-3,1 --~|array;define;UR;1,-1;1,-2;1,-3;2,-1;2,-2;2,-3;3,-1;3,-2;3,-3 --~|array;define;DR;1,1;1,2;1,3;2,1;2,2;2,3;3,1;3,2;3,3 --~|array;define;UL;-1,-1;-1,-2;-1,-3;-2,-1;-2,-2;-2,-3;-3,-1;-3,-2;-3,-3 --~|array;define;DL;-1,1;-1,2;-1,3;-2,1;-2,2;-2,3;-3,1;-3,2;-3,3 --/|Call the "checkForTokenHits" subroutine. The passed parameter will be the per-space VFX. Leave blank for none. -->checkForTokenHits|burst-smoke --/|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];3;-[$Damage.Total]|>ApplyDamageAlterbars;[&tokenid];3;-[$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 affected 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|parameter is vfx descriptor --=baseX|[*S:t-left] - 1 \ 70 --=baseY|[*S:t-top] - 1 \ 70 --~offset|array;getfirst;?{Direction} --:checkTokenLoop| --?"[&offset]" -eq "ArrayError"|endCheckForTokenHits --~split|string;split;,;[&offset] --=thisX|[$baseX] + [&split1] --=thisY|[$baseY] + [&split2] --/|IF we passed a visual effect specifier in %1%, create a point VFX in the square --?"X[%1%]X" -ne "XX" |[ --=VX|[$thisX] * 70 + 35 --=VY|[$thisY] * 70 + 35 --vpoint|[$VX] [$VY] [%1%] --]| -->checkTokens|[$thisX];[$thisY] --~offset|array;getnext;?{Direction} --^checkTokenLoop| --:endCheckForTokenHits| --<| --/|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| --<| --:GetAndCheckSlotInformation| --=SlotLevel|[$SpellLevel] --=SlotsTotal|[*S:lvl[$SlotLevel]_slots_total] --=SlotsExpended|[*S:lvl[$SlotLevel]_slots_expended] --?[$SlotsExpended.Total] -eq 0|NoSlotsLeft --?[$SlotsExpended.Total] -gt [$SlotsTotal.Total]|NoSlotsLeft --@roll20AM|_audio,play,nomenu|Fire Blast --<| --:DeductSpellSlot| --=SlotsExpended|[$SlotsExpended] -1 --@setattr|_charid [*S:character_id] _lvl[$SlotLevel]_slots_expended|[$SlotsExpended] _silent --=SlotsRemaining|[$SlotsTotal] - 1 --+|[c][b]Level [$SpellLevel.Total] Spell Slots Left: [/b][$SlotsExpended][/c] --<| --X| --:NoSlotsLeft| --+|[b][*S:character_name] has no level [$SlotLevel.Total] spell slots available.[/b] --X|NoSlotsLeftStop }}
1620738742

Edited 1622436181
Snow
Pro
Here is my script for Monster Knowledge. First check is 8 + 1/2 CR of creature, second check is 8 + CR of creature. !scriptcard {{ --#whisper|gm --#title|Knowledge Check --=BaseDC|8 --=CreatureCR|@{target|npc_challenge} --=KnowledgeDC|[$CreatureCR]\2+[$BaseDC] --=KnowledgeDCTwo|[$CreatureCR]+[$BaseDC]\1 --?"@{target|npc_type}" -inc aberration|>Arcana --?"@{target|npc_type}" -inc construct|>Arcana --?"@{target|npc_type}" -inc dragon|>Arcana --?"@{target|npc_type}" -inc elemental|>Arcana --?"@{target|npc_type}" -inc ooze|>Arcana --?"@{target|npc_type}" -inc beast|>Nature --?"@{target|npc_type}" -inc giant|>Nature --?"@{target|npc_type}" -inc monstrosity|>Nature --?"@{target|npc_type}" -inc plant|>Nature --?"@{target|npc_type}" -inc celestial|>Religion --?"@{target|npc_type}" -inc fey|>Religion --?"@{target|npc_type}" -inc fiend|>Religion --?"@{target|npc_type}" -inc undead|>Religion --?"@{target|npc_type}" -inc humanoid|>History --:Arcana| --+Arcana Check:| DC = [$KnowledgeDC] --+Arcana Adv Check:| DC = [$KnowledgeDCTwo] --+Monster Type:| @{target|npc_type} --^Final| --:Nature| --+Nature Check:| DC = [$KnowledgeDC] --+Nature Adv Check:| DC = [$KnowledgeDCTwo] --+Monster Type:| @{target|npc_type} --^Final| --:Religion| --+Religion Check :| DC = [$KnowledgeDC] --+Religion Adv Check:| DC = [$KnowledgeDCTwo] --+Monster Type:| @{target|npc_type} --:History| --+History Check :| DC = [$KnowledgeDC] --+History Adv Check:| DC = [$KnowledgeDCTwo] --+Monster Type:| @{target|npc_type} --:Final| }} A black bear, goblin, and a Ancient Red Dragon
1620743316

Edited 1620743461
David M.
Pro
API Scripter
5e Mob Attacks Queries for number of attackers, att/dam modifiers, Norm/Adv/DisAdv, and target AC. !scriptcard {{ --:USER INPUT| --=NumAttacks|?{Number Attackers?|2} --&RollString|?{Attack Type?|Normal,1d20|Advantage,2d20kh1|Disadvantage,2d20kl1}+?{Attack Modifier?|0} --&DamDice|?{Damage Dice?|1d8} --&DamMod|?{Damage Modifier?|0} --=TargetAC|?{Target AC?|10} --:TITLE CARD DISPLAY| --#whisper|gm --#title|Mob Attack --#leftsub|[&RollString] vs AC [$TargetAC] --#rightsub|Dam:[&DamDice]+[&DamMod] --:LOOP THROUGH ATTACKS --=DisplayCount|1 --=DamageTotal|0 --:AttackLoop| -->MakeAttack| call function --=DisplayCount|[$DisplayCount] + 1 --?[$DisplayCount] -le [$NumAttacks]|AttackLoop --:DISPLAY TOTAL DAMAGE| --+Total|Total damage is [$DamageTotal] --X|Exit macro --:PROCEDURES| --:MakeAttack| --=ThisAttack|[&RollString] --?[$ThisAttack.Base] -eq 20|Crit --?[$ThisAttack] -ge [$TargetAC]|Hit --?[$ThisAttack] -lt [$TargetAC]|Miss --:AttackDone| --<| --:Hit| --=ThisDamage|[&DamDice][BASE]+[&DamMod][MOD] --=DamageTotal|[$DamageTotal] + [$ThisDamage.Total] --+Attack[$DisplayCount.Total]|[$ThisAttack] [b]Hits[/b] for [$ThisDamage] dam --^AttackDone| --<| --:Crit| --=ThisDamage|[&DamDice][BASE]+[&DamMod][MOD] + [&DamDice][CRIT] --=DamageTotal|[$DamageTotal] + [$ThisDamage.Total] --+Attack[$DisplayCount.Total]|[$ThisAttack] [b][#009900]Crits[/#][/b] for [$ThisDamage] dam --^AttackDone| --<| --:Miss| --+Attack[$DisplayCount.Total]|[$ThisAttack] [b][#990000]Misses[/#][/b] --^AttackDone| --<| }} Index Entry 5e Mob Attacks - link
David M. said: 5e Turn Undead Your Turn Undead macro works well, but when I use it, it doesn't add the condition marker. And yes, I did set it up for my own condition marker. I just can't seem to make it work.
1620761443

Edited 1620761549
David M.
Pro
API Scripter
Ah yes, I used a custom condition marker. You would have to change that marker name to one you have available. I will edit my post above to highlight that potential gotcha.
1620822464

Edited 1620822496
David M.
Pro
API Scripter
5e Conjure Animals API scripts required: Scriptcards , SelectManager , SpawnDefaultToken , Table-Export .  This spell is pretty involved from a procedural standpoint. The caster picks a Challenger Rating of creatures to summon (which also determines a scaled qty of creatures), and some number of random creature types of the appropriate CR are summoned within range. To handle all of the randomness and to have the whole spell in one macro, I ended up using a combination of the  Spawn ,  Scriptcards , and  SelectManager  api scripts, along with a rollable table that I populated with the Scriptcards version of the Spawn commands (built in excel and imported with Aaron's  table-export  script). Description below, but fair warning: it's a lot!  Here's what it looks like in action (click to play gif). First, I Spawn a "target" token from a token action ability on the character. This will determine the location where the creatures will spawn. This target token has it's own character sheet and default token (required by Spawn), and I put the scriptcards macro into a token action ability on the target token's sheet. In the example, I selected CR 1/4 creatures. The scriptcards ability rolls on the appropriate rollable table using conditional logic, and you can see 8 CR 1/4 wolves were randomly selected and then spawned at the target location.  Note: the grid placement is not ideal for creatures larger than 1x1 (there will be some overlap), as I haven't handled large tokens with grid placement that in the script yet. But, it's easy enough to move them slightly after spawning for now.   Here's the Spawn ability that generated the target token. Note that my characters have access to the spell via a magic item (that I called "Bag of Nature's Allies"). You could call this "Conjure Animals Target" or whatever you want. Just make it match the name of the target "character" sheet. !Spawn {{ --name| Bag of Nature's Allies --offset| 1,0 }} Here's the scriptcard macro. The Rollable table items contain Spawn syntax using the scriptcards format). Also note that the SelectManager script is required to use the "forselected" property to retain the selected token between the two other scripts (Spawn and Scriptcards). The scriptcard populates a "CR" variable, then performs the equivalent of a "Select...Case" (or Switch) statement to call the "RollTable" procedure with the appropriate parameter (the name of the rollable table to use). Finally, it calls the Spawn script (via SelectManager) with the --@forselected line. See the Scriptcard documentation for more info on all of this. !scriptcards {{ --:SETTINGS| --#hideCard|1 --#title|Nature's Allies --=CR|?{How many creatures?|1x CR 2,2|2x CR 1,1|4x CR 1/2,0.5|8x CR 1/4,0.25} --C[$CR.Total]|2:>RollTable;SpawnBeastsCR2|1:>RollTable;SpawnBeastsCR1|0.5:>RollTable;SpawnBeastsCR0.5|0.25:>RollTable;SpawnBeastsCR0.25 --@forselected|[$SpawnSyntax.tableEntryText] --X| End macro --:PROCEDURES| --:RollTable| --=SpawnSyntax|[T#[%1%]] --<| }} These are the rollable tables I created: Here are the table-export macros I used to generate the rollable tables. Note the "_p's" referring to the player-controlled copies I made. !import-table --SpawnBeastsCR2 --show !import-table-item --SpawnBeastsCR2 --Spawn _name|Saber-Toothed Tiger_p _qty|1 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR2 --Spawn _name|Rhinoceros_p _qty|1 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR2 --Spawn _name|Giant Elk_p _qty|1 _size|3,3 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR2 --Spawn _name|Giant Constrictor Snake_p _qty|1 _size|3,3 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR2 --Spawn _name|Giant Boar_p _qty|1 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR2 --Spawn _name|Cave Bear_p _qty|1 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR2 --Spawn _name|Allosaurus_p _qty|1 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR2 --Spawn _name|Quetzalcoatlus_p _qty|1 _size|3,3 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR2 --Spawn _name|Aurochs_p _qty|1 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table --SpawnBeastsCR1 --show !import-table-item --SpawnBeastsCR1 --Spawn _name|Tiger_p _qty|2 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR1 --Spawn _name|Lion_p _qty|2 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR1 --Spawn _name|Giant Vulture_p _qty|2 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR1 --Spawn _name|Giant Toad_p _qty|2 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR1 --Spawn _name|Giant Spider_p _qty|2 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR1 --Spawn _name|Giant Hyena_p _qty|2 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR1 --Spawn _name|Giant Eagle_p _qty|2 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR1 --Spawn _name|Dire Wolf_p _qty|2 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR1 --Spawn _name|Brown Bear_p _qty|2 _size|2,2 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR1 --Spawn _name|Deinonychus_p _qty|2 _size|1,1 _placement|grid 1 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table --SpawnBeastsCR0.5 --show !import-table-item --SpawnBeastsCR0.5 --Spawn _name|Warhorse_p _qty|4 _size|2,2 _placement|grid 2 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.5 --Spawn _name|Giant Wasp_p _qty|4 _size|1,1 _placement|grid 2 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.5 --Spawn _name|Giant Goat_p _qty|4 _size|2,2 _placement|grid 2 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.5 --Spawn _name|Crocodile_p _qty|4 _size|2,2 _placement|grid 2 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.5 --Spawn _name|Black Bear_p _qty|4 _size|1,1 _placement|grid 2 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.5 --Spawn _name|Ape_p _qty|4 _size|1,1 _placement|grid 2 _offset|0,0 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table --SpawnBeastsCR0.25 --show !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Wolf_p _qty|8 _size|1,1 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Pteranodon_p _qty|8 _size|1,1 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Panther_p _qty|8 _size|1,1 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Giant Wolf Spider_p _qty|8 _size|1,1 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Giant Poisonous Snake_p _qty|8 _size|1,1 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Giant Owl_p _qty|8 _size|2,2 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Giant Lizard_p _qty|8 _size|2,2 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Giant Frog_p _qty|8 _size|1,1 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Giant Centipede_p _qty|8 _size|1,1 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Giant Bat_p _qty|8 _size|2,2 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Giant Badger_p _qty|8 _size|1,1 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Elk_p _qty|8 _size|2,2 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Draft Horse_p _qty|8 _size|2,2 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Constrictor Snake_p _qty|8 _size|2,2 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Boar_p _qty|8 _size|1,1 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Axe Beak_p _qty|8 _size|2,2 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Velociraptor_p _qty|8 _size|1,1 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Ox_p _qty|8 _size|2,2 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Hadrosaurus_p _qty|8 _size|2,2 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Dimetrodon_p _qty|8 _size|1,1 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- !import-table-item --SpawnBeastsCR0.25 --Spawn _name|Cow_p _qty|8 _size|2,2 _placement|grid 3 _offset|-1,-1 _resizeSource|0,0,20,50 _expand|20,50 --1 -- Whew! This is obviously a lot of work for one spell (albeit a complicated spell), but I am pretty happy with the result.  Index Entry 5e Conjure Animals - link
1620907470

Edited 1621878674
David M.
Pro
API Scripter
5e Display Passive Perception for All Tokens on Page Select a token on the page and run the report to display passive perception ("passive_wisdom" attribute) for all tokens on the Objects or GM layer. !script {{ --#title|Global Passive Perception --:(1) GET ALL TOKENS INTO THE "allTokens" ARRAY| will have blank 1st element to be removed later --~|array;pagetokens;allTokens;@{selected|token_id} --:(2) PREP ARRAY FOR LOOP| if no array elements then end macro --~tokenid|array;getfirst;allTokens --?[&tokenid] -eq ArrayError|End --:(3) GRAB PASSIVE PERCEPTION FROM EACH TOKEN| --:PPLoop| --:TOKEN MUST BE ON OBJECTS OR GMLAYER AND HAVE A NON_BLANK PASSIVE_WISDOM| --?[*[&tokenid]:t-layer] -ne objects -and [*[&tokenid]:t-layer] -ne gmlayer|NextToken --?[*[&tokenid]:passive_wisdom] -ne ""|>DisplayPP --:NextToken| --~tokenid|array;getnext;allTokens --?[&tokenid] -ne ArrayError|PPLoop --:End| --X| --:DisplayPP| --=PP|[*[&tokenid]:passive_wisdom] ​--+[*[&tokenid]:character_name]|[$PP] --<| }} EDIT - Option 2: Only report tokens with Passive Perception succeeding against a target DC (also whispered output to GM). Changed lines are bolded. !script {{ --#title|Global Passive Perception --=DC|?{Passive Perception DC?|10} --#leftsub|Target DC[$DC] --#whisper|gm --:(1) GET ALL TOKENS INTO THE "allTokens" ARRAY| will have blank 1st element to be removed later --~|array;pagetokens;allTokens;@{selected|token_id} --:(2) PREP ARRAY FOR LOOP| if no array elements then end macro --~tokenid|array;getfirst;allTokens --?[&tokenid] -eq ArrayError|End --:(3) GRAB PASSIVE PERCEPTION FROM EACH TOKEN| --:PPLoop| --:TOKEN MUST BE ON OBJECTS OR GMLAYER AND HAVE A NON_BLANK PASSIVE_WISDOM| --?[*[&tokenid]:t-layer] -ne objects -and [*[&tokenid]:t-layer] -ne gmlayer|NextToken --?[*[&tokenid]:passive_wisdom] -ne "" -and [*[&tokenid]:passive_wisdom] -ge [$DC]|>DisplayPP --:NextToken| --~tokenid|array;getnext;allTokens --?[&tokenid] -ne ArrayError|PPLoop --:End| --X| --:DisplayPP| --=PP|[*[&tokenid]:passive_wisdom] ​--+[*[&tokenid]:character_name]|[$PP] --<| }} Output on same map as above. The Kobold and Direwolf are below the target DC and are filtered. Index Entry 5e Display Passive Perception for All Tokens on Page   - link
1620918845

Edited 1620919235
Bag Of Tricks This macro is listed (or should I say buried) in the Scriptcards forum, but since this section is indexed, I'd thought I would list the Bag of Tricks macro here. It should be mentioned it also requires the SpawnDefaultToken script . It also uses ChatSetAttr script to deduct the number of animals the bag has left (the attribute _bagoftrick_left will have to be created in the character's attribute section. I set that attribute to 3 for the Bag of Tricks, and once all of the animals have been removed from the bag, it has to be reset to 3.). This macro also uses SelectManager as well.  !scriptcard {{ --#titlecardbackground|#65D52A --#title|From The Bag Of Tricks --#sourceToken|@{selected|token_id} --~Animals|string;split;:;Weasel:Giant Rat:Badger:Boar:Panther:Giant Badger:Dire Wolf:Giant Elk --~Offsets|string;split;:;0,1:0,-1:1,0:1,1:1,-1:2,0:3,-3:4,4 --~Sizes|string;split;:;1,1:1,1:1,1:1,1:1,1:1,1:2,2:3,3 --=AnimalCount|?{How many creatures do you want to pull from the bag?|1|2|3} --=BagSlots|[*S:bagoftrick_left] --?[$BagSlots.Total] -lt [$AnimalCount.Total]|NotEnough --@modbattr|_name @{selected|character_name} _bagoftrick_left|-[$AnimalCount.Total] _silent --#emotetext|@{selected|character_name} pulls [$AnimalCount.Total] things out of a bag of tricks! --=Counter|0 --:AddAnAnimal| --=RollAnimal|1d8 --=Counter|[$Counter] + 1 -->Summon|[$RollAnimal.Total];[$Counter.Total] --?[$Counter.Total] -lt [$AnimalCount.Total]|AddAnAnimal --X| --:Summon|Animal number to summon;Counter into Offsets --@forselected+|Spawn _name|[&Animals[%1%]] _offset|[&Offsets[%2%]] _size|[&Sizes[%1%]] _order|toFront _fx|nova-magic _expand|15,30 --@roll20AM| _audio,play,nomenu|Teleport Spell --+|@{selected|token_name} pulls out a [&Animals[%1%]]! --<| --:NotEnough| --#titlecardbackground|#F71805 --#emotetext|Bag Of Tricks Doesn't Have Enough Animals! --+|[$BagSlots.Total] Animals Left --X| }} 5e Bag Of Tricks Magic Item - link
1620919706

Edited 1620919763
Vampiric Touch (5e) API Scripts Required: Scriptcards, Alterbars, ChatSetAttr, Roll20 Audio Master As the name suggests, this is the Vampiric Touch Spell for D&D 5e. This script will deduct a spell slot, it will calculate if it hits and if it does, it will then deduct the damage from the target. The character who used the spell will then be healed for half the damage they inflicted.  !scriptcard {{ --#title|Vampiric Touch --#sourceToken|@{selected|token_id} --#targetToken|@{target|token_id} --=TargetAC|@{target|npc_ac} --?[$TargetAC.Total] -gt 0|DoneWithAC --=TargetAC|@{target|ac} --:DoneWithAC| -->GetAndCheckSlotInformation| -->DeductSpellSlot| --#leftsub|Slot level [$SlotLevel] --#rightsub|Level [$SlotLevel] Slots Remain: [$SlotsExpended] --#emoteText|@{selected|token_name} Uses Vampiric Touch On @{target|token_name} --=AttackRoll|1d20 + @{selected|charisma_mod} [Char] + @{selected|pb} [PROF] --+Attack|@{selected|token_name} rolls [$AttackRoll] vs AC [$TargetAC] --?[$AttackRoll.Total] -ge [$TargetAC.Total]|Hit --+Miss|The attack missed. --^Final| --:DeductSpellSlot| --=SlotsExpended|[$SlotsExpended] - 1 --@setattr|_charid [*S:character_id] _lvl[$SlotLevel]_slots_expended|[$SlotsExpended] _silent --=SlotsRemaining|[$SlotsTotal] - [$SlotsExpended] --<| --:Hit| --=Damage|1d6 * [$SlotLevel.Total] --+Hit!|@{selected|token_name} Deals [$Damage] Points Of Necrotic Damage to @{target|token_name}! --@alter|_target|@{target|token_id} _bar|3 _amount|-[$Damage] --@roll20AM| _audio,play,nomenu|sonic ----vtoken|@{target|token_id} burst-death -->VampireHeal| --<| --^Final| --:GetAndCheckSlotInformation| --=SlotLevel|?{Spell Slot Level?|3|4|5|6|7|8|9} --=SlotsTotal|[*S:lvl[$SlotLevel]_slots_total] --=SlotsExpended|[*S:lvl[$SlotLevel]_slots_expended] --?[$SlotsExpended.Total] -eq 0|NoSlotsLeft --<| --:NoSlotsLeft| --+|[*S:character_name] has no level [$SlotLevel.Total] spell slots available. --X| --:VampireHeal| --=TotalHeal|[$Damage]\2 --@alter|_target|@{selected|token_id} _bar|3 _amount|+[$TotalHeal] --vfx_opt|@{selected|token_id} holy-nova --+Life Absorption!|@{selected|token_name} Regains [$TotalHeal] Hit Points --@roll20AM| _audio,play,nomenu|Regenerate --vtoken|@{selected|token_id} glow-magic --<| --:Final| }} Vampiric Touch D&D 5e Spell - link
1621118953

Edited 1621402137
Update 5/17: I've completed the code, I just need to package it and include documentation and a list of API Script requirements.  When I do post it, it will be in 3 posts.  DM-Tools, NPC-Tools, and my Utility Macros.  Update 5/19: There is so much here, I had to get my own GITHUB account. I've used the tool to pull code, but have never setup one for myself, so working through what I hope is a small learning curve. I'm nearing completion of my suite of DM and NPC Tools version 2.  I hope to post the code and associated API scripts here soon.  Here's a bit of a tease showing the various dialogs and reports. The first set (Blue) are designed to be player character centric and make it easier to manage Player Characters (from a DM/GM point of view).  In the center of this image is the top level form called "DM Tools", and from it, you navigate to all the other DM Tools.   The second set (Green) are designed to manage your monsters, NPCs and encounters. In the center of this image is the top level form called "NPC Tools", and from it, you navigate to all the other NPC Tools.   The third set is a menu system with for all my utility macros. My favorite features: Clicking on a character or NPC, will move the map and ping the character, there are quick options to move tokens between the GM and Objects layers, and finally, the ability to quickly review and set UDL settings for the page and player characters.  
1621121764
David M.
Pro
API Scripter
Looks beautiful, Will!
HI all. Rosco here.  I’ve an idea that may be useful. All the wonderful scripts being proffered attend to game time. What about development and maintenance? My biggest fear is lack of backup support. Let me explain. I use character sheet Abilites for a lot of things other than PC/NPC sheets. The initial reason being, unlike other directories, the Journal for instance, the Collection does not provide subdirectories nor alphabetizing.  What a mess to sort through, never mind maintain.  See code below as an example code that leads to code that leads to code. This approach is supported by the conditionals found in ScriptCards (my favorite). Cutting to the chase: I would like to see a script that would collect the information from all of a sheet’s Abilities at the same time and, say, stuff them into a handout – though I would accept it within the chat. Then I could copy and paste the data to a text file on my hard drive for safe keeping. Since y’all are coders, I know you understand that before you start making changes to code, you must have/create backups. Please forgive me if this is taking up a lot of  space in this forum. I know nowhere else more suitable. Let me show this example of sheet approach only to inspire a need for a tool for this kind of time consuming backup. "Don't worry, Little Brother. There are more." - Class, Race, Weapons, and more comming.  ---------- 1: PC Onad The Great: character sheet Ability title: Club    %{Attack|Club} 2: Attack: work sheet Ability title: Club     ! Having this macro allows the flexability to skip it when a special need arrises elsewhere.     !scriptcard  {{      --#whisper|gm,self      --=WeaponAttacks|1       %{Weapon|Club}    }} 3: Weapon:  work  sheet Ability title: Club --&AbilityCategory|Str --&WeaponName|Club --&WeaponDmgType|Bludgeon --&WeaponHanded|1 --&WeaponDmgLabel|1d4 --=WeaponDmg|1d4 --=WeaponDmgCrit|1d4 --&WeaponType|Melee --&WeaponCat|Simple --&WeaponReach|5' --&WeaponWeight|2 lbs --&WeaponCost|1sp --&WeaponInfo|None --:Set up standard defaults| %{Weapon|Attack_Initialize}  %{Weapon|Attack} 4: Weapon:  work  sheet Ability title: Attack --:|Configure/gather need information| %{Weapon|Attack_Attributes} %{weapon|Attack_Target} %{Weapon|Attack_Attacker} %{Weapon|Attack_Pre_Roll_Adjustments} %{Weapon|Attack_Roll} %{Weapon|Attack_Damage} %{Weapon|Attack_Header} --:Make next step decisions| --+|[#ff0000][b]Attack[/b][/#] roll is [$Atk] which means --?[$Atk.Base] -eq 20|Crit --?[$Atk.Base] -eq 1|CheckSkipFumble --?[$Atk.Total] -ge [$TargetAC.Total]|Hit %{Weapon|Message_Missed} --^EndAttack|   --:Hit| --+|[#ff0000][b]Opponent[/b][/#] takes [$Dmg] points damage. --@alter| _target|@{target|token_id} _bar|1 _amount|-[$Dmg] _show|none --^WeaponInformation| %{Weapon|Attack_FX} --:Crit| --[b]Critical[/b] --+|[#ff0000][b]Opponent[/b][/#] is [b]criticaled[/b] for [$CritDmg] points! --@alter|_target|@{target|token_id} _bar|1 _amount|-[$CritDmg] _show|none --^WeaponInformation|   %{Weapon|Attack_FX} --:CheckSkipFumble| Usually because attacker is a Halfling --?[$SkipFumble] -eq 0|Fumble %{Weapon|Message_Fumble_Immunity} --^gotoFooter| --:Fumble| %{Weapon|Message_Attack_Fumble} --^gotoFooter| --:WeaponInformation| Used for special weapons or attacks %{Weapon|Attack_Information} --^gotoFooter| --:gotoFooter| %{Weapon|Message_Footer}  --^EndAttack| --:EndAttack| ---------- This may seem tidious, but ScriptCards makes this approach worth it (I'm into components) and the results are amazingly fast. Thanks for the listen.
1621179040

Edited 1621185547
I think I understand what you are asking for, an offline repository of your macros for all your character sheets.  For both backup and management purposes.  I kind of achieve this with the following: 1. I create a backup of my primary campaigns every couple weeks. 2. I store all my Macros into their own character sheet I call Mule (Macro-Mule).  I only use the Macro pane for initial development and alpha testing.   3. Since all my macros are stored in a single character sheet (Mule) I can then export the charactersheet as JSon, or to the repository.  I can easily move all my macros between campaigns with Transmogrifier in one action.  4. I develop all my code offline in a programmer's text editor (Sublime) and have developed a file and directory structure that allows for easy cataloging and backup. 5. For many of the more simplistic "Attack/Ability/Feat type macros, I use TokenActions (!ta) script which creates token actions and macros for all my Player's and NPC character sheets.  It automates the creation of dozens and dozens of everyday macros, so I don't spend anytime coding and managing those.   I do wish Roll20 had a better Campaign Management System tracking and logging and note taking system.  Once I finish up with my DM/NPC Suite of tools (see above), I think I might take a stab at building a consolidated campaign management toolset.   Update:  The more I think about implementing an improved Campaign Management System, the more I realize I'd be bumping up against some technical issues and would need improved tools for reading/writing handouts.  I'm still learning JavaScript, so that may be a fun project to tackle and learn from.  I'm hoping that ScriptCards continues to expand and allows for exploration of all Roll20 Objects.
@Will M. Right you are. I use the text editor in Rapid PHP when I need more than Notepad. I'm not familiar with TokenAction. Where it becomes clumsy  is when I need to make a bunch of minor, one line additions or changes to a bunch of similar macros. Whether I move the changes from my hard drive to Roll20 or move them from Roll20 to the hard drive, it is a tedious, time consuming issue. A click to a script would mean a lot. And, now that you mention it, what about a click that allows me to upload the text file from my hard drive. Too much to soon? In any case, I don't know where y'all find the time to do what you're doing now. Hats off.
Say, how to you export to json?
1621187766

Edited 1621188428
It's a capability that VTT Enhancement Suite provides ( VTT Enhancement Suite (justas-d.github.io) ).  It adds a tab to the Character Sheet called Export & Overwrite.  It also has introduces a Macro Generator tab that I believe has similar functionality to TokenActions.  
Will M. said: SpellBook version 0.31 Updated: bug identified (gosub -->DisplayLoop|,  should have been a goto --^DisplayLoop|)  as a result of upgrading to version 1.21 of scriptcards.  Fixed in this version. This is still a work in progress, but I'll update this post as it matures.  Basic functionality I'm going for: Lists all spells for a selected character, indicating which ones are prepared, require concentration and can be cast as ritual Provides buttons to 1) see details, 2) prepare/toggle 3) cast Next Steps Add Slots remaining/max to level header Add "At higher levels" to spell description details Add ability to cast both attack and non-attack spells and auto-deduct from spell counts Add ability to toggle prepare flag (and limit prepared spells to max available) Better support sorcerers (Sorcery Points) Continue to clean up the look of the cards (font and color suggestions welcome) Add SoundFX options Add options to whisper spell description to GM or other players Uh, Will, this is next-level amazing!! I can't wait to see how this develops (the prepare flag and soundFX options, especially). For myself, I'm going to have the scriptcard pull its font and color from a character-specific stored setting.
1621192364

Edited 1621192793
David M I have tried changing the attribute to make it work, but I still get NO attribute set. For simplicity in testing I just set both to dead (below).  Is there a way to return to the chat what SHOULD happen as well as set the condition?  --:FailedSave| add either a dead or fear condition marker to the token, depending on CR        --+[*[&tokenid]:character_name]:|[#990000][b]Failed Save[/b][/#] [$SaveRoll]       --=CR|[*[&tokenid]:npc_challenge]       --?[$CR] -le [$CRdestroy]|>AddConditionMarker;[&tokenid];dead|>AddConditionMarker;[&tokenid];dead   --<|
Random Lingering Injuries Script Dependencies : CombatMaster, SelectManager, and a modded GMNote (not my mod; script appears below). This 5e scriptcard (OGl sheet) checks a table called Lingering-Injuries for one random injury and assigns it to the selected token. It also assigns a Combat Master condition of the same name as the injury to the affected token and adds a note to the character's bio field. With tweaking, you could use this type of scriptcard to assign any random effect to a token. Scriptcard : !scriptcard {{   --#title|Lingering Injury   --#sourceToken|@{selected|token_id}   --#emoteText|*@{selected|token_name} suffers an injury that will not go away!*   --=Event|[T#Lingering-Injuries]   --&InjuryName|[$Event.tableEntryText]        --C[&InjuryName]|Minor Scar:>MinorScar|Limp:>Limp|Broken Ribs:>BrokenRibs|Festering Wound:>FesteringWound|Broken Arm:>BrokenArm|Broken Foot:>BrokenFoot|Concussion:>Concussion|Horrible Scar:>HorribleScar]     --X|   --:MinorScar|   --@forselected+|add-bio [$Event.tableEntryText]   --@forselected+|cmaster _add,condition=minor scar   --<|   --:Limp|   --@forselected+|add-bio [$Event.tableEntryText]   --@forselected+|cmaster _add,condition=limp   --<|   --:BrokenRibs|   --@forselected+|add-bio [$Event.tableEntryText]   --@forselected+|cmaster _add,condition=broken ribs   --<|   --:FesteringWound|   --@forselected+|add-bio [$Event.tableEntryText]   --@forselected+|cmaster _add,condition=festering wound   --<|   --:BrokenArm|   --@forselected+|add-bio [$Event.tableEntryText]   --@forselected+|cmaster _add,condition=broken arm   --<|   --:BrokenFoot|   --@forselected+|add-bio [$Event.tableEntryText]   --@forselected+|cmaster _add,condition=broken foot   --<|   --:Concussion|   --@forselected+|add-bio [$Event.tableEntryText]   --@forselected+|cmaster _add,condition=concussion   --<|   --:HorribleScar|   --@forselected+|add-bio [$Event.tableEntryText]   --@forselected+|cmaster _add,condition=horrible scar   --<|   --<| }} Screenshot : GMNote Script : on('ready',function(){ 'use strict'; const cmdregex=/^(!(?:set|add)-(?:c?gmnote|bio))\s*/, formatMsg = (c)=>c.replace(cmdregex,'').replace(/(^{{\s*|\s*}}$)/gm,''); on('chat:message',function(msg){ if('api' === msg.type) { let match=msg.content.match(cmdregex); // if(match && playerIsGM(msg.playerid) ){ if(match){ let content = formatMsg(msg.content), who=(getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname'); if(_.has(msg,'inlinerolls')){ content = _.chain(msg.inlinerolls) .reduce(function(m,v,k){ var ti=_.reduce(v.results.rolls,function(m2,v2){ if(_.has(v2,'table')){ m2.push(_.reduce(v2.results,function(m3,v3){ m3.push(v3.tableItem.name); return m3; },[]).join(', ')); } return m2; },[]).join(', '); m['$[['+k+']]']= (ti.length && ti) || v.results.total || 0; return m; },{}) .reduce(function(m,v,k){ return m.replace(k,v); },content) .value(); } if(content.length){ let tokens = _.chain(msg.selected) .map( s => getObj('graphic',s._id)) .reject(_.isUndefined) ; var currentdate = new Date(); var datetime = "Note Added: " + (currentdate.getMonth()+1) + "/" + (currentdate.getDate()) + "/" + currentdate.getFullYear() + " @ " + (currentdate.getHours()-5) + ":" + currentdate.getMinutes() + ":" + currentdate.getSeconds(); switch(match[1]){ case '!set-gmnote': tokens.each( o => { o.set({ gmnotes: content }); }); break; case '!set-cgmnote': tokens.map( o => getObj('character',o.get('represents'))) .reject(_.isUndefined) .each( o => { o.set({ gmnotes: content }); }); break; case '!set-bio': tokens.map( o => getObj('character',o.get('represents'))) .reject(_.isUndefined) .each( o => { o.set({ bio: content }); }); break; case '!add-gmnote': tokens.each( o =>{ o.set({ gmnotes: `${o.get('gmnotes')}<br>\n${content}` }); }); break; case '!add-cgmnote': tokens.map( o => getObj('character',o.get('represents'))) .reject(_.isUndefined) .each( o => { o.get('gmnotes',(notes)=>{ _.defer(()=>o.set({ gmnotes: `${notes}<br>\n<hr>${datetime}<br>${content}` })); }); }); break; case '!add-bio': tokens.map( o => getObj('character',o.get('represents'))) .reject(_.isUndefined) .each( o => { o.get('bio',(notes)=>{ _.defer(()=>o.set({ bio: `${notes}<br>\n${content}` })); }); }); break; } } else { sendChat('',`/w "${who}" <div>`+ `<div>Use <code>COMMNAD Some Text</code> or <code>COMMAND {{ some multi-line text}}</code>.</div>`+ `<div><b>Commands:</b></div>`+ `<div><ul>`+ `<li><code>!set-gmnote</code> -- Replaces contents of token gmnotes.</li>`+ `<li><code>!set-cgmnote</code> -- Replaces contents of character gmnotes.</li>`+ `<li><code>!set-bio</code> -- Replaces contents of character bio.</li>`+ `<li><code>!add-gmnote</code> -- Appends to contents of token gmnotes.</li>`+ `<li><code>!add-cgmnote</code> -- Appends to contents of character gmnotes.</li>`+ `<li><code>!add-bio</code> -- Appends to contents of character bio.</li>`+ `</ul></div>` ); } } } }); });
What game (character sheet) is Lingering Injury for?
Donald K. said: What game (character sheet) is Lingering Injury for? Standard D&D 5e sheet. I've updated my post to include that info.
1621201267
David M.
Pro
API Scripter
Donald K. said: David M I have tried changing the attribute to make it work, but I still get NO attribute set. For simplicity in testing I just set both to dead (below).  Is there a way to return to the chat what SHOULD happen as well as set the condition? Do you have the token-mod api script installed? Also, it looks like you need the  Players can use --ids option set to true (can be set from the api console, then restart your sandbox). I just toggled mine off and no condition markers were set. Sorry I failed to denote any of that that as a dependency in my original post, but I'll edit it to include that note. @DM Goss, that may have been your problem, as well?
Thank you for the response. I did not initially understand (read past the dependencies) on CombatMaster, SelectManager, and a modded GMNote. I have added CM and SM, but how does the GMNote function? 
David M. That did it! I did have it installed, but needed to toggle the setting. Thank you!
Donald K. said: Thank you for the response. I did not initially understand (read past the dependencies) on CombatMaster, SelectManager, and a modded GMNote. I have added CM and SM, but how does the GMNote function?  On the API page, click New Script, name it GMNote, and paste the GMNOte code into the field provided. Save the script and you're good. The reason I list each of these scripts as a dependency is because the scriptcard uses each of them. SelectManager allows any token to be selected without weird behavior (CombatMaster doesn't accept the usual @selected_token_id syntax). CombatMaster assigns a condition to the token (complete with status marker; you have to create a Combat Master condition for each lingering injury). GMNote writes the name of the injury to the bio field of the token's character. If you don't care about having the injury in the bio field, you can skip installing it and delete all the add-bio lines in my scriptcard. If you've never used CombatMaster before, you may want to play around with it first before tying it to scriptcards. CM is a super-useful but also complex script. Good luck!
Jay R. I appreciate the explanation, and the work contributed. Thank you!  
1621202651
David M.
Pro
API Scripter
Donald K. said: David M I have tried changing the attribute to make it work, but I still get NO attribute set. For simplicity in testing I just set both to dead (below).  Is there a way to return to the chat what SHOULD happen as well as set the condition ? Yes, I think the following does what you are asking. I added a FailureText string variable and set it when we set the condition marker. Also, I made sure to reset the variable to an empty string at the start of SaveLoop to be ready for the next token. !script {{ --#title|@{selected|character_name} Turns Undead! --#leftsub|Save DC @{selected|spell_save_dc} --:(0) CREATE AN ANIMATED WAVEFRONT WITH RADAR SCRIPT| uses SelectManager to retain selected token --@forselected|radar_range|30ft _pinglife|0 _wavedelay|20 _wavespacing|10 _silent|true --:(1) DETERMINE CR OF UNDEAD THAT CAN BE DESTROYED| --=charLevel|@{selected|level} --?[$charLevel] -lt 5|>SetCRdestroy;0 --?[$charLevel] -ge 5 -and [$charLevel] -lt 8|>SetCRdestroy;0.5 --?[$charLevel] -ge 8 -and [$charLevel] -lt 11|>SetCRdestroy;1 --?[$charLevel] -ge 11 -and [$charLevel] -lt 14|>SetCRdestroy;2 --?[$charLevel] -ge 14 -and [$charLevel] -lt 17|>SetCRdestroy;3 --?[$charLevel] -ge 17|>SetCRdestroy;4 --:(2) GET ALL TOKENS INTO THE "allTokens" ARRAY| will have blank 1st element to be removed later --~|array;pagetokens;allTokens;@{selected|token_id} --:(3) CREATE THE "inRange" ARRAY TO HOLD TOKENS IN RANGE| --~|array;define;inRange; --:(4) PREP ARRAY FOR LOOP| if no array elements then end macro --~tokenid|array;getfirst;allTokens --?[&tokenid] -eq ArrayError|endOutput --:(5) FIND ALL TOKENS IN RANGE| --:RangeLoop| --:TOKEN MUST BE ON OBJECTS OR GMLAYER AND TYPE MUST INCLUDE UNDEAD| --?[*[&tokenid]:t-layer] -ne objects -and [*[&tokenid]:t-layer] -ne gmlayer|NextToken --?"[*[&tokenid]:npc_type]" -ninc "undead"|NextToken --:CHECK DISTANCE IN UNITS. 30ft is 5UNITS| --~dist|euclideandistance;@{selected|token_id};[&tokenid] --?[$dist] -gt 5|NextToken --:ADD TO THE "inRange" ARRAY| --~|array;add;inRange;[&tokenid] --:NextToken| --~tokenid|array;getnext;allTokens --?[&tokenid] -ne ArrayError|RangeLoop --:(6) REMOVE DUMMY FIRST ITEM IN inRange ARRAY| --~|array;removeat;inRange;0 --:(7) ROLL SAVES FOR EACH TOKEN IN RANGE| if fail, set a token condition marker to denote turned --~tokenid|array;getfirst;inRange --?[&tokenid] -eq ArrayError|End --:SaveLoop| --&FailureText| -->GetSaveBonus|[&tokenid];wisdom;wis --=SaveRoll|1d20 + [$saveBonus] [BONUS] --?[$SaveRoll.Total] -ge @{selected|spell_save_dc}|>MadeSave|>FailedSave --~tokenid|array;getnext;inRange --?[&tokenid] -ne ArrayError|SaveLoop --:End| --X| --:PROCEDURES| --:SetCRdestroy| accepts CR as parameter --=CRdestroy|[%1%] --<| --:GetSaveBonus| accepts tokenid, full attribute name, short attribute name as parameters --:TAKE THE GREATER OF "attribute_save_bonus" OR "npc_attr_save_base"| --=bonus1|[*[%1%]:[%2%]_save_bonus] --&bonus2|[*[%1%]:npc_[%3%]_save_base] --:SOMETIMES "npc_attr_save_base" IS BLANK, SO SET TO -99. OTHERWISE USE ATTR VALUE| --?X[&bonus2] -eq "X"|>Set_npc_attr_save_bonus;-99|>Set_npc_attr_save_bonus;[&bonus2] --:FINALLY SET THE SAVE BONUS| --?[$bonus2] -gt [$bonus1]|>SetSaveBonus;[$bonus2]|>SetSaveBonus;[$bonus1] --<| --:Set_npc_attr_save_bonus| blank value is set to -99, otherwise use value stored in attribute --=bonus2|[%1%] --<| --:SetSaveBonus| --=saveBonus|[%1%] --<| --:MadeSave| --+[*[&tokenid]:character_name]:|[#009900][b]Made Save[/b][/#] [$SaveRoll] --<| --:FailedSave| add either a dead or fear condition marker to the token, depending on CR --=CR|[*[&tokenid]:npc_challenge] --?[$CR] -le [$CRdestroy]|>AddConditionMarker;[&tokenid];dead;-Destroy|>AddConditionMarker;[&tokenid];Fear::1510130;-Turn --+[*[&tokenid]:character_name]:|[#990000][b]Failed Save[/b][/#] [$SaveRoll] [b][&FailureText][/b] --<| --:AddConditionMarker| accepts tokenID, condition marker, and descriptive text as parameters --@token-mod|_ignore-selected _ids [%1%] _set statusmarkers|[%2%] --&FailureText|[%3%] --<| }}
Donald K. said: Jay R. I appreciate the explanation, and the work contributed. Thank you!   No problem at all. I've benefited so much from the support and guidance of the Roll20 user community that I'm happy to pay that forward, in my own limited way. :)
Do you have the token-mod api script installed? Also, it looks like you need the  Players can use --ids option set to true (can be set from the api console, then restart your sandbox). I just toggled mine off and no condition markers were set. Sorry I failed to denote any of that that as a dependency in my original post, but I'll edit it to include that note. @DM Goss, that may have been your problem, as well? Yeah, that's the problem I had with putting the condition markers on undead. Once I clicked the  Players can use --ids   option (and used my own custom markers) it worked perfectly.