Kurt J. said: Here is my implementation of Burning Hands. Much of the Lightning Bolt code is reused, the difference being that there is no line calculation but instead the definition of arrays for each of the grid directions. These arrays were taken from the templates in Xanathars for cone spells on a grid. This could easily be updated for 30' cones by simply adding more entries to each array. It would also be a simple matter to update the arrays to handle cube spells like Thunderwave. The numbers in the array are x and y offset pairs for each impacted square, assuming the caster is at 0,0 compared to these values. I have emojis for each of the directional arrows in the dropdown, though they can be hard to see on big displays, so I also include the direction name. Anyway, while I've run it several times there could always be bugs, so let me know if you run into anything. (I need to check the damage numbers - they look off to me, but I'll look at them). Found a bug in the saving throw roll on both this and Lightning Bolt. Updated. !script {{
--/|Burning Hands script. Can be changed to other 15' cone-based spells by updating these parameters.
--/|larger cones can be defined by updating the array definitions for the diretions to include additional offsets.
--/|cube shaped spells could be acocmodated in a similar way.
--&spellName|Burning Hands
--/|Note: because the spell will be cast at a min level of 1, we use 2 here to get the total dice (2+1=3)
--&spellL0DamageDice|2
--/|Prompt for the spell level. Update this to account for the minimum level of the spell
--=SpellLevel|?{Spell Slot Level?|1|2|3|4|5|6|7|8|9}
--&spellDamageDieType|6
--&damageType|fire
--&saveType|dexterity
--/|Source Token is the caster, and target token is the "end of the line". Can be a non-creature (no represents) token.
--#sourcetoken|@{selected|token_id}
--/|Get all of the tokens on the page so we can cache their positions
--~|array;pagetokens;alltokens;@{selected|token_id}
--#leftsub|Save DC @{selected|spell_save_dc}
--#rightsub|Slot Level: [$SpellLevel]
--#title|[&spellName]
--/|Calculate damage based on spell slot.
--=DamageDice|[$SpellLevel.Total] + [&spellL0DamageDice]
--=Damage|[$DamageDice.Total]d[&spellDamageDieType]
--=HalfDamage|[$Damage.Total] \ 2
--=DoubleDamage|[$Damage.Total] * 2
--=QuarterDamage|[$Damage.Total] \ 4
--/|Since we want to be able to hover over a roll and see the dice details, output the rolled damage at the
--/|top of the card. If all critters make their save, the half damage roll won't contain the details.
--+|[c][b]Damage Roll: [/b][$Damage][/c]
--+| 
--/|Create an array to hold the tokens that are intersected by the line.
--~|array;define;tokensHit;
-->createTokenLookup|
--/|Prompt for a direction for hte cast, and define arrays that indicate the relative spaces that will be hit.
--&direction|?{Direction|⬆ (UP),U|↗ (UP-RIGHT),UR|➡ (RIGHT),R|↘ (DOWN-RIGHT),DR|⬇ (DOWN),D|↙ (DOWN-LEFT),DL|⬅ (LEFT),L|&#x2196 (UP-LEFT);,UL|}
--~|array;define;U;0,-1;0,-2;-1,-2;-1,-3;0,-3;1,-3
--~|array;define;D;0,1;0,2;1,2;-1,3;0,3;1,3
--~|array;define;R;1,0;2,0;2,-1;3,-1;3,0;3,1
--~|array;define;L;-1,0;-2,0;-2,-1;-3,-1;-3,0;-3,1
--~|array;define;UR;1,-1;1,-2;1,-3;2,-1;2,-2;3,-1
--~|array;define;DR;1,1;1,2;1,3;2,1;2,2;3,1
--~|array;define;UL;-1,-1;-1,-2;-1,-3;-2,-1;-2,-2;-3,-1
--~|array;define;DL;-1,1;-1,2;-1,3;-2,1;-2,2;-3,1
--/|Call the "checkForTokenHits" subroutine. The passed parameter will be the per-space VFX. Leave blank for none.
-->checkForTokenHits|burn-frost
--/|The first item in the array will be a blank dummy item, so remove it.
--~|array;removeat;tokensHit;0
--/|Loop through the tokensHit tokens and roll saves for each one and apply damage
--~tokenid|array;getfirst;tokensHit
--?[&tokenid] -eq ArrayError|endOutput
--:loopDisplay|
--=SaveRoll|1d20 + [*[&tokenid]:[&saveType]_save_bonus]
--/|Compare the save roll to the save DC and either apply full or half damage
--?"[*[&tokenid]:npc_immunities]" -inc "[&damageType]"|Immune
--?"[*[&tokenid]:npc_resistances]" -inc "[&damageType]"|Resistant
--?"[*[&tokenid]:npc_vulnerabilities]" -inc "[&damageType]"|Vulnerable
--?[$SaveRoll.Total] -lt @{selected|spell_save_dc}|>ApplyDamageAlterbars;[&tokenid];3;-[$Damage.Total]|>ApplyDamageAlterbars;[&tokenid];3;-[$HalfDamage.Total]
--?[$SaveRoll.Total] -ge @{selected|spell_save_dc}|madeSave
--/|Here are various damage applications if the creature is immune, resistant, or vulnerable. In some cases, we will reuse output lines,
--/|for example, a resistant creature that fails its save will jump to "madeSave", since that is the correct damage amount. (half), while
--/|a vulnerable creature that makes its save will jump to "FailedSave" since that will be normal damage.
--/|Output a line for a failed saving throw (we will also jump here for a vulnerable creature that MAKES its save)
--:FailedSave|
--+[*[&tokenid]:t-name]:|Save [$SaveRoll] [r][$Damage] [&damageType][/r]
--^afterSave|
--:Immune|
--+[*[&tokenid]:t-name]:|is not effected by the spell!
--^afterSave|
--:Resistant|
--?[$SaveRoll.Total] -lt @{selected|spell_save_dc}|>ApplyDamageAlterbars;[&tokenid];3;-[$HalfDamage.Total]|>ApplyDamageAlterbars;[&tokenid];3;-[$QuarterDamage.Total]
--?[$SaveRoll.Total] -lt @{selected|spell_save_dc}|madeSave
--+[*[&tokenid]:t-name]:|Save [$SaveRoll] [r][$QuarterDamage] [&damageType][/r]
--^afterSave|
--:Vulnerable|
--?[$SaveRoll.Total] -lt @{selected|spell_save_dc}|>ApplyDamageAlterbars;[&tokenid];3;-[$DoubleDamage.Total]|>ApplyDamageAlterbars;[&tokenid];3;-[$Damage.Total]
--?[$SaveRoll.Total] -ge @{selected|spell_save_dc}|FailedSave
--+[*[&tokenid]:t-name]:|Save [$SaveRoll] [r][$DoubleDamage] [&damageType][/r]
--^afterSave|
--/|Output a line for a successful saving throw
--:madeSave|
--+[*[&tokenid]:t-name]:|Save [$SaveRoll] [r][$HalfDamage] [&damageType][/r]
--:afterSave|
--~tokenid|array;getnext;tokensHit
--?[&tokenid] -ne ArrayError|loopDisplay
--:endOutput|
--X|
--:ApplyDamageTokenmod|Parameters are tokenid;bar#;amount
--@token-mod|_ignore-selected _ids [%1%] _set bar[%2%]_value|[%3%]
--<|
--:ApplyDamageAlterbars|Parameters are tokenid;bar#;amount
--@alter|_target|[%1%] _bar|[%2%] _amount|-[%3%] _show|none
--<|
--:checkForTokenHits|parameter is vfx descriptor
--=baseX|[*S:t-left] - 1 \ 70
--=baseY|[*S:t-top] - 1 \ 70
--~offset|array;getfirst;?{Direction}
--:checkTokenLoop|
--?"[&offset]" -eq "ArrayError"|endCheckForTokenHits
--~split|string;split;,;[&offset]
--=thisX|[$baseX] + [&split1]
--=thisY|[$baseY] + [&split2]
--/|IF we passed a visual effect specifier in %1%, create a point VFX in the square
--?"X[%1%]X" -ne "XX" |[
--=VX|[$thisX] * 70 + 35
--=VY|[$thisY] * 70 + 35
--vpoint|[$VX] [$VY] [%1%]
--]|
-->checkTokens|[$thisX];[$thisY]
--~offset|array;getnext;?{Direction}
--^checkTokenLoop|
--:endCheckForTokenHits|
--<|
--/|Reads the variables created by createTokenLookup to find any tokens that occupy a given space.
--:checkTokens|x;y
--?"X[&tok[%1%]-[%2%]]X" -ne "XX"|[
--~split|string;split;!;[&tok[%1%]-[%2%]]
--%P|1;[$splitCount.Total];1
--=var|split[&P]
--?"X[&[$var.RollText]]X" -eq "XX"|%
--~exists|array;indexof;tokensHit;[&[$var.RollText]]
--?[&exists] -ne ArrayError|skipAdd
--?[&[$var.RollText]] -eq ArrayError|skipAdd
--~|array;add;tokensHit;[&[$var.RollText]]
--:skipAdd|
--%|
--<|
--/|Creates a series of string variables with names like 'tok12-15' which represent the various squares that are
--/|occupied by tokens on the page. Handle 1x1, 2x2, and 3x3 tokens by simply adding extra squares in the appropriate
--/|pattern around the center point location. The result is that if there are two tokens at 12,15, the tok12-15 string
--/|will contain something like "-asln34njfn2nafd!-sdnfklaserfs" (IDs separated by exclamation points) that we can use to
--/|quickly evaluate hits by essentially asking "what is in square 12x15" by just reading the variable.
--:createTokenLookup|
--~tokenid|array;getfirst;alltokens
--:tokenSetupLoop|
--?[&tokenid] -eq ArrayError|endSetupLoop
--=tLeft|[*[&tokenid]:t-left] - 1 \ 70
--=tTop|[*[&tokenid]:t-top] - 1 \ 70
--=tWidth|[*[&tokenid]:t-width]
--?[$tWidth] -eq 70|[
--&tok[$tLeft]-[$tTop]|+[&tokenid]!
--/+[*[&tokenid]:character_name]|At [$tLeft],[$tTop] : [&tok[$tLeft.Total]-[$tTop.Total]]
--]|
--?[$tWidth] -eq 140|[
--=NX|[$tLeft] + 1
--=NY|[$tTop] + 1
--&tok[$tLeft]-[$tTop]|+[&tokenid]!
--&tok[$tLeft]-[$NY]|+[&tokenid]!
--&tok[$NX]-[$tTop]|+[&tokenid]!
--&tok[$NX]-[$NY]|+[&tokenid]!
--]|
--?[$tWidth] -eq 210|[
--=PX|[$tLeft] - 1
--=PY|[$tTop] - 1
--=NX|[$tLeft] + 1
--=NY|[$tTop] + 1
--&tok[$tLeft]-[$tTop]|+[&tokenid]!
--&tok[$PX]-[$PY]|+[&tokenid]!
--&tok[$tLeft]-[$PY]|+[&tokenid]!
--&tok[$NX]-[$PY]|+[&tokenid]!
--&tok[$PX]-[$tTop]|+[&tokenid]!
--&tok[$NX]-[$tTop]|+[&tokenid]!
--&tok[$PX]-[$NY]|+[&tokenid]!
--&tok[$tLeft]-[$NY]|+[&tokenid]!
--&tok[$NX]-[$NY]|+[&tokenid]!
--]|
--~tokenid|array;getnext;alltokens
--^tokenSetupLoop|
--:endSetupLoop|
--<|
}} Your scripts are currently disabled due to an error that was detected. Please make appropriate changes to your script's code and click the "Save Script" button. We will then attempt to start running the scripts again. More info... If this script was installed from the Script Library, you might find help in the Community API Forum. For reference, the error message generated was: ReferenceError: arrayvariables is not defined
ReferenceError: arrayvariables is not defined
at apiscript.js:8323:30
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:1708:12
at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560
at hc (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:39:147)
at Kd (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:546)
at Id.Mb (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:489)
at Zd.Ld.Mb (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:94:425)
at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:111:400 "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 137" "ScriptCards Error: Label [ is not defined on line 101" "ScriptCards Error: Label [ is not defined on line 113" "ScriptCards Error: Label % is not defined on line 117" I get these errors after running this code. I get nearly the same errors for the lightning bolt example you made. Am I supposed to alter this code to make it work? BTW- I love what you've made here and I'm eager to master it. I've already been able to re-script almost all of the PowerCards macros I made in less than a week. Great work. I can't wait to be proficient enough to contribute to the community. Any help with this you can provide is GREATLY appreciated.