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

API for manipulating bar values

Hi all, hope I'm posting this in the right place. I am trying to replicate the Resident Evil 4 puzzle where the players have to manipulate liquids in 3 vials correctly to progress (for reference, search Resident Evil 2 Remake Liquid Solution Machine puzzle).

My initial hope was to use to create a token for the liquid container, have all three bars visible, and have custom token macros for the liquid container that would split, swap and reset the bar values to replicate the RE2 puzzle. I tried doing this initially with TokenMod, but you can't get bar values (only set them) or store the current bar values as variables with TokenMod, which is important for the puzzle to update dynamically when the players split/swap the values.

I also tried PowerCards, as you can create variables with that API, but there doesn't seem to be any way to get/set bar values in that one either. I tried looking at AlterBars as well, but it doesn't seem to be in the Mod Library and I'm not sure how to install it manually (as you can tell, I'm new to Roll20 APIs).

Is there an API that could do the above? As in be able to get and set bar values, while also being able to store them as variables? Or is there a method of doing it with TokenMod and PowerCards that I haven't considered?

I bet you could accomplish this with a combination of TokenMod and MetaScript toolbox scripts and hopefully timmaugh comes along to show that option but you should be able to do this with ScriptCards.

ScriptCards can be used to get values from a token, with object referencing, short example below using the sourceToken parameter:

!script {{
--#sourceToken|@{selected|token_id}
--&currentBar1|[*S:t-bar1_value]
--&currentBar2|[*S:t-bar2_value]
--&currentBar3|[*S:t-bar3_value]
--+Current Levels|[&currentBar1] [&currentBar2] [&currentBar3]
}}

ScriptCards can also modify objects including the values of a token's bars, the following example will swap the values of bar1 and bar3:

!script {{
--#sourceToken|@{selected|token_id}
--&currentBar1|[*S:t-bar1_value]
--&currentBar2|[*S:t-bar2_value]
--&currentBar3|[*S:t-bar3_value]
--+Current Levels|1:[&currentBar1] 2:[&currentBar2] 3:[&currentBar3]
--!graphic:[*S:t-id]|bar1_value:[&currentBar3]|bar3_value:[&currentBar1]
--+New Levels|New 1:[*S:t-bar1_value] New 3:[*S:t-bar3_value]
}}

So one option you can use to get and set token bars is by using ScriptCards. Like I said though, I bet there are MetaScripts like Fetch that can also accomplish what you want to do. I'm just more familiar with ScriptCards but there should be more ways to accomplish this task.

If you want help with the ScriptCards, I can probably help with that. There are also links on the ScriptCards wiki to support threads on this forum and quite helpful Discord server as well.

May 18 (1 year ago)

Edited May 18 (1 year ago)
David M.
Pro
API Scripter

EDIT - ninja'd!

Scriptcards sounds perfect for this application. It can read bar values, perform math, apply the new values, and report the current status after application. 

I'm not sure of the exact math you need, but here's a template you could use as a starting point. I am assuming bar1=Green, bar2=Blue, and bar3=Red. It queries for the desired action (Fill, swap B/G, swap B/R) and calls the appropriate function based on a conditional.

For the "Fill" math, I took half of the absolute value of the difference between Blue & Green (rounded down using integer division "\"). You should modify this as needed. Note that Scriptcards math operations read from left to right. They don't respect PEMDAS rules.

!script {{
  --&action|?{Action?|Fill Green with Blue,Fill|Swap Green/Blue,GB|Swap Blue/Red,BR}

  --#emotestate|0
  --#sourcetoken|@{selected|token_id}
  --=targetVal|50
  --=val1|[*S:t-bar1_value]
  --=val2|[*S:t-bar2_value]
  --=val3|[*S:t-bar3_value]
 
  --?"[&action]" -eq "Fill"|>Fill
  --?"[&action]" -eq "GB"|>SwapGreenBlue
  --?"[&action]" -eq "BR"|>SwapBlueRed

  --:DISPLAY CURRENT VALUES|
  --+Target Value [#009900](Green)[/#]|[$targetVal]
  --+[c]~~ Current Values ~~[/c]|
  --+[#009900]Green[/#]|[#009900][b][*S:t-bar1_value][/b][/#]
  --+[#000099]Blue[/#]|[#000099][b][*S:t-bar2_value][/b][/#]
  --+[#990000]Red[/#]|[#990000][b][*S:t-bar3_value][/b][/#]

  --X| End macro

  --:FUNCTIONS|
  --:Fill|
      --#title|Filling Green with Blue
      --=amountToFill|[$val2] - [$val1] {ABS} \ 2
      --=val1|[$val1] + [$amountToFill]
      --=val2|[$val2] - [$amountToFill]
      --!t:[*S:t-id]|bar1_value:[$val1.Raw]|bar2_value:[$val2.Raw]
  --<|
  --:SwapGreenBlue|
      --#title|Swapping Green/Blue
      --!t:[*S:t-id]|bar1_value:[$val2.Raw]|bar2_value:[$val1.Raw]
  --<|
  --:SwapBlueRed|
      --#title|Swapping Blue/Red
      --!t:[*S:t-id]|bar2_value:[$val3.Raw]|bar3_value:[$val2.Raw]
  --<|
}}

Here's some sample output. I didn't "solve" the puzzle, but it gives the idea.


May 18 (1 year ago)
timmaugh
Forum Champion
API Scripter

I think all you're lacking for being able to do this with TokenMod is the ability to set a variable... because you can reference the bar values easily enough with standard Roll20 syntax. So, while I review the rules of the actual Resident Evil puzzle... here is how you can store a variable in any command line (with the metascript toolbox installed):

{&global ([VariableName1] Variable1 Value Here) ([VariableName2] Variable2 Value Here) }

Basically, it's this:

{& global ... }

With a series of variable declarations like this:

([ ... ] ... )

You can have one or more variables declared in each global tag.

Those create text replacements for the rest of the command line, looking for your variable names, and replacing with the value you designate. So you could do something like:

{&global ([ExistingBar3Val] @{selected.bar3}) }

Or, in a TokenMod line:

!token-mod --set bar2|ExistingBar3Val {&global ([ExistingBar3Val] @{selected.bar3}) }

But that brings up a point... Roll20 constructions resolve before TokenMod sees the line... so you should be able to swap them without running into issue. For instance, setting bar2 equal to bar3 and the reverse... both references to the value should resolve before TokenMod gets involved. Or do you need to reference starting values at some point much later in the process?

A lot of things I'm finding when I search for the puzzle are solutions... but can you actually outline the available steps? That is, can you outline the rules and how you might use the command lines we come up with? For instance, if you need to average 2 bar values, let us know that. If you ever need to revert to a previous value... how far back? Back to the beginning? Let us know that, too.

With a little more information, either the ScriptCards solutions, above, or a metascript solution can help, here.

Thanks all, this has all been really helpful! I'll take a look at the metascripts and ScriptCards to see, but yes the biggest hurdle is being unable to set variables. Here's the general overview of the puzzle I'm trying to make:

The players will discover a token for an old fuel generator (this represents the liquid solution machine in RE2). On this token, all 3 bars will be visible. Bar 1 (green for me) will display 12/12, bar 2 (blue for me) will display 0/6, and bar 3 (red for me) will display 0/10.

This token will have the following 4 token actions/abilities available when the players click on it:

  • 1.Add-Bar-2-to-Bar-1 - This will add the value of Bar 2 to Bar 1, but will not exceed Bar 1's maximum. Any excess will remain in Bar 2.
  • 2.Swap-Bar-1-&-Bar-2 - This will swap the current and max values of Bar 1 and 2. So if this button was pressed first, the green bar would turn from 12/12 to 0/6, and the opposite for the blue bar.
  • 3.Swap-Bar-2-&-Bar-3 - The same as the above, but with the blue and red bars.
  • 4.Reset-Bars - This will reset the values and max of all bars back to their starting values.

To complete the puzzle, the players need to get Bar 1 to the value of 8. How this is done in the RE2 puzzle is outlined below for reference:

  • 3.Swap-Bar-2-&-Bar-3 - This makes Bar 2 0/10, and Bar 3 0/6
  • 2.Swap-Bar-1-&-Bar-2 - This makes Bar 1 0/10, and Bar 2 12/12
  • 1.Add-Bar-2-to-Bar-1 - This makes Bar 1 10/10, and Bar 2 2/12
  • 3.Swap-Bar-2-&-Bar-3 - This makes Bar 2 0/6, and Bar 3 2/12
  • 2.Swap-Bar-1-&-Bar-2 - This makes Bar 1 0/6, and Bar 2 10/10
  • 1.Add-Bar-2-to-Bar-1 - This makes Bar 1 6/6, and Bar 2 4/10
  • 3.Swap-Bar-2-&-Bar-3 - This makes Bar 2 2/12, and Bar 3 4/10
  • 2.Swap-Bar-1-&-Bar-2 - This makes Bar 1 2/12, and Bar 2 6/6
  • 1.Add-Bar-2-to-Bar-1 - This makes Bar 1 8/12, and Bar 2 0/6

If I can get the variables stored at the end of each of the 4 macros/token actions, then it's just a case of getting the maths right and TokenMod or ScriptCards can handle the rest. Timmaugh I tried the syntax you provided above as a token action/ability "!token-mod --set bar2|ExistingBar3Val {&global ([ExistingBar3Val] @{selected.bar3}) }" but this just seems to change the bar value to the token's name?

May 19 (1 year ago)
David M.
Pro
API Scripter

Ok, does this work? I can supply screenshots later but I need to run some errands right now.

!script {{
  --&action|?{Action?|Fill Green with Blue,Fill|Swap Green/Blue,GB|Swap Blue/Red,BR|Reset,Reset}

  --#emotestate|0
  --#sourcetoken|@{selected|token_id}

  --:STARTING VALUES|
  --=targetVal|8
  --=startVal1|12
  --=startVal1Max|12
  --=startVal2|0
  --=startVal2Max|6
  --=startVal3|0
  --=startVal3Max|10

  --:GET CURRENT VALUES|
  --=val1|[*S:t-bar1_value]
  --=val1Max|[*S:t-bar1_max]
  --=val2|[*S:t-bar2_value]
  --=val2Max|[*S:t-bar2_max]
  --=val3|[*S:t-bar3_value]
  --=val3Max|[*S:t-bar3_max]
 
  --?"[&action]" -eq "Fill"|>Fill
  --?"[&action]" -eq "GB"|>SwapGreenBlue
  --?"[&action]" -eq "BR"|>SwapBlueRed
  --?"[&action]" -eq "Reset"|>Reset

  --:DISPLAY CURRENT VALUES| reads directly from updated bar values
  --+Target Value [#009900](Green)[/#]|[$targetVal] / [$targetVal]
  --+[c]~~ Current Values ~~[/c]|
  --+[#009900]Green[/#]|[#009900][b][*S:t-bar1_value] / [*S:t-bar1_max][/b][/#]
  --+[#000099]Blue[/#]|[#000099][b][*S:t-bar2_value] / [*S:t-bar2_max][/b][/#]
  --+[#990000]Red[/#]|[#990000][b][*S:t-bar3_value] / [*S:t-bar3_max][/b][/#]

  --?[*S:t-bar1_value] -eq [$targetVal]|[
      --+[c]~~ SUCCESS!!! ~~[/c]|
  --]|

  --X| End macro

  --:FUNCTIONS|
  --:Fill|
      --#title|Filling Green with Blue
      --=tempVal|[$val1] + [$val2]
      --?[$tempVal] -gt [$val1Max]|[
          --=tempVal|[$val1Max]
          --=amountToFill|[$tempVal]
          --=newVal1|[$tempVal]
          --=newVal2|[$val2] - [$tempVal]
      --]|[
          --=newVal1|[$val1] + [$val2]
          --=newVal2|0
      --]|      
      --!t:[*S:t-id]|bar1_value:[$newVal1.Raw]|bar2_value:[$newVal2.Raw]
  --<|
  --:SwapGreenBlue|
      --#title|Swapping Green/Blue
      --!t:[*S:t-id]|bar1_value:[$val2.Raw]|bar1_max:[$val2Max.Raw]|bar2_value:[$val1.Raw]|bar2_max:[$val1Max.Raw]
  --<|
  --:SwapBlueRed|
      --#title|Swapping Blue/Red
      --!t:[*S:t-id]|bar2_value:[$val3.Raw]|bar2_max:[$val3Max.Raw]|bar3_value:[$val2.Raw]|bar3_max:[$val2Max.Raw]
  --<|
  --:Reset|
      --#title|Resetting Values
      --!t:[*S:t-id]|bar1_value:[$startVal1.Raw]|bar1_max:[$startVal1Max.Raw]|bar2_value:[$startVal2.Raw]|bar2_max:[$startVal2Max.Raw]|bar3_value:[$startVal3.Raw]|bar3_max:[$startVal3Max.Raw]
  --<|
}}


Thanks David, I created a macro with the above included, and set it as a token action. When I press the button it comes up with the drop down menu ("Action?: Fill Green with Blue, Swap Green/Blue", etc.) but when I choose one and submit the bars don't seem to change?

May 19 (1 year ago)
David M.
Pro
API Scripter

Are you getting any chat output at all? Scriptcards is installed and your sandbox is running?

May 19 (1 year ago)
timmaugh
Forum Champion
API Scripter

Here is the metascript + TokenMod solution. For this, I created a character called "PuzzleControl" and created four abilities on the sheet:


FILL-1-FROM-2

!token-mod --set bar1_value|+[\][\]{@(selected.bar2),@(selected.max1)-@(selected.bar1)}kl1\]\] bar2_value|-$[[0]].value {&select LiquidPuzzle}

SWAP-1-2

!token-mod --set bar1_value|@(selected.bar2) bar1_max|@(selected.max2) bar2_value|@(selected.bar1) bar2_max|@(selected.max1) {&select LiquidPuzzle}

SWAP-2-3

!token-mod --set bar2_value|@(selected.bar3) bar2_max|@(selected.max3) bar3_value|@(selected.bar2) bar3_max|@(selected.max2) {&select LiquidPuzzle}

RESET

!token-mod --set bar1_value|12 bar1_max|12 bar2_value|0 bar2_max|6 bar3_value|0 bar3_max|10 {&select LiquidPuzzle}

Then I created 2 tokens... one for PuzzleControl and another called "LiquidPuzzle". 

I set the image for "PuzzleControl" to be the value that I wanted the player to reach in any "vial", and placed it near the "LiquidPuzzle".

By using 2 tokens, I could select the control token without obscuring the bars of the puzzle token... I found this to be easier to experience/read. And, by using the {&select} tag from SelectManager, I was able to affect the puzzle token without having it selected. That meant that I used Fetch references to the selected token (rather than Roll20 syntax), so that SelectManager had time to supply the selected token (the "LiquidPuzzle" token), and Fetch retrieved the values from there.

My setup looked like this:


May 19 (1 year ago)
The Aaron
Roll20 Production Team
API Scripter

To really duplicate the puzzle, I think you'd want to have all bars have the same maximum value, but track a logical maximum in a script somewhere, and not show the numbers.  That would probably take quite a bit more work though, and likely a custom script.

Ah that's done it - I tried timmaugh's method and it seems to have done the trick, the only thing I changed was making a LiquidPuzzle character as well as a token. Thanks everyone for your help, I've certainly learned a lot more about how macros work after this!