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 .
×
Advertisement Create a free account

[Meta Script] ZeroFrame - one script to control them all

1618936876

Edited 1619014793
timmaugh
Pro
API Scripter
ZeroFrame FILE LOCATION:   My Personal Repo (until one-click submission) 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. Remember, one level of escaping is removed at the end of each pass of the loop, so something requiring deferral until the second pass of the loop would have two escape characters. For an inline roll, that would look like: [\\][\\] ... \\]\\] ...and for a normal text structure (for instance, setting the order of the loop for a particular pass), it might look like this: {\\& 0 get sm} Note that there must be at least one indication that the loop should continue in order for a further loop pass to be initiated and a further level of escape characters to be removed. This is generally accomplished by having some modification to the command line (via one of the registered meta-scripts), or by the detection of an inline roll after the escape characters have been removed at the end of the loop pass. (The loop runs until it finds, in a single pass, no changes from any of the registered scripts  and  no new inline rolls detected after unescaping the line.) 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 Typically, you only need to do this in a situation where the roll will not be unpacked automatically. Automatic unpacking happens for nested inline rolls (see below), for rolls that are output to a simple/flat chat message (see below), as well as in certain meta-script constructions (in an APILogic IF condition, or a MathOps tag, for example). Also, it's good to remember that if you are sending a macro or command line to the API that is intended for another script, there is a good chance that other script knows what it wants to do with inline rolls, already, so if you don't need to actually use the value of the roll, you could just leave it in the command line. Roll Availability The Roll20 parsers detect inline rolls, process them, and leave behind roll markers in the command line (things like $[[0]]). This happens before each pass of the ZeroFrame loop. Also with each pass of the loop, ZeroFrame evaluates the  .value  token to look for places where you want to unpack a roll. If a roll is not available at the time that the  .value  token is detected, the unpacking returns a 0. For instance, the following will not properly use the result of the $[[1]] roll: !somescript --roll1|[[1d10]] --roll2|[\][\]1d20\]\] --arg|$[[1]].value At the time that ZeroFrame attempts to extract the value of the $[[1]] roll (on the first pass of the loop), it doesn't yet exist. The $[[1]] roll (the second roll in the command line), was deferred with escape characters, and doesn't exist until the second pass of the ZeroFrame loop. To make sure that the roll is available, use the appropriate number of escape characters to mask the  .value  token until the roll is available: !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.
1618936885

Edited 1619014318
timmaugh
Pro
API Scripter
Updates and Releases v1.0.1 - Fixed bug where line breaks were being removed and not restored by ZeroFrame
1618936908
timmaugh
Pro
API Scripter
Advanced Usage and Tricks
1618986905

Edited 1618987772
I noticed while testing these scripts out that line breaks were getting stripped from templates used with the SendText and Universal Chat Menu scripts. Disabling ZeroFrame fixed it, so something about the way it passes API calls to chat is messing up line breaks in the text. Here's a short example macro, for context: !sendtext {{}} {{charactername=@{selected|token_name}}} {{header=ID}} {{desc=**CHARACTER:** ``@{selected|character_id}`` **TOKEN:** ``@{selected|token_id}``}} Hope there's a workaround  for this!
Right. I'm coming back to Roll20 just to DM a ZeroFrame campaign. Is Apilogic the end boss, or do you have another one planned?
1619014256
timmaugh
Pro
API Scripter
I was unaware that some scripts might require the line-breaks to function properly. I have corrected ZeroFrame to properly restore the line breaks in v1.0.1, so give that a run and see if it works (it was good in my testing). And, Oosh, that's really cool to hear. As far as end-bosses go, I would nominate ZeroFrame for the position. Not sure there will be other scripts in the Meta Toolbox, but there could be if we found another way people might want to modify their command lines in real time. =D
1619014423

Edited 1619708297
timmaugh
Pro
API Scripter
Version 1.0.1 April 21, 2021 FIXED : Minor bug where line breaks were being removed by ZeroFrame but not restored before the message was released to other scripts.
timmaugh, I'm getting a consistent crash when using a specific macro that I use frequently. The crash only happens when I run the macro while ZeroFrame is enabled. Here's the crash report: TypeError: Cannot read property 'returns' of undefined at apiscript.js:40908:79 at Array.map (<anonymous>) at parseInlineRolls (apiscript.js:40879:28) at Object.getRollData (apiscript.js:40944:19) at runLoop (apiscript.js:48284:87) at handleInput (apiscript.js:48449:13) at eval (eval at <anonymous> (/home/node/d20-api-server/api.js:154:1), <anonymous>:65:16) at Object.publish (eval at <anonymous> (/home/node/d20-api-server/api.js:154:1), <anonymous>:70:8) at /home/node/d20-api-server/api.js:1663:12 at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560 Here's the macro: !chatmenu @{selected|character_id} {template:rolls} {{charactername=@{selected|token_name}}} {{header=@{selected|npc_type} @{selected|level}}} {{subheader=@{selected|alignment} | @{selected|size} | @{selected|traits}}} {{info01_name=Languages}} {{info01=@{selected|languages}}} {{info02_name=AC🛡️}} {{info02=**@{selected|armor_class}**; @{selected|armor_class_notes}}} {{info03_name=HP❤️}} {{info03=**@{selected|bar1}**/@{selected|hit_points|max}; @{selected|hit_points_notes}}} {{info04_name=Immunities}} {{info04=@{selected|immunities}}} {{info05_name=Weaknesses}} {{info05=@{selected|weaknesses}}} {{info06_name=Resistances}} {{info06=@{selected|resistances}}} {{info07_name=Speed}} {{info07=@{selected|speed}; @{selected|speed_notes}}} {{info08_name=Recall🆔 DC}} {{info08=@{selected|npc_short_description}}} {{desc=CHATMENU}} --title:Senses | [Initiative](`#NPCINIT) --Perception @{selected|perception}; @{selected|perception_notes}; @{selected|senses},PERCEPTION,perception --title:Skills🛠️ --Acrobatics @{selected|acrobatics}; @{selected|acrobatics_notes},ACROBATICS,acrobatics|Arcana @{selected|arcana}; @{selected|arcana_notes},ARCANA,arcana|Athletics @{selected|athletics}; @{selected|athletics_notes},ATHLETICS,athletics|Crafting @{selected|crafting}; @{selected|crafting_notes},CRAFTING,crafting|Deception @{selected|deception}; @{selected|deception_notes},DECEPTION,deception|Diplomacy @{selected|diplomacy}; @{selected|diplomacy_notes},DIPLOMACY,diplomacy|Intimidation @{selected|intimidation}; @{selected|intimidation_notes},INTIMIDATION,intimidation|Medicine @{selected|medicine}; @{selected|medicine_notes},MEDICINE,medicine|Nature @{selected|nature}; @{selected|nature_notes},NATURE,nature|Occultism @{selected|occultism}; @{selected|occultism_notes},OCCULTISM,occultism|Performance @{selected|performance}; @{selected|performance_notes},PERFORMANCE,performance|Religion @{selected|religion}; @{selected|religion_notes},RELIGION,religion|Society @{selected|society}; @{selected|society_notes},SOCIETY,society|Stealth @{selected|stealth}; @{selected|stealth_notes},STEALTH,stealth|Survival @{selected|survival}; @{selected|survival_notes},SURVIVAL,survival|Thievery @{selected|thievery}; @{selected|thievery_notes},THIEVERY,thievery --title:Lore --repeating_lore|lore_name|LORE|lore --title:Ability Checks --STR @{selected|strength_modifier},STR,strength_modifier!—|STR @{selected|strength_modifier},STR,strength_modifier=0|DEX @{selected|dexterity_modifier},DEX,dexterity_modifier!—|DEX @{selected|dexterity_modifier},DEX,dexterity_modifier=0|CON @{selected|constitution_modifier},CON,constitution_modifier!—|CON @{selected|constitution_modifier},CON,constitution_modifier=0|INT @{selected|intelligence_modifier},INT,intelligence_modifier!—|INT @{selected|intelligence_modifier},INT,intelligence_modifier=0|WIS @{selected|wisdom_modifier},WIS,wisdom_modifier!—|WIS @{selected|wisdom_modifier},WIS,wisdom_modifier=0|CHA @{selected|charisma_modifier},CHA,charisma_modifier!—|CHA @{selected|charisma_modifier},CHA,charisma_modifier=0 --title:Interaction Abilities --repeating_interaction-abilities|name|action-npc --title:Saving Throws --Fort @{selected|saving_throws_fortitude},FORT|Ref @{selected|saving_throws_reflex},REF|Will @{selected|saving_throws_will},WILL --title:Automatic and Reactive Abilities --repeating_free-actions-reactions|name|action-npc --title:Melee Strikes⚔️ --repeating_melee-strikes|weapon|ATTACK-DAMAGE-NPC --title:⚔️Second --repeating_melee-strikes|weapon|ATTACK-DAMAGE-NPC2 --title:️⚔️Subsequent --repeating_melee-strikes|weapon|ATTACK-DAMAGE-NPC3 --title:Ranged Strikes🏹 --repeating_ranged-strikes|weapon|ATTACK-DAMAGE-NPC --title:🏹Second --repeating_ranged-strikes|weapon|ATTACK-DAMAGE-NPC2 --title:🏹Subsequent --repeating_ranged-strikes|weapon|ATTACK-DAMAGE-NPC3 --title:Offensive or Proactive Abilities --repeating_actions-activities|name|action-npc --title:Items🎒 --repeating_items-worn|worn_item|item-npc --title:Innate Spells --repeating_spellinnate|name|npcspellroll|frequency!constant --title:Constant --repeating_spellinnate|name|npcspellroll|frequency=constant --title:Focus Spells (@{selected|focus_points}/@{selected|focus_points|max}) --repeating_spellfocus|name|npcspellroll --title:Cantrips --repeating_cantrip|name|npcspellroll --title:1st-level (@{selected|level_1_per_day|max}/day) --repeating_spell1|name|npcspellroll --title:2nd-level (@{selected|level_2_per_day|max}/day) --repeating_spell2|name|npcspellroll --title:3rd-level (@{selected|level_3_per_day|max}/day) --repeating_spell3|name|npcspellroll --title:4th-level (@{selected|level_4_per_day|max}/day) --repeating_spell4|name|npcspellroll --title:5th-level (@{selected|level_5_per_day|max}/day) --repeating_spell5|name|npcspellroll --title:6th-level (@{selected|level_6_per_day|max}/day) --repeating_spell6|name|npcspellroll --title:7th-level (@{selected|level_7_per_day|max}/day) --repeating_spell7|name|npcspellroll --title:8th-level (@{selected|level_8_per_day|max}/day) --repeating_spell8|name|npcspellroll --title:9th-level (@{selected|level_9_per_day|max}/day) --repeating_spell9|name|npcspellroll --title:10th-level (@{selected|level_10_per_day|max}/day) --repeating_spell10|name|npcspellroll --separator: | : I have several other macros that use this script command and none of them cause the crash. I've tried deleting different sections of the macro but no specific section seems to be causing the issue; instead I think it's just because it's so long. After deleting about three quarters of the macro, no matter which sections, it goes through without a crash.
1619275811
timmaugh
Pro
API Scripter
It looks like it isn't finding inline rolls when it thinks it should see them. Let me dig into this and see what I can find.
1619448587
timmaugh
Pro
API Scripter
Found it. This was a bug in the libInline library script that ZeroFrame uses to parse the inline rolls. I had encountered (and fixed) this error as a part of the Meta Toolbox development, but failed to push it to the one-click or my personal repository. I have now pushed it to my personal repo and submitted it to this week's one-click merge, so it should be distributed soon. My apologies. I will update the libInline thread for the new release.
1619458725

Edited 1619458740
Would this solve the problem I was having?
1619460521
timmaugh
Pro
API Scripter
It's worth a try... but I think your problem will take ZeroFrame detecting a particular construction and working around it (buffering it to not let Roll20 parsers see/error on it). I haven't had a chance to test your specific macro, yet, but that's next for me. =D
1619708590
timmaugh
Pro
API Scripter
Version 1.0.2 April 29, 2021 FIXED : ZeroFrame will now detect line breaks at every pass of the loop. Update Notes This update addresses a potential problem where new text could be inserted into the command line, and that new text could contain line-breaks. This could happen from the resolution of a Muled variable, or newly detected text structure based on modifying the command line, etc. Whatever the reason, ZeroFrame will now search for and handle line breaks to appropriately handle the message as it stands for that pass of the loop.
1620097289

Edited 1620412919
timmaugh
Pro
API Scripter
Version 1.0.3 Released May 3, 2021 FIXED/ADDED : Multiple exclamation points are by default reduced to a single exclamation point FIXED : SIMPLE and FLAT tags now drop the message to a simple chat message (no API) no matter how many exclamation points start the message ADDED : ZeroFrame config box priority values are now clickable and link to syntax to reset the priority of that script Update Notes Single Bang Through processes such as retrieving text from an ability or macro, or parsing different logical paths, etc., you might arrive at a position where your command line has more than one exclamation point (or "bang") beginning it. For instance, if you have a macro that reads: !token-mod --set name|Tacos ...and you retrieve that macro into your command line: !#(TacoMacro) ...then the net effect will be that the command line will have 2 bangs (exclamation points): !!token-mod --set name|Tacos When that message is released, it would not be picked up by token-mod since the construction of the opening handle is wrong. As of this update, ZeroFrame will reduce those multiple-bangs down to a single bang. SIMPLE and FLAT On a related note, no matter how many opening-bangs remain when ZeroFrame encounters a {& simple} or {& flat} tag, ZeroFrame will bypass them all and release the message as a simple chat message. !!!!!!!!!!!!!!This will become normal text.{&simple} ...outputs a basic message of: This will become normal text. Clickable Config Screen You can pull the ZeroFrame config screen up by entering the following into chat: !0 config That will bring up the config screen as pictured in the original post. As of this update, the numbers in that config screen are now clickable to let you reset the priority of the script in question. Clicking on the 20 next to SelectManager will ask you what new value you wish to enter for the SelectManager meta script. These changes to a script's priority become the default priority for that script for future calls (until it is changed again or unless it is overridden for a particular call).
1620417638
timmaugh
Pro
API Scripter
Version 1.0.5 Released May 7, 2021 FIXED : Bug where roll templates were not restored before releasing the message ADDED : Better logging output (including the final release message) ADDED : New syntax token for late specification of a roll template: {& template:...} Update Notes Roll Templates I had not realized that roll templates had been neglected and/or mishandled by ZeroFrame. Thanks to Scott for pointing that out. Now, roll templates will survive through the ZF loop. Three possible paths for the default behavior: 1) You intended to target a script with the roll template Nothing is required; this is standard behavior for ZeroFrame to make this option work. (Roll20 strips off the roll template declaration but passes the component parts.) 2) You intended to actually utilize the roll template (no script) Use {&simple} or {&flat} in your message to drop out of the api into a standard chat message. The roll template will be restored. For instance, if you wanted to take the line: &{template:default}{{name=Hooligans}}{{Seagulls=Stop it now.}} But determine information at the time the command is sent, you might want to invoke ZeroFrame by prepending this with an exclamation point, then using whatever meta-structures you need in order to retrieve your data. Here is an option using Fetch constructions... to make this work, we add the exclamation point, the Fetch constructions, and the {&simple} tag: !&{template:default}{{name=Hooligans}}{{@(selected.token_name)=@(selected.gmnotes)}}{&simple} 3) You want to late-designate the template If you wanted to delay the detection of the roll template (for instance, to differentiate what template to use based on some meta operation or input from the user), then you can use the {& template: ... }  tag. If detected, the contents of the template's designation will be passed to the final message that hits chat. For instance, to choose between 2 known templates, you could offer a roll template: !{& template:?{What template?|default|attack} }{{name=Hooligans}}{{Seagulls=Stop it now}}{&simple} That will prompt you to choose what template to apply. In most use-cases, you'd want other configurations of the command based on other meta-operations, since the data you might want to put into two different templates might be very different. Better Logging Logging output (triggered by including the {&log} tag somewhere in your command line) now includes more expansive notes as well as the final output command line released by ZeroFrame.