Script:SmartAoE
From Roll20 Wiki
Contents |
This page is a work in progress! Keep checking back for updates...
Concept
SmartAoE. Have you ever overlayed a cone, line, or circle template on a map and wondered if that square that is just barely covered should count as "in"? Sure, there are pre-made grid templates out there, but you are usually limited to 90/45deg orientations. The idea behind this script is to provide flexibility in casting angles (to align just the right spot before triggering) and a means for consistent ruling of these cases. Also, the script can detect creatures within affected squares and be able to roll saving throws and/or apply damage and condition markers automatically (ala GroupCheck or similar script).
Example of 4 active AoE's: 90deg cone (fixed radius, snapped to intersection), 5e-style cone (variable radius), line, and circle (using float keyword and custom multi-sided controlToken). The circle AoE is triggered (5e SRD Ice Storm spell), making saving throws for tokens in area, automatically deducting damage (--autoApply|true), and outputting results to chat.
Current functionality is to spawn a "control token" over a selected token. The location of the AoE is set by the positioning of the control token (and for lines/cones, the relative positions of the selected and control tokens). Depending on the commands used to spawn that control token, the script will associate those settings with that control token and act accordingly (a link between the selected and control tokens is made and stored in persistent memory). To determine whether a square is affected, you define a minimum grid coverage area in your macro. I'll use cones in the following discussion: For example, using --minGridArea|0.25
would require 25% of the grid square to be covered by the cone boundaries. You can choose to have the origin of the cone be in the default center of the origin (selected) token, or use the --origin|nearest
command to automatically shift the origin point to the nearest corner or face of the origin token. There are additional commands to rotate the origin point CW/CCW and to "trigger" the effect.
You can also define rules for the minimum percentage of a token's area that needs to be covered by an affected AoE grid square in order for the creature to be considered "in" the area of effect.
There are a variety of customization options for the AoE, including type (line, circle, cone, square - of which circle and square can be made independent of source token position), radius, AoE fill and line colors, saving throw formulas, difficulty class (target save number), up to two damage formulas & damage types, condition markers for pass/fail/dead, bar links, damage resistance/vulnerability/immunity (based on attribute content and damage type), and auto application of damage. These parameters and more are described below under #List of Subcommands.
Initial Setup
- Install the SmartAoE api script, currently found on GitHub here: v0.13
- Install the API script (available as 1-click install). SmartAoe is dependent on this utility script!
- Create a character sheet with the default token image you want for the AoE control token. If you do not specify a
--controlTokName
, then the script will look for the default token for a character namedAoEControlToken
. You can use a Multi-Sided Token, for which you may set the side and size via commands when spawned. - Create a macro utilizing the syntax described below. There are currently three different base commands:
Syntax Description !smartaoe <subcommands> this is the primary api syntax. Descriptions of commands is below, but they all follow the form --commandName|parameter(s)
!smartrotateorigin <cw/ccw> valid for cones only - this rotates the origin point cw or ccw along corners or faces of the origin token !smarttrigger currently no subcommands. Triggers the fx and does all the stuffs
It is recommended to create the following abilities on the AOEControlToken character and select "Show as token action". This will expedite the AoE manipulation and triggering process. |
Ability Name Ability Content CCW !smartrotateorigin ccw CW !smartrotateorigin cw Trigger !smarttrigger
List of Subcommands
AoE Behavior Commands
Command | Parameter(s) | Description | Default Value | Example(s) | Additional Notes |
---|---|---|---|---|---|
--radius | <###><optional units like ft. or "u"> | If a numeric value is specified, the AoE will have a constant radius regardless of the distance between the origin and control tokens. If "variable" (or omitted), the radius is dynamically determined by the relative spacing of the two tokens | variable | --radius|60ft --radius|12u |
If no units are given, will default to pixels! Behavior depends on "aoeType" keyword and "origin" type: For "nearest" origin, if "float" keyword is omitted, the origin token's square is omitted from the radius (making it bigger). Otherwise, float will result in a true radius. |
--aoetype | <type>,<optional coneWidth>,<optional "float"> | currently supports "line", "square", "circle", "cone", and "5econe" | line | --aoetype|5econe --aoetype|cone, 90 --aoetype|circle, float --aoetype|line |
The "float" keyword "untethers" the AoE from the sourceToken, creating the AoE around the controlToken only (e.g. a Fireball spell) NOTE: default is "line" if this subcommand is omitted |
--origin | <style> <optional "face"> | AoE starts in center or edge of square (ignored for line AoE’s) | center | --origin|nearest --origin|nearest, face --origin|center |
"Center" (or omitted) will pick the center of the origin token for the AoE origin. "Nearest" will pick the closest corner. "Nearest, face" will include the flat sides of the token's square as potential origin points. |
--forceIntersection | <true/yes/1/false/no/0> | forces the dragged controlToken center to the intersection of grid squares | false | --forceIntersection|0 | I'd recommend setting to true for PF-style cone approximations. Otherwise, if set to false (or omitted), you can always press Alt while positioning the controlToken for fine tuning of the AoE placement. NOTE: This command is ignored and automatically set to true if a "float" style circle or square AoE is used |
--mingridarea | <#> | what percentage of the grid square’s area must lie within the AoE to be included in the final affected area | 0.01 | --mingridarea|0.1 | The example to the left would require only 10% of the grid to be covered by the AoE to be included. For 5e cones, I'd recommend a good place to start would be 25%. For PF cone approximations, I'd go with 50% along with --forceIntersection|1. More than 50% might start making cones not "emanate" fully from the source token |
--mintokarea | <#> | what percentage of the token’s area must lie within the AoE to be included as an affected creature | 0.01 | --mintokarea|0.25 | The example to the left would require only 25% of the token's area to be covered by affected squares for them to be in the area of effect. |
--fx | <style>-<type> | will spawn fx in affected squares when triggered | --- | --fx|burn-death --fx|glow-holy |
fx will spawn at each affected square |
--aoecolor | <#RRGGBBTT> | determines the fill color of the AoE’s affected squares | #ff000050 | --aoeColor|#ff000050 | NOTE: default is #ff000050 if this subcommand is omitted |
--aoeOutlineColor | <#RRGGBB> | determines the line color of the AoE outline | #ff0000 | --aoeColor|#ff000050 | NOTE: default is #ff0000 if this subcommand is omitted |
--controlTokName | <charName> | The name of the character sheet whose default token will be used as the AoE control token | AoEControlToken | --controlTokName|GenericSpellAoE | It is generally best if the default token image is a png file with partial transparency to allow the affected grid squares and tokens to be visible. NOTE: default is "AoEControlToken" if this subcommand is omitted |
--controlTokSize | <#> | The size (in squares) of the control token | 1 | --controlTokSize|8 | NOTE: default is 1 if this subcommand is omitted |
--controlTokSide | <#> | For rollable table tokens: the side of the control token's image to be set when created | 1 | --controlTokSide|6 | NOTE: default is 1 if this subcommand is omitted |
--isDrawing | <true/yes/1/false/no/0> | Sets the isdrawing property of the spawned control token | FALSE | --isDrawing|true | NOTE: default is false if this subcommand is omitted |
--ignore | <attrName, attrValue> | Characters with matching attribute values will not be included in the chat output | --- | --ignore|SmartAoE_Ignore, 1 | NOTE: must have both the attrName and attrValue separated by a comma |
--selectedID | <token_id or character_id> | allows direct selection of the source token | --- | --selectedid|-MlBqIRAtRSwAZ-8Jr_E | |
--playerID | <player_id> | The name of the calling player. Useful when calling from another API script. Tells the script which playerID can control the control token (if not set by default in character sheet). Also for error msg whispers when called by another script. | --- | --playerid|-MlBqIRAtRSwAZ-8Jr_E |
AoE Math Commands
Command | Parameter(s) | Description | Default Value | Example(s) | Additional Notes |
---|---|---|---|---|---|
--dc | <value or inline roll> | the target roll for each saving throw (>= is passing, < is failing) | 0 | --dc|{selected|spell_save_dc} --dc|[[5d6+2]] |
|
--saveformula | <inline roll with special syntax (see notes)> | Formula to be used for saving throws for all affected tokens. | --- | --saveFormula|<<1d20 + a{dexterity_save_bonus}>> --saveFormula|5eDEX |
In order to delay the save rolls until the AOE is triggered, and to apply that formula to each token individually, replace inline roll format in the following way:
NOTE: for 5e games, you can use the shorthand "5eSTR", "5eDEX", "5eCON", "5eINT", "5eWIS","5eCHA" |
--damageformula1 | <inline roll> | Formula to be used for damage1 | --- | --damageformula1|[[8d6]] --damageformula1|[[(5+?{Cast at what level? |3,3|4,4|5,5|6,6|7,7|8,8|9,9})d6]] |
|
--damagetype1 | <text> | the damage type for damage1 | --- | --damageType1|Fire | |
--damageformula2 | <inline roll> | Formula to be used for damage2 | --- | --damageformula1|[[8d6]] --damageformula1|[[(5+?{Cast at what level? |3,3|4,4|5,5|6,6|7,7|8,8|9,9})d6]] |
|
--damagetype2 | <text> | the damage type for damage2 | --- | --damageType1|Fire | |
--bar | <#> | which token bubble to apply damage. Default = 1 | 1 | --bar|1 | |
--autoapply | <true/yes/1/false/no/0> | Toggle to apply damage and condition markers automatically or after subsequent interaction with chat output. | FALSE | --autoApply|1 | Confirmation of the applied damage will be posted to chat. Tokens on GM layer will have whispered confirmation. NOTE: default is false if this subcommand is omitted. |
--conditionfail | <name(s) of status markers to apply on a failed save> | comma delimited | --- | --conditionFail|red --conditionFail|red@3 --conditionFail|skull,cobweb |
NOTE: if custom markers are used, you must include the whole id, e.g. "name::####" NOTE:inserting @# will overlay a number over the condition marker |
--conditionpass | <name(s) of status markers to apply on a successful save> | comma delimited | --- | --conditionPass|Target::1510119 --conditionPass|green@3 --conditionPass|aura,bolt-shield |
NOTE: if custom markers are used, you must include the whole id, e.g. "name::####" |
--zerohpmarker | <name(s) of status markers to apply if designated token bar is 0 after damage is applied> | comma delimited | --- | --zerohpmarker|dead | NOTE: if custom markers are used, you must include the whole id, e.g. name::#### |
--resistAttr | <attrName> | If the damageType(s) string is included in the current value of the deNOTEd attribute, then the --resistanceRule will be applied | npc_resistances | --resistAttr|npc_resistances | NOTE: default is npc_resistances if this subcommand is omitted |
--vulnerableAttr | <attrName> | If the damageType(s) string is included in the current value of the deNOTEd attribute, then the --vulnerableRule will be applied | npc_vulnerabilities | --resistAttr|npc_vulnerabilities | NOTE: default is npc_vulnerabilities if this subcommand is omitted |
--immunityAttr | <attrName> | If the damageType(s) string is included in the current value of the deNOTEd attribute, then the --immunityRule will be applied | npc_immunities | --resistAttr|npc_immunities | NOTE: default is npc_immunities if this subcommand is omitted |
--resistanceRule | <expression> | The math operation (accepts single Operator and Operand) to be applied if target is resistant to damageType(s) | *0.5 | --resistanceRule|*0.5 --resistanceRule|/2 --resistanceRule|-10 |
NOTE: default is "*0.5" if this subcommand is omitted |
--vulnerableRule | <expression> | The math operation (accepts single Operator and Operand) to be applied if target is vulnerable to damageType(s) | *2 | --vulnerableRule|*2 --vulnerableRule|+10 |
NOTE: default is "*2" if this subcommand is omitted |
--immunityRule | <expression> | The math operation (accepts single Operator and Operand) to be applied if target is immune to damageType(s) | *0 | --immunityRule|*0 | NOTE: default is *0 if this subcommand is omitted |
Chat Output Style Commands
Command | Parameter(s) | Description | Default Value | Example(s) | Additional Notes |
---|---|---|---|---|---|
--title | <text> | the title of the chat output table | SmartAoE | --title|Burning Hands | NOTE: all chat output options will revert to default values if omitted from the macro |
--leftsub | <text> | subtitle of the chat output table. If rightsub is included, they will be separated by a diamond icon | --- | --leftsub|some text --leftsub|Slot level ?{Cast at what level?|3,3|4,4|5,5|6,6|7,7|8,8|9,9} |
" " |
--rightsub | <text> | subtitle of the chat output table. If leftsub is included, they will be separated by a diamond icon | --- | --rightsub|some text --rightsub|DC @{selected|spell_save_dc} DEX |
" " |
--desc | <text> | optional description at bottom of chat output table | --- | --desc| Line 1 of the description%br%Line 2 of the description | " " |
--hideNames | <true/yes/1/false/no/0> | If true, the token names will be replaced with Target_# | FALSE | --hidenames|1 | " " |
--titlecardbackground | <html> | Value to set the html "background-image:" property of the title field of the chat output | linear-gradient(red, yellow) | --titlecardbackground|linear-gradient(#995522, blue) --titlecardbackground|url('https://s3.amazonaws.com/files.d20.io/images/ 248538196/c9xft1A2jWNqOkBsxQwyLQ/max.jpg?1633278017');background-size: contain; |
" " |
--titlefontface | <fontName> | Font style of the chat output title | Contrail One | --titlefontface|Contrail One | " " |
--titlefontcolor | <#RRGGBB> | Font color of the chat output title | #EEEEEE | --titlefontcolor|#EEEEEE --titlefontcolor|red |
" " |
--titlefontsize | <html size> | Font size of the chat output title | 1.2em | --titlefontsize|1.2em --titlefontsize|18px |
" " |
--titlefontlineheight | <html size> | line-height of the chat output title | 1.2em | --titlefontlineheight|1.2em --titlefontlineheight|18px |
" " |
--titlecardbottomborder | <html> | Html border of the table title | 2px solid #444444; | --titlecardbottomborder|2px solid #444444 | " " |
--subtitlefontface | <fontName> | Font style of the chat output subtitle | Tahoma | --subtitlefontface|Tahoma | " " |
--subtitlefontcolor | <#RRGGBB> | Font color of the chat output subtitle | #333333 | --subtitlefontcolor|#333333 | " " |
--subtitlefontsize | <html size> | Font size of the chat output subtitle | 13px | --subtitlefontsize|13px | " " |
--bodyfontface | <fontName> | Font style of the chat output body | Helvetica | --bodyfontface|Helvetica | " " |
--bodyfontsize | <html size> | Font size of the chat output body | 14px | --bodyfontsize|14px | " " |
--tablebgcolor | <#RRGGBB> | Background color of the damage and description fields | #EEEEEE | --tablebgcolor|#EEEEEE | " " |
--tableborder | <html> | Html border of the table | 2px solid #000000; | --tableborder|2px solid #000000; | " " |
--tableborderradius | <html> | Html border radius of the table | 6px; | --tableborderradius|6px; | " " |
--tableshadow | <html> | Html shadow of the table | 5px 3px 3px 0px #aaa; | --tableshadow|5px 3px 3px 0px #aaa; | " " |
--evenrowbackground | <#RRGGBB> | Background color of the even rows of the Save fields | #DDDDDD | --evenrowbackground|#DDDDDD | " " |
--oddrowbackground | <#RRGGBB> | Background color of the odd rows of the Save fields | #FFFFFF | --oddrowbackground|#FFFFFF | " " |
--evenrowfontcolor | <#RRGGBB> | Font color of the even rows of the Save fields | #000000 | --evenrowfontcolor|#000000 | " " |
--oddrowfontcolor | <#RRGGBB> | Font color of the odd rows of the Save fields | #000000 | --oddrowfontcolor|#000000 | " " |
Chat Output Cheat Sheet
The following describes the various regions and features of the chat output, along with labels for which #Chat Output Style Commands are relevant to which regions
Example SmartAoE Macros
Simple 20ft cube
This macro has bare-bones functionality. It just spawns a 20ft cube, using the float keyword to disconnect it from the sourceToken. Note that since the "float" keyword was used, the script automatically snaps the controlToken to the grid intersections.
!smartaoe {{ --aoeType|square, float --radius|10ft }}
Simple variable cube
This macro has bare-bones functionality. It just creates a square AoE linked to the sourceToken and creates burn-fire fx on trigger. Radius is variable based on relative positions of source & control tokens.
!smartaoe {{ --aoeType|square --fx|burn-fire }}
PF-style 30ft cone approximation
Attempt at getting close to PF-style cone rules. Forced controlToken to grid intersection, only allowed token corners for origin point, and required 50% of grid area coverage required (--minGridArea|0.5). Any more than 50% will start to omit the squares closest to the sourceToken. This is as close as I could get to PF rules, although there are some extra squares counted. The PF ruleset does not appear to weigh percentage of grid area evenly.
!smartaoe {{ --aoeType|cone, 90 --radius|30ft --minGridArea|0.50 --origin|nearest --forceIntersection|1 }}
5e Burning Hands
This macro creates a 15ft 5e-style cone using the default AoEControlToken character for the controlToken, allows token faces to be the point of origin, triggers fire fx, rolls 5e DEX saves (ignoring tokens with a "1" in a custom attribute called "SmartAOE_ignore", and auto applies damage to the tokens after saves are made. Also, green/red condition markers for pass/fail are applied, and tokens having 0 in their bar1 field will gain the "dead" condition marker.
!smartaoe {{ --title|Burning Hands --leftsub|Slot level ?{Cast at what level?|1,1|2,2|3,3|4,4|5,5|6,6|7,7|8,8|9,9} --rightsub|DC @{selected|spell_save_dc} DEX --aoeType|5econe --forceIntersection|0 --radius|15ft --origin|nearest, face --minGridArea|0.25 --minTokArea|0.25 --fx|burn-fire --dc|@{selected|spell_save_dc} --saveFormula|5eDEX --damageFormula1|[[(?{Cast at what level?}+2)d6]] --damageType1|Fire --ignore|SmartAOE_ignore,1 --autoApply|1 --bar|1 --conditionFail|red --conditionPass|green --zeroHPmarker|dead --desc|As you hold your hands with thumbs touching and fingers spread, a thin sheet of flames shoots forth from your outstretched fingertips. Each creature in a 15-foot cone must make a Dexterity saving throw. A creature takes 3d6 fire damage on a failed save, or half as much damage on a successful one.%br%%br%The fire ignites any flammable objects in the area that aren't being worn or carried. }}
5e Ice Storm
This macro creates a 20ft radius "floating" circle using a custom multi-sided token from a character called "GenericSpellAoE" for the controlToken, triggers ice fx, rolls 5e DEX saves (ignoring tokens with a "1" in a custom attribute called "SmartAOE_ignore", and delays damage application to the tokens until the P/F icons are clicked in the chat output. There are two damage types for this spell. Also, tokens having 0 in their bar1 field after damage is applied from this click event will gain the "dead" condition marker. There are also several changes to the formatting of the chat output from the default.!smartaoe {{ --title|Ice Storm --leftsub|Slot level ?{Cast at what level?|4,4|5,5|6,6|7,7|8,8|9,9} --rightsub|DC @{selected|spell_save_dc} DEX --titlecardbackground|linear-gradient(blue, cyan) --oddrowbackground|#00ccff --evenrowbackground|#edfcfc --oddrowfontcolor|#000000 --tablebgcolor|#edfcfc --controlTokName|GenericSpellAoE --controlTokSize|8 --controlTokSide|14 --aoeColor|#00ccff50 --aoeOutlineColor|#0099ff --aoeType|circle, float --radius|20ft --minGridArea|0.25 --minTokArea|0.25 --fx|burn-frost --dc|@{selected|spell_save_dc} --saveFormula|5eDEX --damageFormula1|[[(?{Cast at what level?}-2)d8]] --damageType1|Bludgeon --damageFormula2|[[4d6]] --damageType2|Cold --ignore|SmartAoE_Ignore,1 --autoApply|0 --bar|1 --zeroHPmarker|dead --desc|A hail of rock-hard ice pounds to the ground in a 20-foot-radius, 40-foot-high cylinder centered on a point within range. Each creature in the cylinder must make a Dexterity saving throw. A creature takes 2d8 bludgeoning damage and 4d6 cold damage on a failed save, or half as much damage on a successful one.%br%%br%Hailstones turn the storm's area of effect into difficult terrain until the end of your next turn. }}