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

Multiple Targets - Deselecting after running macro

Morning all, I'm working on a script that will allow me to damage or heal selected tokens, I plan to put these in button form so I don't have to keep typing out the command every time (e.g. 1, 5, 10, 50 options). Everything works, except when I have multiple targets - they get deselected after each click of the macro. It doesn't happen for single targets. Am I missing something? Thanks :)
1707933162

Edited 1707935255
Hi Josh We have a weapon effect that targets a variable number of targets and use this script for it.&nbsp; If you look you can see it is based heavily on Kurt J's Magic Missile and also another piece of his that produces an array of targets.&nbsp; Perhaps you could adapt this?&nbsp; It wouldn't take much to add a query for whether healing or harm and thus make the final amount of damage used by Token-Mod a positive or negative.&nbsp; If saves don't factor, that part could easily be chopped out or DC set ridiculously high? !script {{ --/| Let’s set up some basics, starting with the card layout --#bodyfontface|Helvetica --#bodyfontcolor|#220000 --#buttonfontsize|9px --#buttonbackground|#2c0f70 --#buttonfontface|Tahoma --#titlecardbackground|#f6efd6 --#titlefontcolor|#ffffff --#titlefontsize|1.5em --#titlefontshadow|0 --#titlecardBackgroundImage|url(' <a href="https://s3.amazonaws.com/files.d20.io/images/248538196/c9xft1A2jWNqOkBsxQwyLQ/max.jpg?1633278017" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/248538196/c9xft1A2jWNqOkBsxQwyLQ/max.jpg?1633278017</a> '); background-size: 100% 100%; background-repeat: no-repeat; --#oddrowbackground|#f6efd6 --#evenrowbackground|#f6efd6 --#subtitlefontcolor|#58180d --#sourceToken|@{selected|token_id} --#emoteText|@{selected|character_name} uses SPELLNAME HERE to blast enemies with lightning! --=SaveDC|DC [[8 + @{selected|PB} + @{selected|constitution_mod}]] Dex save --+| [c]DC [$SaveDC] Dex Save[/c] --/|Now the script. Set this to either "scriptcards" or anything else to not apply damage --&amp;damageApplyScript|scriptcards --/|Set this to the bar number you use to track hit points --&amp;hitPointsBar|1 --/|If damageMode is 1, a separate die will be rolled for each missile. Set this variable to 0 to, --/|only have a single damage die roll applied to each missile. --&amp;damageMode|0 --&amp;damageType|lightning --#reentrant|targetPicker_[&amp;SendingPlayerID] --#title|SPELLNAMEHERE --#whisper|self --/|Helper variable build up to allow us to include a target prompt in an rbutton --&amp;TB|&amp; --&amp;TB|+# --&amp;TB|+64 --&amp;TB|+; --&amp;TB|+{ --&amp;TargetBase|[&amp;TB]Target|Target_##|token_id} --&amp;ButtonEnd|[/rbutton] --&amp;BaseButton|[rbutton]##::AddTarget;[&amp;TargetBase] --&amp;ButtonArray(0)|[&amp;BaseButton(replaceall,##,1)] --%loop|1;9 --&amp;ButtonArray([&amp;loop])|[@ButtonArray([=[&amp;loop] - 1])]|[&amp;TargetBase(replaceall,##,[=[&amp;loop]+1])] --&amp;temp|[@ButtonArray([&amp;loop])] --&amp;rep|[=[&amp;loop] + 1]:: --&amp;find|[&amp;loop]:: --&amp;ButtonArray([&amp;loop])|[&amp;temp(replaceall,[&amp;find],[&amp;rep])] --%| --%loop|0;[@ButtonArray(maxindex)] --&amp;ButtonArray([&amp;loop])|[@ButtonArray([&amp;loop])][&amp;ButtonEnd] --%| --+|[c]Choose number of targets[/c][br] --&amp;output|[c] --%loop|foreach;ButtonArray --&amp;output|+[&amp;loop] --%| --&amp;output|+[/c] --+|[&amp;output] --X| --:ShowTargetList|Y or N for including removeal buttons --?"[@targetList()]" -eq ""|&lt; --?"[@targetList()]" -eq "undefined array"|&lt; --=Index|0 --%loop|foreach;targetList --&amp;append|[r][rbutton]X::RemoveTarget;[$Index.Raw][/rbutton][/r] --?"[%1%]" -ne "Y"|&amp;append; --+Target|[&amp;loop] ([*[&amp;loop]:t-name]) [&amp;append] --=Index|[$Index] + 1 --%| --&lt;| --/|Reentrant point for the "Add Target" button --:AddTarget| --~|array;define;inRange;[&amp;reentryval(replaceall,|,;)] --=TargetNum|[@inRange(length)] --/|Calculate damage --=DamageDice|3 --=Damage|[$DamageDice.Total]d8 --=HalfDamage|[$Damage.Total] \ 2 --/|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] --+|&amp;nbsp; --/|Loop through the inRange tokens and roll saves for each one and apply damage --~tokenid|array;getfirst;inRange --?[&amp;tokenid] -eq ArrayError|endOutput --:loopDisplay| --&gt;MakeSavingThrow|[&amp;tokenid];dexterity;[[8 + @{selected|PB} + @{selected|constitution_mod}]] ;[$Damage.Total];lightning;thisTokenDamage;saveResult;dex --+[*[&amp;tokenid]:character_name]:|Rolled [$savingThrow] [r][$thisTokenDamage] lightning damage[/r] --&gt;ApplyDamageTokenmod|[&amp;tokenid];1;[$thisTokenDamage] --/|Put a burn-fire visual effect on impacted tokens --vtoken|[&amp;tokenid] burn-frost --/|Get the next token and continue the loop until we run out. --~tokenid|array;getnext;inRange --?[&amp;tokenid] -ne ArrayError|loopDisplay --/|Add some extra visual effects - a nova-fire at the target, and a beam-fire from source to target --vtoken|[&amp;tokenid] nova-frost --vbetweentokens|@{selected|token_id} [tokenid] beam-magic --:endOutput| --X| --/|Subroutine to make saving throws and calculate damage amounts --:MakeSavingThrow|tokenid;savetype;dc;damage;damagetype;damagevariable;saveresultvariable;shortabilityname --&gt;GetSaveBonus|[&amp;tokenid];dexterity;dex --=savingThrow|1d20 + [$saveBonus] [BONUS] --&amp;dmgmult| --?[$savingThrow] -ge [%3%]|&gt;set_string;dmgmult; \ 2 --?[$savingThrow] -lt [%3%]|&gt;set_string;[%7%];fail --?[$savingThrow] -ge [%3%]|&gt;set_string;[%7%];success --?"[*[%1%]:npc_resistances]" -inc "[%5%]" -and [$savingThrow] -lt [%3%]|&gt;set_string;dmgmult; \ 2 --?"[*[%1%]:npc_resistances]" -inc "[%5%]" -and [$savingThrow] -ge [%3%]|&gt;set_string;dmgmult; * 0 --?"[*[%1%]:npc_vulnerabilities]" -inc "[%5%]" -and [$savingThrow] -ge [%3%]|&gt;set_string;dmgmult; --?"[*[%1%]:npc_vulnerabilities]" -inc "[%5%]" -and [$savingThrow] -lt [%3%]|&gt;set_string;dmgmult; * 2 --?"[*[%1%]:npc_immunities]" -inc "[%5%]"|&gt;set_string;dmgmult; * 0 --=[%6%]|[%4%] [&amp;dmgmult] --&lt;| --:set_string|mod_variable;value --&amp;[%1%]|[%2%] --&lt;| --: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] --&amp;bonus2|[*[%1%]:npc_[%3%]_save_base] --:SOMETIMES "npc_attr_save_base" IS BLANK, SO SET TO -99. OTHERWISE USE ATTR VALUE| --?X[&amp;bonus2] -eq "X"|&gt;Set_npc_attr_save_bonus;-99|&gt;Set_npc_attr_save_bonus;[&amp;bonus2] --:FINALLY SET THE SAVE BONUS| --?[$bonus2] -gt [$bonus1]|&gt;SetSaveBonus;[$bonus2]|&gt;SetSaveBonus;[$bonus1] --&lt;| --:Set_npc_attr_save_bonus| blank value is set to -99, otherwise use value stored in attribute --=bonus2|[%1%] --&lt;| --:SetSaveBonus| --=saveBonus|[%1%] --&lt;| --/|Subroutine to apply damage with TokenMod. Could be replcaed with alterbars or chatsetattr --:ApplyDamageTokenmod|Parameters are tokenid;bar#;amount --@token-mod|_ids [%1%] _set bar[%2%]_value|-[%3%] --&lt;| }} --%loop|1;9 sets the number of targets, currently 10 Hope that helps? EDIT - the saving rolls bit comes from David M (I think) and their Turn Undead script.&nbsp; I realise the script could be polished up so references to magic missile etc are taken out, but I needed to get up and running swiftly for the final session of Descent and so as long as it worked I was happy.&nbsp;
Hi Simon,&nbsp; I've got the script written and macro setup, my plan was to have a selection of buttons to accumulate damage. So with tokens selected, for 36 points of damage, I could just click 10, 10, 10, 5, 1. The only issue I'm getting is that when performing on multiple targets, they are deselected after the first click (all of them). It doesn't behave the same if a single target is selected which is strange.&nbsp; Right now I've got the script holding them in a list or an array (can't remember which off the top of my head). I just can't find a way to select those tokens once more. As much as I'd like to know why they get deselected, I'd be happy just tagging a tokenSelect function on the end.&nbsp; Thanks,&nbsp; Josh.&nbsp;
Hi Josh, my understanding is that the part of the script above that does the token select bit is essential as a way to select multiple tokens because of how Roll20 processes. Unfortunately I am very much starting out with scripting and can't really advise, I was just hoping you would butcher that as required. I saw 3 scripts that all had something I liked so I chopped and stitched. It works, but I don't pretend to understand all of it The discord server for Scriptcards is incredibly useful, f you post there I m sure you will get the support you need
Hey Josh, I don't know about how to get Roll20 to not deselect the tokens but if you are open to a ScriptCards &nbsp;option, this would do what you are asking for: !scriptcard {{ --/|Will present buttons for healing and damage and then perform that on the token bar --/|Requires: ScriptCards 2.6.2+ --/|VARIABLES TO SET --&amp;HPBar|1 --#title|Adjust HP for Selected --#reentrant|HPAdjuster[$SendingPlayerID] --&gt;LibSN_COPY_ARRAY|SC_SelectedTokens;HPTokenList --+|[b][c]Heal Selected[/b][/c] --+|[c][rbutton]10::ReentryPoint;10[/rbutton][rbutton]5::ReentryPoint;5[/rbutton][rbutton]1::ReentryPoint;1[/rbutton][/c] --+|[c][b]Damage Selected[/b][/c] --+|[c][rbutton]-10::ReentryPoint;-10[/rbutton][rbutton]-5::ReentryPoint;-5[/rbutton][rbutton]-1::ReentryPoint;-1[/rbutton][/c] --X| --:ReentryPoint|HPAdjustmentAmount --#hidecard|1 --&gt;LibSN_APPLY_DAMAGE_OR_HEALING_TO_ARRAY|HPTokenList;[&amp;HPBar];[&amp;reentryval];0 --X| --/|The following are functions from Kurt J's systemneutrallib library --/|Including them in this ScriptCard for completeness without requiring a library handout --/|<a href="https://github.com/kjaegers/ScriptCards/blob/main/ScriptCards_Examples/libraries/systemneutrallib.scard" rel="nofollow">https://github.com/kjaegers/ScriptCards/blob/main/ScriptCards_Examples/libraries/systemneutrallib.scard</a> --/|Not using the existing SELECTED function since this is re-entry script and SC_Selected can change --/|This script will use the selected tokens as of the first run --:LibSN_APPLY_DAMAGE_OR_HEALING|tokenid;bar#;amount;display (0 or 1) --=_applyValue|[%3%] --=_newValue|[*[%1%]:t-bar[%2%]_value] + [$_applyValue] --?[$_newValue] -lt 0|=_newValue;0 --?[$_newValue] -gt [*[%1%]:t-bar[%2%]_max]|=_newValue;[*[%1%]:t-bar[%2%]_max] --?"X[%4%]" -eq "X1"|+Applying;[%3%] HP to [*[%1%]:t-name] --!t:[%1%]|bar[%2%]_value:[$_newValue.Raw] --&lt;| --:LibSN_APPLY_DAMAGE_OR_HEALING_TO_ARRAY|ArrayName;bar#;amount;display (0 or 1) --%_thisToken|foreach;[%1%] --&gt;LibSN_APPLY_DAMAGE_OR_HEALING|[&amp;_thisToken];[%2%];[%3%];[%4%] --%| --&lt;| --:LibSN_COPY_ARRAY|SOURCE;DEST;START (OPTIONAL);END (OPTIONAL) --&amp;_STARTCOUNT|[%3%] --&amp;_ENDCOUNT|[%4%] --?"[&amp;_STARTCOUNT]" -eq ""|&amp;_STARTCOUNT;0 --?"[&amp;_ENDCOUNT]" -eq ""|&amp;_ENDCOUNT;[@[%1%](maxindex)] --~dummy|array;[%2%];define --=_DESTITEM|0 --%_loop|[&amp;_STARTCOUNT];[&amp;_ENDCOUNT] --&amp;[%2%]([$_DESTITEM.Raw])|[@[%1%]([&amp;_loop])] --=_DESTITEM|[$_DESTITEM] + 1 --%| --&lt;| }} So when you click the button in chat, it will still de-select the tokens on the board but with this ScriptCard the selected token list is remembered from when it is first run and the buttons will still work. The example in chat looks like this currently: And hitting the various buttons will add or subtract the specified amounts. Note that this is currently set to modify token bar 1 but can be adjusted by changing the following String variable near the top of the ScriptCard: --&amp;HPBar|1 If you want it to only whisper to you that can be changed by adding either --#whisper|self or --#whisper|gm below the --#title.
Hi Joshua, As nice as that looks, I wanted something that just pops up when I have tokens selected. Unless I'm misunderstanding, I'd have to call the script to get that into chat, no? At which point I may as well just be calling the script that removes or adds health. Thanks anyways though!
To explain, that is a macro, you can add that to your Collections tab as a Macro and then click it as a token action or in the macro bar depending. You would install&nbsp; ScriptCards &nbsp;as the the API Script/Mod and then this is a macro written in the ScriptCards syntax that provides a chat menu with the buttons. If you would prefer to not have it be a chat menu, it could be turned into individual macros with specified health. ScriptCards is pretty flexible and was just a way to get around the issue you were having.
Hi Joshua, Sorry, yeah it makes sense now that you've said that *face palm*. I'm still pretty fresh with the syntax for js, so I'll wait a little while before expanding my horizons further. Might be sped up if I find myself reselecting tokens too many times in one go.&nbsp; It certainly looks great though and it will no doubt be help should anyone else stumble across this thread. Thanks very much all! P.S.&nbsp; Just out of curiosity, do you know if ScriptCards is able to detect either: The map of a selected token, or the map that the GM is on? I've rustled up a script to randomise movement for my free roaming "tokens" on the world map, but I've had to hard code the dimensions. Would like to make it more universal if I can... It could be this that forces me to take the leap into ScriptCards. Feel free to PM so the thread doesn't extend beyond it's title.&nbsp; (&gt;_&lt;)
ScriptCards can get the page of a token. Graphic objects (ie tokens) have a property named _pageid. So for example the following: !script {{ --#sourceToken|@{selected|token_id} --+[*S:t-name]|is on the page named [*O:[*S:t-_pageid]:page:name] }} So the first line: --#sourceToken|@{selected|token_id} uses the Roll20 attribute call @{} which Roll20 will process before any ScriptCard is processed. That will end up with the ScriptCard&nbsp;parameter for sourceToken &nbsp;which will allow ScriptCards references for attributes and token properties using [*S: So that in the following line: --[*S:t-name] will use the sourceToken's token name. Note that token properties are prefixed by t-&nbsp; So [*S:t-_pageid] will get the Page ID of the source token and then that is placed within [*O:&lt;ID&gt;:page:name] to get the name of the page. You can also get the page that the player ribbon is on with [*C:playerpageid] Also recently Kurt pushed an alpha for 2.7.0 to his Github that will allow the player specific pages to be set as well. If you need help with your new script, let me know. I have a number of ScriptCards macros and triggers around token movement on a grid.
1709852110
Kurt J.
Pro
API Scripter
Unfortunately, as far as I know there is no way to tell what page the GM is looking at with the Roll20 API.