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

[Token-Mod] Individual character damage reduction with AOE target-selecting damage macro

I am trying to apply damage to a bunch of starship tokens at once by changing their bar values. Several of the ships have a damage reduction score of 10. I want to apply the damage correctly for all the tokens. Currently, the macro kind of  works, but is having some problems with target selection, I think. I've noticed it continues to let me select "Target 8" repeatedly after the prompt appears for the damage amount. It applies correctly to some targets, but does nothing to others and occasionally applies the damage more than once if I click the same target twice (which I thought Token Mod was supposed to prevent). I think it is not correctly selecting all the targets. It almost always fails to apply any damage to target 8 (the last one). I'm also using the CFX and Delay scripts. Here's the macro, which is called as an ability from my Macro Holder character sheet. Integrity is the ship's damage reduction stat, which all the ships do have, though for some the value is 0. The macro usually applies the damage correctly to these, so the 0 isn't the issue. I kept the non-relevant parts in because the mistake might be there. I know I had some problems with open brackets never being closed, but I fixed the ones I could find. !roll20AM --audio,play,nomenu,mode:single | CruiserMissileHit !delay 0.5 --!cfx ShipHitMedium @{target|1|token_id} @{target|1|token_id} @{target|2|token_id} @{target|3|token_id} @{target|4|token_id} @{target|5|token_id} @{target|6|token_id} @{target|7|token_id} @{target|8|token_id} !delay 0.55 --!token-mod --ids @{target|1|token_id} @{target|2|token_id} @{target|3|token_id} @{target|4|token_id} @{target|5|token_id} @{target|6|token_id} @{target|7|token_id} @{target|8|token_id} --set tint_color|rgb(64,0,0) !token-mod --ids @{target|1|token_id} --set bar3_value|-[[?{Damage|60}-@{target|1|Integrity}]]! !token-mod --ids @{target|2|token_id} --set bar3_value|-[[?{Damage|60}-@{target|2|Integrity}]]! !token-mod --ids @{target|3|token_id} --set bar3_value|-[[?{Damage|60}-@{target|3|Integrity}]]! !token-mod --ids @{target|4|token_id} --set bar3_value|-[[?{Damage|60}-@{target|4|Integrity}]]! !token-mod --ids @{target|5|token_id} --set bar3_value|-[[?{Damage|60}-@{target|5|Integrity}]]! !token-mod --ids @{target|6|token_id} --set bar3_value|-[[?{Damage|60}-@{target|6|Integrity}]]! !token-mod --ids @{target|7|token_id} --set bar3_value|-[[?{Damage|60}-@{target|7|Integrity}]]! !token-mod --ids @{target|8|token_id} --set bar3_value|-[[?{Damage|60}-@{target|8|Integrity}]]! !delay 0.6 --!token-mod --ids @{target|1|token_id} @{target|2|token_id} @{target|3|token_id} @{target|4|token_id} @{target|5|token_id} @{target|6|token_id} @{target|7|token_id} @{target|8|token_id} --set tint_color|rgb(128,0,0) !delay 0.65 --!token-mod --ids @{target|1|token_id} @{target|2|token_id} @{target|3|token_id} @{target|4|token_id} @{target|5|token_id} @{target|6|token_id} @{target|7|token_id} @{target|8|token_id} --set tint_color|rgb(256,0,0) !delay 0.7 --!token-mod --ids @{target|1|token_id} @{target|2|token_id} @{target|3|token_id} @{target|4|token_id} @{target|5|token_id} @{target|6|token_id} @{target|7|token_id} @{target|8|token_id} --set tint_color|rgb(128,0,0) !delay 0.75 --!token-mod --ids @{target|1|token_id} @{target|2|token_id} @{target|3|token_id} @{target|4|token_id} @{target|5|token_id} @{target|6|token_id} @{target|7|token_id} @{target|8|token_id} --set tint_color|rgb(64,0,0) !delay 0.8 --!token-mod --ids @{target|1|token_id} @{target|2|token_id} @{target|3|token_id} @{target|4|token_id} @{target|5|token_id} @{target|6|token_id} @{target|7|token_id} @{target|8|token_id} --set tint_color|transparent Any insight would be appreciated.
1632006399
timmaugh
Forum Champion
API Scripter
I think the unique-ing of your ids happens in TokenMod only if they are in the same command line. When you send the damage through, it comes as individual line entries for each target.  You can obtain a unique set (and shorten your macro) using a few metascripts. SelectManager offers a way to virtually select tokens (which could still use the targeting function of Roll20), and it will limit the tokens selected to a unique set. It can then can iterate commands over those tokens with the forselected handle. Fetch can then retrieve differentiated, token-specific information to fill in the appropriate unique portions of the command line. That could make the middle bit reduce down to one line: !forselected(^) token-mod --set bar3_value|-^[^[?{Damage|60}-@^(selected.Integrity)^]^] {&select @{target|1|token_id}, @{target|2|token_id}, @{target|3|token_id}, @{target|4|token_id}, @{target|5|token_id}, @{target|6|token_id}, @{target|7|token_id}, @{target|8|token_id} } That would require SelectManager and Fetch. To make sure they ran in the correct order, I'd also suggest ZeroFrame. If you like that result, I'm thinking of other ways to condense your macro with metascript constructions... which might give the possibility of expanding beyond 8 targets.
As so often happens, the answer is MOAR SCRIPTS. XD I will give SelectManager and Fetch a try, thanks!
Okay, that works for the most part but now the damage reduction isn't being applied at all. All the ships take the same damage regardless of which ones have an Integrity attribute greater than 0.
Also, I was using targeting because I didn't know a better way to do this with token mod. Would SelectManager make it possible to just select a bunch of tokens and hit the macro? Cause that would seem to be much more effective. As it is now I have to select at least 8 targets, and if I double up that ship takes damage twice, which isn't what I'm after.
1632015812

Edited 1632015925
timmaugh
Forum Champion
API Scripter
Yes... Token-Mod will act on selected tokens by default. Since SelectManager's forselected feeds your selected tokens to your command line one at a time, that should let us get differentiated information (Fetch) from it. So as long as you can select the tokens on the tabletop (like, if you are the GM), that plan should work. You can use forselected to send commands to the delay script (which sends commands to the TokenMod script -- around and around we go), or you could embed the secondary calls for a given ship into a main call using Plugger. Although, there is no differentiated information to pull from the ships when you are adjusting their auras... so there really isn't a reason to use forselected for those delay calls... hmm... Let me look at that and why your Fetch construct is returning the same value for every ship. I have an idea what might be going on there, but I can run a couple of scenarios in my test game and tell for sure. I can probably come back with the fully compressed script, relying on you actually selecting the ships on the VTT.
You are a very helpful person, and I hope you know how well that reflects on you.
1632022366

Edited 1632054411
timmaugh
Forum Champion
API Scripter
Thanks! OK, I was right about what was going on. When the iterated command is sent for each selected token, the inline roll tries to parse before Fetch has a chance to pull in the proper information. We have to defer it in a way that won't fire until after Fetch retrieves the Integrity value, and for that we have to rely on ZeroFrame. It's really deep in the meta sauce, but the ZeroFrame deferral works because it doesn't fire before forselected fires off the command line. Since nothing changes about the command line before forselected sends the command, ZeroFrame's deferral character's stay in the line, waiting to do their work over each iterated command. Like I said. Deep. Sauce. The following should work, provided you select the tokens before you begin: !roll20AM --audio,play,nomenu,mode:single | CruiserMissileHit !forselected(^) delay 0.5 --!cfx ShipHitMedium @^(selected.token_id) !delay 0.55 --!token-mod --set tint_color|rgb(64,0,0) !forselected(^) token-mod --set bar3_value|-[\][\]?{Damage|60}-@^(selected.Integrity)\]\] !delay 0.6 --!token-mod --set tint_color|rgb(128,0,0) !delay 0.65 --!token-mod --set tint_color|rgb(256,0,0) !delay 0.7 --!token-mod --set tint_color|rgb(128,0,0) !delay 0.75 --!token-mod --set tint_color|rgb(64,0,0) !delay 0.8 --!token-mod --set tint_color|transparent REQUIRED SCRIPTS: SelectManager, Fetch, ZeroFrame
1632023395
timmaugh
Forum Champion
API Scripter
BTW, the reason you can do this: !delay 0.7 --!token-mod ... ...and not need to use TokenMod's --ids argument is because you have SelectManager installed. It restores the selected tokens when one script calls another script.
When I run this macro, it errors out my API and posts the following: Your scripts are currently disabled due to an error that was detected. Please make appropriate changes to your script's code and click the "Save Script" button. We will then attempt to start running the scripts again.  More info...  If this script was installed from the Script Library, you might find help in the Community API Forum. For reference, the error message generated was:  SyntaxError: Expected "(", ".", "[", "abs(", "ceil(", "d", "floor(", "round(", "t", "{", [ |\t], [+|\-] or [0-9] but "e" found. undefined I'm not really sure what to make of that. It's finding a letter "e" when it's looking for a bracket or something? I don't see any loose "e"s in the macro.
Okay, I looked at the ZeroFrame documentation and figured out there was a missing "]". I put that in, and now the macro works without errors in the API, but seems to fail and do nothing if I have more than two or three tokens selected. It also doesn't work if I select tokens by drawing a rectangle around them rather than clicking each one, and sometimes I have to run the macro twice to make it do anything. When it does run, however, it calculates the damage reductions properly! So that's definitely progress.
1632055738
timmaugh
Forum Champion
API Scripter
Yes, sorry. Thanks for catching that. I was testing the macro in parts and reconstructing it here, and I just missed that bracket. It shouldn't matter how you select the tokens, they are selected for the purposes of the message. You can check that with something simple like this: !forselected(^) @^(selected.token_name){^&simple} No matter how you select the tokens, you should see the same names hitting the chat. If we have it working but it is firing intermittently, I think what you're running into is a known bug where Roll20 is dropping some command lines out of multi-command macros.
Interesting. I guess I'd better pare down the flashy bits and focus on just the most  important lines for the time being. Thanks again! 
1632063369
timmaugh
Forum Champion
API Scripter
Well, at the risk of saying, "MOAR scripts!", You could potentially wrap parts of this in Plugger tags, leaving you with a single command line that encompasses the others. One command to the API would, through Plugger, fire the other commands. The thought would be that single command macros don't drop, as far as we can tell, and once it fires, the scripts are taking care of the rest of the messages. I'll see if I can put that together for you...
1632070294

Edited 1632070642
Wow, that sounds perfect! I wonder what percentage of the 'code' my game is running is native Roll20 stuff and what percentage is scripts at this point XD
Wow, it was definitely the command dropping lines. I removed everything but the actual damage line and the sound effect and now it works much more reliably. I'd like to use that Plugger trick to at least get the cfx command back so my players can see who's getting hit, but this will definitely get the job done for now.  Timmaugh, you have been helping me out a lot. Do you have anything set up where I can buy you a coffee or something?
1632077091
timmaugh
Forum Champion
API Scripter
OK, theoretically, this should work. I don't have all of the scripts, the particular track, fx, etc., so I can't give it a proper test, but this basically wraps each element in a Plugger {&eval} tag, all ultimately embedded in the last command in the series. Since Plugger works left to right, outside-in, all of the plugger constructs will run still in the correct order. And since they all run before the housing command line, it makes sense to have the last command be that housing command. Try this: !{&eval}roll20AM --audio,play,nomenu,mode:single | CruiserMissileHit{&/eval}{&eval}forselected(^) delay 0.5 --!cfx ShipHitMedium @^(selected.token_id){&/eval}{&eval}delay 0.55 --!token-mod --set tint_color|rgb(64,0,0){&/eval}{&eval}forselected(^) token-mod --set bar3_value|-[\][\]?{Damage|60}-@^(selected.Integrity)\]\]{&/eval}{&eval}delay 0.6 --!token-mod --set tint_color|rgb(128,0,0){&/eval}{&eval}delay 0.65 --!token-mod --set tint_color|rgb(256,0,0){&/eval}{&eval}delay 0.7 --!token-mod --set tint_color|rgb(128,0,0){&/eval}{&eval}delay 0.75 --!token-mod --set tint_color|rgb(64,0,0){&/eval}delay 0.8 --!token-mod --set tint_color|transparent
When I run this, it plays the sound effect but nothing else happens. It also tries to print something to the chat, but it's just blank. Seems like a typo, probably? I'll look through it and see if I can figure it out.