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

ChatSetAttr inline command using 2 damage rolls

1646386432

Edited 1646386500
For a naruto game I'm in I can absorb chakra when I hit someone and I've got this working perfectly fine with the following inline command: !modattr --name Buzz Aburame --class_resource|+$[[9]]!!! My problem arises in the case that I make a critical hit, I would need to add both the dice roll without additional damage, the $[[9]] in the example above, plus the dice roll of the crit damage, that would be $[[11]] in my case, I have tried executing 2 separate inline commands but then it will only do the first one so instead I attempted: !modattr --name Buzz Aburame --class_resource|+[[$[[9]]+$[[11]]]]!!! but this just throws the following error  I learned that ZeroFrame has some functionality for extracting roll values and being able to operate on them, but I don't seem to be able to use modattr at all with ZeroFrame's inline command functionality (I kinda expected this since ChatSetAttr has its own inline command functionality but was out of other options so decided to give it a quick try) So I've come here looking for someone with more knowledge to hopefully explain to me the correct way of doing this, and for those interested the whole ability is this one, its only the damage portion as I've structured it as a typical roll20 attack where you roll for attack first and only roll damage by clicking the name when you've hit. &{template:dmg} {{globaldamage=%{-Mt_oHwi-h1sowcFIkmT|repeating_attack_-MwOXEOAL-eUwSyYR3dH_attack_crit}}} {{damage=1}} {{dmg1flag=1}} {{dmg1=[[[[1 + floor((@{level} + 1) / 6)]]d4+@{strength_mod}]]}} {{dmg1type=Bludgeoning}} {{dmg2flag=1}} {{dmg2=[[[[1d4]][1d4]+@{strength_mod}]]}} {{dmg2type=Piercing}} {{crit=1}} {{crit1=[[[[1 + floor((@{level} + 1) / 6)]]d4]]}} {{crit2=[[1d4]]}} !modattr --name Buzz Aburame --class_resource|+$[[9]]!!!
1646419958

Edited 1646704101
timmaugh
Forum Champion
API Scripter
ZeroFrame lets you extract the roll value if it gets a chance at the message. To make sure it gets a chance at the message, you'd have to make just a couple of changes to your line... including... 1) starting with an exclamation point 2) ...requiring you to include a {&simple} in the outer command (to output the template at the end) 3) wrap the ChatSetAttr in Plugger constructs ({&eval})... and... 4) Defer the combo roll (including the critical hit) until after the values have been extracted. Here is how you would do that with ZeroFrame and Plugger: !&{template:dmg} {{globaldamage=%{-Mt_oHwi-h1sowcFIkmT|repeating_attack_-MwOXEOAL-eUwSyYR3dH_attack_crit}}} {{damage=1}} {{dmg1flag=1}} {{dmg1=[[[[1 + floor((@{level} + 1) / 6)]]d4+@{strength_mod}]]}} {{dmg1type=Bludgeoning}} {{dmg2flag=1}} {{dmg2=[[[[1d4]][1d4]+@{strength_mod}]]}} {{dmg2type=Piercing}} {{crit=1}} {{crit1=[[[[1 + floor((@{level} + 1) / 6)]]d4]]}} {{crit2=[[1d4]]}}{&simple} {&eval(^)modattr --name Buzz Aburame --class_resource|+[^[^$[[9]].value+$[[11]].value^]^]{&/eval} That hard codes the inclusion of the critical success, so you could conditionally include it (only include it if some condition is met) using APILogic. I have no idea about this system, but as an example, if the test for the critical success was a 4 (on a 1d4) in what looks like Roll #7 (marker #6), then the APIL test would be: {& if $[[6]].value < 4}0{&else}$[[11]].value{&end} Making the whole Plugger syntax: {&eval{^}modattr --name Buzz Aburame --class_resource|+[^[^$[[9]].value+{& if $[[6]].value < 4}0{&else}$[[11]].value{&end}^]^]{&/eval} Obviously that would require APILogic in addition to ZeroFrame and Plugger. Interestingly, I don't think it matters in this case whether you defer the APIL constructions the same way you defer the inline roll in the EVAL block... because before either plugger or apil get a chance at the line, ZeroFrame has already extracted the roll values... after that it doesn't matter whether the logical test happens immediately or in the message that Plugger dispatches. EDIT: fixed typo in the example macro, above (3/7/2022)
When I add an exclamation mark to the front and replace the base inline command with the zeroframe way of doing it as you instructed like so: {&simple} {&eval{^}modattr --name Buzz Aburame --class_resource|+[^[^$[[9]].value+$[[11]].value^]^]{&/eval} it outputs the damage in chat but does not actually update the class resource on the character sheet, now if i boil it down to the simpler version without the crit applying what i learned from you yesterday with tokenmod and change the command to the following just as a test to see if its working at all then it does update the class resource but doesnt output the chatsetattr whisper message to inform it was executed correctly: {&simple} {&eval}modattr --name Buzz Aburame --class_resource|+$[[9]].value{&/eval} again this was just a base test to see if anything would happen by slowly removing the bits I didnt fully understand or figured might be problematic, i ended up finding that the more basic version would only work when changing  {&eval{^}  to  {&eval}  now im assuming the ^ is the character used for defering, so from my understanding applying it should ensure that part of the code waits longer until all rolls have been calculated which is why i find it weird that upon removing it, at least the simple version seems to work and lead me to try the entire thing again without any of the ^ characters likes so: {&simple} {&eval}modattr --name Buzz Aburame --class_resource|+[[$[[9]].value+$[[11]].value]]{&/eval} And that seems to work perfectly, i believe i tried something like that before based on what i learned yesterday but i may have mistaken the lack of a chatsetattr whisper message as it not working, anyways got it to work so thanks for the help! If you would be so kind i would like a little explanation on what the ^ character does and why it seems to behave in the complete opposite way i would expect it to from my understanding of it, and if you have any insight as to why ChatSetAttr doesnt output a response anymore once used inside plugger even though there is no --silent operator present for it id love to understand that as well. As for applying stuff conditionally, at least for crits, roll20 makes that pretty easy, ive got the base to attack roll set up as so: &{template:atk}{{mod=+[[@{strength_mod}+@{pb}]]}} {{rname=[Bug Punch](~bugpunch-damage)}} {{rnamec=[Bug Punch](~bugpunch-crit)}} {{r1=[[1d20+@{strength_mod}[Strength]+@{pb}[Proficiency]]]}} {{always=1}} {{r2=[[1d20+@{strength_mod}[Strength]+@{pb}[Proficiency]]]}} and by filling in  {{rname=}}  it will link to the regular damage roll and  {{rnamec=}}  will link to the damage roll with hardcoded crit damage when it detects either r1 or r2 has rolled the max on the die, for testing purposes i usually set these to 1d2 (if you make it a d1 it wont actually consider it a crit because 1 is the average roll for a d1), but i shall def be looking into APILogic, it seems pretty usefull as well.
1646713649
timmaugh
Forum Champion
API Scripter
Kilidian  said: When I add an exclamation mark to the front and replace the base inline command with the zeroframe way of doing it as you instructed like so: {&simple} {&eval{^}modattr --name Buzz Aburame --class_resource|+[^[^$[[9]].value+$[[11]].value^]^]{&/eval} it outputs the damage in chat but does not actually update the class resource on the character sheet, Unfortunately, that's my fault. I left a typo in the macro code. I'll explain, below. Kilidian said: {&simple} {&eval}modattr --name Buzz Aburame --class_resource|+[[$[[9]].value+$[[11]].value]]{&/eval} And that seems to work perfectly, i believe i tried something like that before based on what i learned yesterday but i may have mistaken the lack of a chatsetattr whisper message as it not working, anyways got it to work so thanks for the help! If you would be so kind i would like a little explanation on what the ^ character does and why it seems to behave in the complete opposite way i would expect it to from my understanding of it, and if you have any insight as to why ChatSetAttr doesnt output a response anymore once used inside plugger even though there is no --silent operator present for it id love to understand that as well. OK, so the ^ would be acting as a deferral character... if I had enclosed it in parentheses instead of braces: {&eval(^)} That's the first problem. I corrected my post, above, to remove this error. In its proper form, the character within the parentheses will be used as a deferral character... meaning that when Plugger dispatches the outbound command line (this time to ChatSetAttr), it will remove that character. Up to that point, the Roll20 parsers have only seen a version of the entire command line (the whole message) that included the deferral character, and the presence of that character meant that the Roll20 parsers didn't properly identify the syntax constructions that it could have. Roll20 won't detect: @^{Actual Cannibal|normal_tuesday_night} ...as something it needs to retrieve from the game-character "Actual Cannibal." However, when Plugger removes the ^ letter-character from the construction and sends the embedded command, the Roll20 parsers have another chance at the line, and this time they recognize the syntax. That's important when you have something that you don't want to be caught by the Roll20 parsers, or something which  can't be caught by the Roll20 parsers immediately... like where you reuse roll markers in a different inline roll: [[$[[9]].value + $[[11]].value]] That syntax would break a normal inline roll. Roll20 doesn't know what to do with it. If you are using that and *not* seeing it break, it very likely is not getting you the correct data. It might be zero-ing out parts of the roll, or using some other static value. What needs to happen is that (1) the source rolls are detected and compiled (rolls $[[9]] and $[[11]] in their original position). Then, (2) ZeroFrame extracts the value of the rolls. Then (3) the outer roll is detected and parsed. Steps 1 and 3 happen in the Roll20 parsers, but each message only passes through them one time. Since Plugger dispatches a new message, it gives you another chance at the R20 parsers. In order for the outer roll to be detected during that later message (and not before ZeroFrame has a chance at the .value constructions), they have to be masked with the deferral character. SIDE NOTE : ZeroFrame also has a deferral character, and it establishes a loop where it passes the message over the Roll20 parsers and the rest of the metascripts until no more meta-constructions are detected. That would also work in this case, but I won't confuse the issue by going into it now. (The syntax is different from Plugger.) Why ChatSetAttr Doesn't Report When a script sends a message through the chat interface (a script-generated message, as opposed to a user-generated message), a few things are lost. There is no set of selected tokens, the "who" of "who sent the message" is changed, as is the "playerid" associated with the message. Most of the time, the lack of selected tokens is the key thing that is lost... (a script calling a second script leaves the second script without a set of selected tokens that it might have been counting on). In your case, you are running into another issue. ChatSetAttr doesn't know to whom to report the output message. Since Plugger is calling ChatSetAttr, the who and the playerid are both lost. The fix for this is to install SelectManager (another metascript). It comes configured to give back the selected tokens, and you can instruct it to give back either/both of the playerid and/or who. Once installed, issue this command: !smconfig +playerid +who One of those should allow ChatSetAttr to properly whisper its output to you to let you know what it has done.