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

[Scripts] Some questions about using scripts for IF statements

October 05 (1 year ago)

Edited October 05 (1 year ago)

My Google-Fu has failed me on this but maybe somebody can help me. Most of my searching just returns "You need scripts to do this" but I haven't found any example scripts to play with. I'm not looking for anyone to hold my hand on this, just looking for the relevant scripts and documentation pages, if you can point me to them!


I'd like to do a few things with API Scripts to try to automate combat a little better. I know IF Statements are not possible with vanilla Macros, but should be with some of the API Scripts floating around out there? I'll try to detail some of my use cases if anyone has ideas for how to solve them. I already have several scripts installed (Token Mod, CharSetAttr, MetaScriptToolbox).


#1. Check if an attribute is greater than 0. If it is, I'd like to take some steps like adding an additional bonus to a roll, removing token markers, setting attribute changes elsewhere, using !deal to take or remove cards, setting the Attribute = Attribute -1, etc. If it's 0, I'd like nothing to happen.

#2. Check if a token has a specific marker. If it does, I'd like to do operations on the token and its sheet similar to the ones in #1 above. 

#3. Check if a token has a specific marker with a specific associated number. If it does, I'd like to be able to do things like set the attribute marker number N = N-1, clear the marker entirely if that ends up bringing it from 1 to 0, and take other actions.

Any of all of these being possible would be great, I can work with just one of them being possible if the others are not.


An example of a higher-level use case I am trying to accomplish:

#4. As part of a combat power macro, check if the triggering creature has advantage or disadvantage. I would be fine to check this either via markers or an attribute. If it has advantage (either as a marker or attribute), roll 2d20kh1, if it has disadvantage, roll 2d20kl1, if it has neither, roll 1d20. If it had Advantage/Disadvantage as a token marker with no associated number or the number = 1, delete the marker. If it did have a number >1, reduce the number by 1. If it had Advantage/Disadvantage as confirmed via a stored Attribute Value >0, set that value = N-1.


Are these all possible with my existing installed scripts? If not, are there any recommend scripts I can use/documentation to review?

Thank you!

October 05 (1 year ago)

Edited October 05 (1 year ago)

ScriptCards has the ability to provide conditional statements. It can be used standalone to a lot and can also call other scripts/mods like TokenMod and ChatSetAttr. It's a very robust macro building language to allow you to build what you want. I use it to check if a token has a specific status marker in many of my macros.

--~|array;statusmarkers;MarkerArray;@{selected|token_id}

that line there will fetch the statusmarkers and return them in a ScriptCard array to look through.

EDIT: Here is a Nick Olivo video where he builds a sample macro with ScriptCards

Here is the First ScriptCards post and the Currently open ScriptCards thread and a thread of examples with ScriptCards

EDIT2: Here is a quick thrown together ScriptCard to illustrate your first example. Obviously this a very quick and contrived example but it can hopefully illustrate what can be done

!scriptcard {{
    --#title|ScriptCard Example 1

    --/|Set a string variable for the token id
    --&TID|@{selected|token_id}

    --/|Use that variable to set a scriptcard setting for source token
    --#sourceToken|[&TID]

    --/|Use that source token to fetch other attributes like the character id
    --&CharID|[*S:character_id]

    --/|Check if an attribute is 0 and if so, have nothing happen
    --/|The default ScriptCard condition is like a GOTO to a section and sections start with a --:
    --?[*S:hp] -le 0|Done

    --/|Now we know that the hp attribute is greater than 0

    --/|Remove a token marker as an example with TokenMod
    --/|Calling other mods is --@ and those mods parameters have the -- replaced with underscores
    --@token-mod|_ids [&TID] _set statusmarkers|-dead

    --/|Setting attributes can be done with ScriptCards or with ChatSetAttr
    --/|In this case reduce an attribute named sanity by 1
    --@modattr|_charid [&CharID] _sanity|-1
    --!a:[&CharID]|sanity:-=1

    --/|Another super contrived example cause I don't know the !deal script at all
    --@deal|_dealflag1|value1 _dealflag2|value2

    --/|A section named Done where the ScriptCard will exit
    --:Done|
    --X|

}}
October 05 (1 year ago)
keithcurtis
Forum Champion
Marketplace Creator
API Scripter

APILogic by Timmaugh also allows for if/then statements. It's part of the metascripts suite.

October 05 (1 year ago)
timmaugh
Forum Champion
API Scripter

As Keith says, if you install the MetaScriptToolbox you will get all of the metascript toys, including APILogic, which will give you IF blocks (including nestable IF conditionals).

You'd also get Fetch, which allows you to pull information from most game objects (including the status markers from tokens).

The metascripts are set up to build your command line (or change the message object, in the background) before the message ever gets to a recipient script (or to the chat output)... so in that way, they really work with most other scripts to add that sort of IF/THEN, branching, or looping functionality.

Every one of your "it would be nice to be able to do... this... " examples are possible with metascripts. I don't have time at the moment to post examples, but I will try to remember to do that later.

October 06 (1 year ago)

Edited October 06 (1 year ago)


timmaugh said:

As Keith says, if you install the MetaScriptToolbox you will get all of the metascript toys, including APILogic, which will give you IF blocks (including nestable IF conditionals).

You'd also get Fetch, which allows you to pull information from most game objects (including the status markers from tokens).

The metascripts are set up to build your command line (or change the message object, in the background) before the message ever gets to a recipient script (or to the chat output)... so in that way, they really work with most other scripts to add that sort of IF/THEN, branching, or looping functionality.

Every one of your "it would be nice to be able to do... this... " examples are possible with metascripts. I don't have time at the moment to post examples, but I will try to remember to do that later.

Thank you for the help! If you do get a chance to post just a simple example I'd appreciate it -- I've tried putzing around with Fetch and APILogic by themselves but if I understand correctly they will not do anything if they are not included inside of a different !script? So I can't just use Fetch to force-display an attribute and nothing else by just simply putting something like "@(campaign.page_name)" in a macro with no other text or script being performed. I assume if I wanted to display an attribute as just text I'd need to use some other script to pull out and display that value, yeah? Similarly I can't just putz with APILogic by having a macro block only do a trivial logic check like "{& if a = a} true stuff {& else} default stuff {& end}", it would have to be passed as part of some other script to evaluate?

EDIT: Read through more of the wiki documentation specifically on ZeroFrame and I think I understand how to do this sort of testing (Using a leading ! and {@simple} tag). If you get time to share an example though it'd still be helpful for me to wrap my head around it!

October 06 (1 year ago)
timmaugh
Forum Champion
API Scripter


Marstead said:


EDIT: Read through more of the wiki documentation specifically on ZeroFrame and I think I understand how to do this sort of testing (Using a leading ! and {@simple} tag). If you get time to share an example though it'd still be helpful for me to wrap my head around it!


Yep, you've got it. All the metascripts work by changing the command line or the message object (where the data is, for scripts) before that message reaches its destination. So while the metascripts *COULD* listen for and attempt to modify a message that was headed straight for the chat panel... the message actually reaches the chat panel BEFORE the metascripts have a chance to change it (the message would hit in original form... then the metascripts would act... annnnnnnnnd... no one would see the alterations).

To get around that, we have to at least START the message as a bangsy message (beginning with a ! ). Then, if we want to output to chat, we use ZeroFrame's {&simple} tag to "redirect" the output from a mod script destination to the chat window, instead.

Here are some specific examples

Marstead said:

#1. Check if an attribute is greater than 0. If it is, I'd like to take some steps like adding an additional bonus to a roll, removing token markers, setting attribute changes elsewhere, using !deal to take or remove cards, setting the Attribute = Attribute -1, etc. If it's 0, I'd like nothing to happen.

Simple check syntax:

!{&if @{selected|hp} > 0}The creature is still standing, with @{selected|hp} hits.{&elseif @{selected|hp} = 0}The creature has 0 hp.{&else}The creature is dead{&end} {&simple}

Here is an example of using that sort of syntax to drive another script (or not, conditionally). This was a solution I helped someone with who had PMed me with a question. They wanted to enact a ChatSetAttr command to modify the hp_temp attribute only if the hp_temp attribute was 0. If hp_temp was something other than 0, they wanted to output a message announcing that the character couldn't gain temporary hp:

!{& if @{selected|hp_temp} = 0}setattr --sel --hp_temp|[[@{selected|level}*5]] {& else}Can't Gain Temp {&simple} {& end}

Note that the {&simple} is in the command, but it doesn't always activate. You wouldn't want it to activate if you were running the ChatSetAttr line... since you wouldn't want to redirect the message AWAY from a mod script destination. You only want it to run if the conditional check fails... so you include it within the ELSE block of text, so it only survives (and activates) for that portion of the conditional text.

If you want to use Fetch, you can replace the attribute calls -- like @{selected|hp} or @{selected|hp_temp} -- with a Fetch construction: @(selected.hp) or @(selected|hp_temp)

But if you're going to use Fetch it's probably to get at the information in a way that Roll20 doesn't natively offer. For instance, if you wanted to use the macro to check the hp of the token currently up in the Turn Tracker, you could replace the "selected" with "tracker" in a Fetch construction:

!{&if @(tracker.hp) > 0}The creature is still standing, with @(tracker.hp) hits.{&elseif @(tracker.hp) = 0}The creature has 0 hp.{&else}The creature is dead{&end} {&simple}

That allows you to check the character of the token currently up in the tracker without having to select it.

But, if you're going to check the Tracker, you might be working with some tokens that are just tokens... so let's look at getting token-specific properties...


Marstead said:

#2. Check if a token has a specific marker. If it does, I'd like to do operations on the token and its sheet similar to the ones in #1 above. 

Simple check:

!{&if @(selected.status.Bloodied.is) = yes}The token is bloodied.{&else}The token is not bloodied.{&end} {&simple}

Or, if the Bloodied status has numbers that mean something to you (for instance... blood loss per round), you can get the value like this:

!{&if @(selected.status.Bloodied.is) = yes && @(selected.status.Bloodied > 0}The token is bleeding at a rate of @(selected.status.Bloodied) hits per round.{&else}The token is not bleeding.{&end} {&simple}
You can see how, based on whether the creature was bleeding, you could take action with another script (like a ChatSetAttr line decrementing the hp of the creature). In that case, you'd want to move the {&simple} command the same way I demonstrated, above, so that it was paired with ONLY the chat-output ELSE case, and not the true side of the IF conditional... since that's where you'd put the ChatSetAttr line.

That's all I have time for at the moment, but hopefully it gives you a place to start. I'll try to work up the other 2 cases you mentioned in your OP later.




October 06 (1 year ago)

Thanks a ton @timmaugh this is more than enough to start with!