
ZeroFrame
FILE LOCATION: My Personal Repo & 1-click Installation
META SCRIPT: This script is a meta-script, and basis of the ZeroFrame Meta Toolbox. It can be used on its own, or in conjunction with the other meta-toolbox scripts, to modify other scripts' API commands.
ABSTRACT: ZeroFrame provides a way to organize, order, and loop over the other meta-scripts in the Meta Toolbox. It can unpack inline-rolls right in the command line, and lets you defer things like inline roll detection or the syntax token (the structures that would trigger the other meta-scripts) by escaping the text with a backslash.
Introduction
The ZeroFrame script is a framework for organizing the other meta-scripts. In effect, it is a single script registration in the order of script processing that lets you order and loop over the other meta-scripts. Since it uses the shin-kicking method of getting to the head of the script processing queue, it normally doesn't matter where/when you have this in the order of installed scripts*. Simply by having it in your arsenal of enabled scripts in your game will enable it to do what it needs to do no matter what other script you are calling.
* - the method of getting to the front of the script processing queue has been demonstrated to work with the vast majority of scripts, however if you find that ZeroFrame (or any other meta-script) does not properly intercept a message, remember that the most fool-proof way to make sure that one script processes before another is to have it installed in the script page of your campaign before the other script. In this rare case, some minor reordering may be required.
Syntax Highlights
Drop these syntax tokens into any API command to trigger the associated behavior. They will be filtered out (or replaced with the appropriate data) by the script.
!0 config => displays the ZeroFrame configuration (showing script priorities and handles) !0 sm|20 => sets the priority of SelectManager to 20 !0 logic|75 set|80 => multiple meta-scripts can be set in one statement (APILogic to 75, Muler Setting to 80) {& 0 get sm } => an inline tag for calls to another script changing the default loop order for this call (only), the order will be Muler Get, SelectManager, then the other scripts in default order .value => inline token to reduce an inline roll to its value (i.e., [[1d10]].value or $[[0]].value ) {& log} => inline tag to output the ZeroFrame log {& flat} => send the resulting message to the chat (no further API interaction), only detected after the loop finishes {& stop} => stops further processing (no chat, no API); only detected after the loop finishes
The Loop
ZeroFrame tracks the other meta-scripts that you have installed (those which register themselves to ZeroFrame), and loops over them until the scripts all report that they have nothing more to do with the message. At that point, the message is released, and the other scripts in your game can pick it up.
Script Priority and the Default Order
When you load another script in the Meta-Toolbox, it will register to ZeroFrame with a default priority value. Priority values are numbers, and operate in ascending order in the loop (so a priority 10 script will run before a priority 11, etc.). The scripts that are a part of the toolbox ship with a priority that places them in an order that should answer most needs, but you can change that order (either permanently, or for a given call).
To view the current loop order, run !0 config or !0 cfg from the chat. You will see something like the following (depending on the scripts you have installed and their relative priorities):
Setting Default Order (Permanent)
To change the order (permanently, so that all future calls will follow a new order), use an explicit call to ZeroFrame, setting the value for the priority of any script that requires it:
!0 sm|23 set|60
You can refer to the script by any of the shorthand references listed under the script name in the above config panel. For instance, you can affect APILogic by referring to apilogic, apil, or logic. Separate scripts by spaces, and separate the script from its intended priority with a pipe.
Setting Default Order (Temporary)
If you have a default order of the meta-scripts that answers most of your needs, you may still encounter a case where you have to operate under a different order for a given call. For those specific calls, ZeroFrame also gives you an inline tag to order the scripts. The tag will only affect the API command into which they are placed, and will not affect your default order.
{& 0 get sm}
The above would load Mules before SelectManager handled restoring selected tokens. The scripts that are included in the tag get hauled to the front of the loop order. Those scripts not mentioned are then added to the loop in their default order as it stands when the call is made.
DEFAULT ORDER : sm get fetch math eval set apil
INLINE TAG : {& math get sm }
ACTUAL TEMPORARY ORDER : math get sm fetch eval set apil
Setting Temporary Order and the Loop
ZeroFrame will look for the ordering tag at every pass of the loop, so if necessary you can fine-tune the loop order from one pass over the loop to the next. Note, if you do not change the loop order, it will remain whatever it was last set to (default or temporary).
Escaping Text (Deferred Processing)
You can use escape characters to break up text formations so that they do not process before you are ready. One level of escape characters is removed at each pass of the loop, so provided you build your command line properly, they are gone before the message is released to other scripts. The escape character can mask either Roll20 formations or inline meta-script tags.
For most text formations you can use the backslash ( \ ) character to escape the text.
For Inline rolls, use a single closing bracket after the escaping slashes for each opening bracket, and a simple backslash to escape closing brackets.
[\][\] [[1d10]]d10 \]\]
The above will roll 1d10 on the first pass, and then use that value as the number of d10 to roll on the second pass. This simple arrangement example can get much more complicated as you use other Meta Toolbox scripts in the same formation:
[\][\] {& math get.AttackMods.[[1d10]] * 2}d10 \]\]
There, the 1d10 is initially rolled, then the value is compared to a Mule called AttackMods (see the Muler script thread), then passed to a math operation where that is multiplied by 2 (see the MathOps thread), before finally being used as the number of d10 to roll in the second pass.
[\\][\\] ... \\]\\]
{\\& 0 get sm}
Inline Rolls
Getting an Inline Roll's Value
You can append .value to any roll or roll marker to have ZeroFrame extract the roll's value right in the line. This is the equivalent of substituting the value of the roll into that position in the command line.
!somescript --attackval|[[1d20+2]].value --altattack|$[[0]].value ...becomes...
!somescript --attackval|14 --altattack|14
Automatic Unpacking
Roll Availability
!somescript --roll1|[[1d10]] --roll2|[\][\]1d20\]\] --arg|$[[1]].value
!somescript --roll1|[[1d10]] --roll2|[\][\]1d20\]\] --arg|$[[1]]\.value ^ new escape character--^
Nesting Inline Rolls
ZeroFrame takes advantage of its loop to give you the ability to nest your reused inline rolls. For instance, we know that the first inline roll detected by the Roll20 parser can be reused in the command line by using the $[[0]] marker. However, using that marker nested inside another inline roll would break the Roll20 parser and throw an error:
[[ $[[0]]d10 ]]
(this breaks in a normal chat call!)
If ZeroFrame detects a nested inline roll, it will drop the marker out and substitute in the value of the roll. To make it work, you should escape the outer roll brackets as mentioned above:
[\][\] $[[0]]d10 \]\]
That way, by the time the Roll20 parsers see the outer roll structure, ZeroFrame will have replaced the inner roll marker with the value of the roll.
Nest multiple levels of inner rolls by using 1-more escape character for each outer wrapping of inline roll structure, as mentioned above in the section Escaping Text (Deferred Processing).
Post Processing - (Stop and Simple/Flat Tags)
Once the loop has completed, ZeroFrame looks for either the STOP or SIMPLE tags.
{& stop}
{& simple} or {& flat}
If detected, these tags trigger special behavior for the how the message is handled.
The STOP tag tells ZeroFrame not to release the message. In other words, nothing would reach the chat window, nor would it let other scripts receive the message. Conversely, the SIMPLE tag tells ZeroFrame to release the message only after it has converted it from an api-call (prepended with the !) into a simple chat message (and removing any SIMPLE tags it finds). This will output the resulting command line as a message to the chat window, but not allow other scripts to receive or take action based on the message. If you have APILogic installed, then embedding these tags within IF blocks give you a way to provide different results for different branches of your condition evaluation.
Messages output to chat by inclusion of the SIMPLE tag automatically format inline rolls as they would be were those rolls input directly to chat without ever having gone through the API. Use of the {&simple} tag is therefore a way to utilize syntax tokens of the meta-toolbox scripts (which only are invoked in an API message) in a normal chat message. In other words, provided you have access to the API, these meta-scripts expand the functional interface of the chat to even basic chat messages.
Logging
If you want to see how a command line changes throughout the loop process, include the {& log } token in your command line:
!somescript --arg1|[[1d10]].value {& log}
With that enabled, ZeroFrame will track how the command line changes as it is handed off to each script, for each pass of the loop. At the end, it will show you an output that lists those changes so you can see how pieces are resolved.
Each dot represents something different.
Orange => Loop Iteration
Blue => Nothing detected requiring attention, nothing changed
Green => Detected something to change, change was made successfully
Red => Detected something to change, but could not resolve that change on this pass of the loop
Unresolved Syntax and Stopping Endless Loops
If a meta-script can't resolve a token for which it is responsible, it will raise an 'unresolved' flag and leave the structure in place (for the most part). The loop will operate again to see if another meta-script might alter the command line in such a way that the token can be resolved. Because of this, we run the risk of infinite loops.
Certain Mule variable retrieval patterns can also cause infinite loops. If the result of a variable retrieval is, itself, a get.variable statement, which resolves into another get.variable, etc., the process runs the risk of never ending. Similarly, expanding inline rolls against tables which include the syntax to trigger another inline roll against the table, could create a series of inline roll resolutions that would never end.
ZeroFrame stops this by comparing the command lines at each pass of the loop to those that have come before to find duplicates. After a certain number of these identical command lines are detected, ZeroFrame ends it processing (leaving some syntax structures in place), and provides you the log screen so you can see what happened.