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

Ice Knife and other spells that deal damage two ways

1718772712

Edited 1718772846
Dink
Pro
Curious if two different events can be written into one script in ScriptCards.   Ice Knife  Is one such spell.   1st damage is piercing damage dealt by an attack roll to the target. 2nd damage is to the target and all within 5' cold damage with a saving throw to lessen the damage. I can write the script for the 1st damage easy enough, and I can adapt a fireball script, adjusting the AOE and the damage to fit the parameters, but if I just follow the 1st part with the 2nd... will the parameters from the first influence the 2nd? or will they be overwritten with the new parameters when the function calls ask for the information? Another issue is the building of the text block in the chat.  Will it just keep going?  or will the second part just completely overwrite the first in the chat?
ScriptCards is capable of doing separate damage for things. I have this Ice Knife SC when I was working with another forum user on the spell. !scriptcard {{ --/|Ice Knife has an attack and area of effect damage --/|Script can be set to auto-roll NPC token saves for AoE damage --/|Script can be set to auto-apply damage to NPC tokens --/|NOTE: PC tokens are always prompted for the player to roll the save. Never autorolls for a player --/|NPC saves also roll a second roll for advantage/disadvantage --/|Auto-applying damage will not use adv/disadvantage and only consider the initial saving throw --/|Requires: ScriptCards 2.3.8+ --/|TODO: allow upcasting --/|VARIABLES TO SET --&FeatureName|Ice Knife --&MinimumSpellLevel|1 --&TargetACAttribute|npc_ac --&AutoRollNPCSaves|false --&AutoApplyDamage|false --&HPBar|1 --&emoteMessage|conjures a sharp cold blade! --&verboseOutput|true --#sourceToken|@{selected|token_id} --#targetToken|@{target|token_id} --#title|[&FeatureName] --#emoteText|[*S:character_name] [&emoteMessage] --#reentryval|[&FeatureName][*S:character_id] --Rfind|[*S:character_id];[&FeatureName];repeating_spell-[&MinimumSpellLevel];spellname --?"[*R:spellname]" -eq "NoRepeatingAttributeLoaded"|>NotFound;[&FeatureName] --/|Check spell slot remaining --=RemainingSlots|[*S:lvl[&MinimumSpellLevel]_slots_expended] --?[$RemainingSlots] -eq 0|InsufficientResources --:DeductResources| --!a:[*S:character_id]|lvl[&MinimumSpellLevel]_slots_expended:-=1 --:AttackRoll| --=AtkRoll|1d20 + [*S:spell_attack_bonus] [SPELLATTACK] --?[$AtkRoll] -lt [*T:[&TargetACAttribute]]|Miss --?[$AtkRoll.Base] -eq 20|Crit|Hit --:SplashDamage| --=SplashDamageRoll|[*R:spelldamage2] --+Splash Damage|Each creature in area needs to make a [*R:spellsave] vs DC [*R:roll_output_dc] or take [$SplashDamageRoll] [*R:spelldamagetype2] damage. [*R:spellsavesuccess][br] --:DetermineTokensInArea| --/|Check for friendly fire first --~pcTokenCount|array;pagetokens;PCTokenArr;[*C:playerpageid];pc --%pctid|foreach;PCTokenArr -->CheckAdjacency|[*T:t-id];[&pctid];PCAdjacent --?[&PCAdjacent] -eq 1|[ --+Friendly Fire|[b][*[&pctid]:t-name][/b] needs to make a [sheetbutton][*R:spellsave]::[*[&pctid]:character_name]::Saves[/sheetbutton] --]| --%| --~|array;define;AdjancentNPCTokenArr;[*T:t-id] --~npcTokenCount|array;pagetokens;NPCTokenArr;[*C:playerpageid];npc --%npctid|foreach;NPCTokenArr --?"[&npctid]" -eq "[*T:t-id]"|% -->CheckAdjacency|[*T:t-id];[&npctid];NPCAdjacent --?[&NPCAdjacent] -eq 1|[ --~|array;add;AdjancentNPCTokenArr;[&npctid] --]| --%| --%adjacentTID|foreach;AdjancentNPCTokenArr --&damageType|[*R:spelldamagetype2] --?"[*[&adjacentTID]:npc_immunities]" -inc "[&damageType(tolowercase)]"|[ --*IMMUNE|[*[&adjacentTID]:t-name] is adjacent but immune to [&damageType(tolowercase)] --%| --]| --&buttonParams|[&adjacentTID]%[*R:spellsave]%[*R:roll_output_dc] --?"[&AutoRollNPCSaves]" -ne "true"|[ --*[*[&adjacentTID]:t-name]|[rbutton][*R:spellsave] Save::NPCSavingThrow;[&buttonParams][/rbutton] --]|[ -->NPCSavingThrow|[&adjacentTID];[*R:spellsave];[*R:roll_output_dc] --]| --%| --:Done| --X| --:Miss| --=AtkDamage|0 --+[&FeatureName]|Attack Roll:[$AtkRoll] misses![br] --^SplashDamage| --:Hit| --=AtkDamage|[*R:spelldamage] --+[&FeatureName]|Attack Roll:[$AtkRoll] hits for [$AtkDamage] [*R:spelldamagetype] damage[br] --^SplashDamage| --:Crit| --+[&FeatureName]|Attack Roll:[$AtkRoll] critical hit! --=DamageRoll|[*R:spelldamage] --=CritRoll|[*R:spelldamage] --=AtkDamage|[$DamageRoll] + [$CritRoll] [CRIT] --+Total Damage|[$DamageRoll] + [$CritRoll] critical damage for [$AtkDamage] total [*R:spelldamagetype] damage[br] --^SplashDamage| --:CheckAdjacency|TargetTokenID;AdjacentTokenID;StringVariableToSet --/|If the tokens overlap then they are also considered adjacent for the purposes of splash damage -->DoTokensOverlap|[%1%];[%2%];0;[%3%] --<| --/|Check to see if two tokens overlap --/|The y coordinates are negative because roll20 0,0 is the top left corner of the page --/|that makes the y coordinates for tokens negative on a traditional grid --/|The PixelPadding is to allow checking if tokens overlap without sharing a border --/|Set PixelPadding to 1 to remove adjacent tokens that share a border --/|Set to 0 to also get adjacent tokens --:DoTokensOverlap|TokenID1;TokenID2;PixelPadding;StringVariableToSet --=T1HalfHeight|[*[%1%]:t-height] / 2 --=T1HalfWidth|[*[%1%]:t-width] / 2 --/|L1x is realLeft --=L1x|[*[%1%]:t-left] - [$T1HalfWidth] + [%3$] --/|L1y is negative realTop --=L1y|-[*[%1%]:t-top] + [$T1HalfHeight] - [%3%] --/|R1x is right --=R1x|[*[%1%]:t-left] + [$T1HalfWidth] - [%3%] --/|R1y is negative bottom --=R1y|-[*[%1%]:t-top] - [$T1HalfHeight] + [%3%] --=T2HalfHeight|[*[%2%]:t-height] / 2 --=T2HalfWidth|[*[%2%]:t-width] / 2 --/|L2x is realLeft --=L2x|[*[%2%]:t-left] - [$T2HalfWidth] + [%3%] --/|L2y is negative realTop --=L2y|-[*[%2%]:t-top] + [$T2HalfHeight] - [%3$] --/|R2x is right --=R2x|[*[%2%]:t-left] + [$T2HalfWidth] - [%3%] --/|R2y is negative bottom --=R2y|-[*[%2%]:t-top] - [$T2HalfHeight] + [%3%] --&[%4%]|1 --?[$L1x] -gt [$R2x] -or [$L2x] -gt [$R1x]|&[%4%];0 --?[$R1y] -gt [$L2y] -or [$R2y] -gt [$L1y]|&[%4%];0 --<| --X| --/|AutoRoll will use params and non-Auto will use re-entry buttons --:NPCSavingThrow|NPCTokenID;SaveType;DC --?"X[%1%]" -eq "X"|[ --&params|[&reentryval] --#hidecard|1 --]|[ --&params|[%1%]%[%2%]%[%3%] --]| --~npcSTInfo|string;split;%;[&params] --?"[&npcSTInfo2]" -eq "Strength"|&npcSTShortname;str --?"[&npcSTInfo2]" -eq "Dexterity"|&npcSTShortname;dex --?"[&npcSTInfo2]" -eq "Constitution"|&npcSTShortname;con --?"[&npcSTInfo2]" -eq "Intelligence"|&npcSTShortname;int --?"[&npcSTInfo2]" -eq "Wisdom"|&npcSTShortname;wis --?"[&npcSTInfo2]" -eq "Charisma"|&npcSTShortname;cha --~npcSTMod|math;max;[*[&npcSTInfo1]:npc_[&npcSTShortname]_save];[*[&npcSTInfo1]:[&npcSTInfo2(tolowercase)]_save_bonus] --=saveRoll|1d20 + [$npcSTMod] [MOD] --=advRoll|1d20 + [$npcSTMod] [MOD] --?[$saveRoll] -ge [&npcSTInfo3] -and [$advRoll] -ge [&npcSTInfo3]|&result;success --?[$saveRoll] -lt [&npcSTInfo3] -and [$advRoll] -lt [&npcSTInfo3]|&result;failure --?[$saveRoll] -ge [&npcSTInfo3] -and [$advRoll] -lt [&npcSTInfo3]|&result;successmixed --?[$saveRoll] -lt [&npcSTInfo3] -and [$advRoll] -ge [&npcSTInfo3]|&result;failuremixed --&tookDamage|0 --?"[*T:t-id]" -eq "[&npcSTInfo1]" -and [$AtkDamage] -gt 0|&initialDamage;1|&initialDamage;0 --?"[&result]" -inc "failure" -or [&initialDamage] -eq 1|&tookDamage;1 --&msg|Sv:[$saveRoll] A/D:[$advRoll] [b][&result][/b] --?"[&verboseOutput]" -eq "true"|[ --*[*[&npcSTInfo1]:t-name]|[&msg] --]| --?"[&AutoApplyDamage]" -eq "true" -and "[&tookDamage]" -eq 1|>ApplyDamage;[&npcSTInfo1];[&result] --?"[&AutoApplyDamage]" -ne "true" -and "[&result]" -ne "success"|[ --*[*[&npcSTInfo1]:t-name]|[rbutton]Apply Damage::ApplyDamage;[&npcSTInfo1]%[&result][/rbutton] --]| --<| --/|Add a stop here so re-entry doesn't fallthrough when not set to auto --X| --:ApplyDamage|NPCTokenID;Result --?"X[%1%]" -eq "X"|[ --&adParams|[&reentryval] --#hidecard|1 --]|[ --&adParams|[%1%]%[%2%] --]| --&adTID|[&adParams(split,%,0)] --/|Check damage modifiers. Already checked immunity previously -->Lib5E_CheckDamageModifiers|ResistType;[*R:spelldamagetype2] --=TotalDamage|[$SplashDamageRoll] [&ResistType] --/|Check if initial target to add any piercing damage and check result so that successful saving throws don't get splash damage --?"[&adTID]" -eq "[*T:t-id]"|[ --?"[&AutoApplyDamage]" -eq "true" -and "[&adParams(split,%,1)]" -inc "success"|=TotalDamage;0 --=TotalDamage|[$TotalDamage] [SPLASH] + [$AtkDamage] [ATTACK] --]| --?"[&verboseOutput]" -eq "true"|[ --*Applying Damage|[$TotalDamage] damage to bar [&HPBar] of [b][*[&adTID]:t-name][/b] --]| --!t:[&adTID]|bar[&HPBar]_value:-=[$TotalDamage] --<| --/|Add a stop here so re-entry doesn't fallthrough when not set to auto --X| --/|From Kurt J's dnd5elib library but porting over here to make scriptcard self contained --:Lib5E_CheckDamageModifiers|damageVariableName;damageType --&[%1%]| --?"[*T:npc_vulnerabilities]" -inc "[%2%]"|>_Lib5E_IsVulnerable;[%1%] --?"[*T:npc_resistances]" -inc "[%2%]"|>_Lib5E_IsResistant;[%1%] --?"[*T:npc_immunities]" -inc "[%2%]"|>_Lib5E_IsImmune;[%1%] --<| --:_Lib5E_IsVulnerable| --&[%1%]| * 2 [Vulnerable] --<| --:_Lib5E_IsResistant| --&[%1%]| \ 2 [Resistant] --<| --:_Lib5E_IsImmune| --&[%1%]| * 0 [Immune] --<| --:NotFound|FeatureName --#emoteText|Not Found --+ERROR|[%1%] not found. --^Done| --:InsufficientResources| --#emoteText|Out of spell slots --+Out of Uses|No more remaining spells for [&FeatureName] --^Done| }} The configuration is in variables near the top of the SC. --/|VARIABLES TO SET --&FeatureName|Ice Knife --&MinimumSpellLevel|1 --&TargetACAttribute|npc_ac --&AutoRollNPCSaves|false --&AutoApplyDamage|false --&HPBar|1 --&emoteMessage|conjures a sharp cold blade! --&verboseOutput|true This can set which token bar is used for HP, whether or not to auto-roll the NPC saves (note it will not roll saves for PCs it will just print that PCs need to roll their save), whether to auto-apply the damage or whisper to the DM a button to apply damage. I know other folks have their own Ice Knife SCs so the above is just one way to do but maybe it can be a starting point for you. ScriptCards will output all direct output stataments `--+` in them. The only way to overwrite is if you stored your messages in string variables `--&` and overwrite the string variable before outputting it.
1718843020

Edited 1718843342
Dink
Pro
awesome!  Thanx again Joshua!  will have to give this a try! are the variables You mention in the second box the defaults?  If so good,.. I'm torn between the "apply damage" issue and leaning toward manual manipulatiion currently.
Those variables are where you can set things to how you want to run it. If you want it to prompt for the saves and prompt to apply damage, then leave them set to false. If you want to try out the auto-roll saving throws and auto-apply damage set them to true and make sure the --&HPBar| string variable is set to the token bar your game uses for HP. I try to keep the configuration up near the top of the scriptcard so folks can set it to however works best for their game.
yikes. ok.. I think this one is quite beyond my skill set at this point.. there are a lot of ... "variables".. that I'm not finding origins for and have to assume are just "known" values... like,.. I think "*T" refers to the target? without typing out the whole "@{target|token_id}" every time,.. and "*S" is for "@{selected|token_id}" but that's a guess seeing their locations in the lines...  but there's no line defining that, I'm just guessing You'd have to know that ahead of time... but there are a few.. like "[*T:t-id]" that i'm at a loss for since i get the *T.. but the rest.??   I'm only guessing that the : means something, and will have to find that in the wiki...   So for now... adapting this one isn't something i'll be doing,.. also.. without being able to uplevel this,.. I won't be able to use it anyway.. My Druid is prone to the gaurdian/healer/protector role,.. and wildshapes a lot... Ice Knife is a favorite for her when baddies are bunched up and she doesn't have much use for most of her higher spells.... so Ice Knife get's the higher slots often... BUT,.. I will be trying to figure this one out...  just can't use much of it currently.... Thanx MUCHLY for the help!!
So the [*S: and [*T: syntax are  attribute referencing  and specifically shortcuts using the 2 parameters --#sourceToken| and --#targetToken|. Which you see include the Roll20 attribute references of @{selected|token_id} and @{target|token_id} which are resolved before the ScriptCard runs. When using ScriptCards attribute referencing character attributes, like hp or ac are used directly like [*S:ac] or [*T:hp],  token properties  are prefixed with a t-, so [*T:t-id] is target token id. [*T:t-left] is the targets token left property and [*T:t-top] would be the target token's top property. So here is an updated version to allow upcasting. !scriptcard {{ --/|Ice Knife has an attack and area of effect damage --/|Script can be set to auto-roll NPC token saves for AoE damage --/|Script can be set to auto-apply damage to NPC tokens --/|NOTE: PC tokens are always prompted for the player to roll the save. Never autorolls for a player --/|NPC saves also roll a second roll for advantage/disadvantage --/|Auto-applying damage will not use adv/disadvantage and only consider the initial saving throw --/|Requires: ScriptCards 2.3.8+ --/|VERSION: 1.1.0 --/|VARIABLES TO SET --&FeatureName|Ice Knife --&MinimumSpellLevel|1 --&TargetACAttribute|npc_ac --&AutoRollNPCSaves|false --&AutoApplyDamage|false --&HPBar|1 --&emoteMessage|conjures a sharp cold blade! --&verboseOutput|true --#sourceToken|@{selected|token_id} --#targetToken|@{target|token_id} --#title|[&FeatureName] --#emoteText|[*S:character_name] [&emoteMessage] --#reentryval|[&FeatureName][*S:character_id] --Rfind|[*S:character_id];[&FeatureName];repeating_spell-[&MinimumSpellLevel];spellname --?"[*R:spellname]" -eq "NoRepeatingAttributeLoaded"|>NotFound;[&FeatureName] -->Lib5eCasting_GetAvailableSpellSlots|[*S:character_id];[&MinimumSpellLevel];SpellsAvailableArr --?[@SpellsAvailableArr(length)] -lt 1|InsufficientResources --:GetCastingLevel| --&castingLevel|[&MinimumSpellLevel] --?[@SpellsAvailableArr(length)] -eq 1|[ --?"[&verboseOutput]" -eq "true"|+;Only 1 available spell level. Casting at level [@SpellsAvailableArr(0)] --&castingLevel|[@SpellsAvailableArr(0)] --^ProcessSpell| --]| --+|[c][b]Choose Spell Level for [&FeatureName][/b][/c] --&splvlMsg| --%splvl|foreach;SpellsAvailableArr --&splvlMsg|+[rbutton][&splvl]::CastSpell;[&splvl][/rbutton] --%| --+|[c][&splvlMsg][/c] --:Done| --X| --:CastSpell|SpellLevel --:DeductResources| --!a:[*S:character_id]|lvl[&reentryval]_slots_expended:-=1 --:AttackRoll| --=AtkRoll|1d20 + [*S:spell_attack_bonus] [SPELLATTACK] --?[$AtkRoll] -lt [*T:[&TargetACAttribute]]|Miss --?[$AtkRoll.Base] -eq 20|Crit|Hit --:SplashDamage| --?[&reentryval] -gt 1|&upcastDamage; + [= [&reentryval] - 1]d6|&upcastDamage; --=SplashDamageRoll|[*R:spelldamage2] [&upcastDamage] --+Splash Damage|Each creature in area needs to make a [*R:spellsave] vs DC [*S:spell_save_dc] or take [$SplashDamageRoll] [*R:spelldamagetype2] damage. [*R:spellsavesuccess][br] --:DetermineTokensInArea| --/|Check for friendly fire first --~pcTokenCount|array;pagetokens;PCTokenArr;[*C:playerpageid];pc --%pctid|foreach;PCTokenArr -->CheckAdjacency|[*T:t-id];[&pctid];PCAdjacent --?[&PCAdjacent] -eq 1|[ --+Friendly Fire|[b][*[&pctid]:t-name][/b] needs to make a [sheetbutton][*R:spellsave]::[*[&pctid]:character_name]::Saves[/sheetbutton] --]| --%| --~|array;define;AdjancentNPCTokenArr;[*T:t-id] --~npcTokenCount|array;pagetokens;NPCTokenArr;[*C:playerpageid];npc --%npctid|foreach;NPCTokenArr --?"[&npctid]" -eq "[*T:t-id]"|% -->CheckAdjacency|[*T:t-id];[&npctid];NPCAdjacent --?[&NPCAdjacent] -eq 1|[ --~|array;add;AdjancentNPCTokenArr;[&npctid] --]| --%| --%adjacentTID|foreach;AdjancentNPCTokenArr --&damageType|[*R:spelldamagetype2] --?"[*[&adjacentTID]:npc_immunities]" -inc "[&damageType(tolowercase)]"|[ --*IMMUNE|[*[&adjacentTID]:t-name] is adjacent but immune to [&damageType(tolowercase)] --%| --]| --&buttonParams|[&adjacentTID]%[*R:spellsave]%[*S:spell_save_dc] --?"[&AutoRollNPCSaves]" -ne "true"|[ --*[*[&adjacentTID]:t-name]|[rbutton][*R:spellsave] Save::NPCSavingThrow;[&buttonParams][/rbutton] --]|[ -->NPCSavingThrow|[&adjacentTID];[*R:spellsave];[*S:spell_save_dc] --]| --%| --^Done| --:Miss| --=AtkDamage|0 --+[&FeatureName]|Attack Roll:[$AtkRoll] misses![br] --^SplashDamage| --:Hit| --=AtkDamage|[*R:spelldamage] --+[&FeatureName]|Attack Roll:[$AtkRoll] hits for [$AtkDamage] [*R:spelldamagetype] damage[br] --^SplashDamage| --:Crit| --+[&FeatureName]|Attack Roll:[$AtkRoll] critical hit! --=DamageRoll|[*R:spelldamage] --=CritRoll|[*R:spelldamage] --=AtkDamage|[$DamageRoll] + [$CritRoll] [CRIT] --+Total Damage|[$DamageRoll] + [$CritRoll] critical damage for [$AtkDamage] total [*R:spelldamagetype] damage[br] --^SplashDamage| --:CheckAdjacency|TargetTokenID;AdjacentTokenID;StringVariableToSet --/|If the tokens overlap then they are also considered adjacent for the purposes of splash damage -->DoTokensOverlap|[%1%];[%2%];0;[%3%] --<| --/|Check to see if two tokens overlap --/|The y coordinates are negative because roll20 0,0 is the top left corner of the page --/|that makes the y coordinates for tokens negative on a traditional grid --/|The PixelPadding is to allow checking if tokens overlap without sharing a border --/|Set PixelPadding to 1 to remove adjacent tokens that share a border --/|Set to 0 to also get adjacent tokens --:DoTokensOverlap|TokenID1;TokenID2;PixelPadding;StringVariableToSet --=T1HalfHeight|[*[%1%]:t-height] / 2 --=T1HalfWidth|[*[%1%]:t-width] / 2 --/|L1x is realLeft --=L1x|[*[%1%]:t-left] - [$T1HalfWidth] + [%3$] --/|L1y is negative realTop --=L1y|-[*[%1%]:t-top] + [$T1HalfHeight] - [%3%] --/|R1x is right --=R1x|[*[%1%]:t-left] + [$T1HalfWidth] - [%3%] --/|R1y is negative bottom --=R1y|-[*[%1%]:t-top] - [$T1HalfHeight] + [%3%] --=T2HalfHeight|[*[%2%]:t-height] / 2 --=T2HalfWidth|[*[%2%]:t-width] / 2 --/|L2x is realLeft --=L2x|[*[%2%]:t-left] - [$T2HalfWidth] + [%3%] --/|L2y is negative realTop --=L2y|-[*[%2%]:t-top] + [$T2HalfHeight] - [%3$] --/|R2x is right --=R2x|[*[%2%]:t-left] + [$T2HalfWidth] - [%3%] --/|R2y is negative bottom --=R2y|-[*[%2%]:t-top] - [$T2HalfHeight] + [%3%] --&[%4%]|1 --?[$L1x] -gt [$R2x] -or [$L2x] -gt [$R1x]|&[%4%];0 --?[$R1y] -gt [$L2y] -or [$R2y] -gt [$L1y]|&[%4%];0 --<| --X| --/|AutoRoll will use params and non-Auto will use re-entry buttons --:NPCSavingThrow|NPCTokenID;SaveType;DC --?"X[%1%]" -eq "X"|[ --&params|[&reentryval] --#hidecard|1 --]|[ --&params|[%1%]%[%2%]%[%3%] --]| --~npcSTInfo|string;split;%;[&params] --?"[&npcSTInfo2]" -eq "Strength"|&npcSTShortname;str --?"[&npcSTInfo2]" -eq "Dexterity"|&npcSTShortname;dex --?"[&npcSTInfo2]" -eq "Constitution"|&npcSTShortname;con --?"[&npcSTInfo2]" -eq "Intelligence"|&npcSTShortname;int --?"[&npcSTInfo2]" -eq "Wisdom"|&npcSTShortname;wis --?"[&npcSTInfo2]" -eq "Charisma"|&npcSTShortname;cha --~npcSTMod|math;max;[*[&npcSTInfo1]:npc_[&npcSTShortname]_save];[*[&npcSTInfo1]:[&npcSTInfo2(tolowercase)]_save_bonus] --=saveRoll|1d20 + [$npcSTMod] [MOD] --=advRoll|1d20 + [$npcSTMod] [MOD] --?[$saveRoll] -ge [&npcSTInfo3] -and [$advRoll] -ge [&npcSTInfo3]|&result;success --?[$saveRoll] -lt [&npcSTInfo3] -and [$advRoll] -lt [&npcSTInfo3]|&result;failure --?[$saveRoll] -ge [&npcSTInfo3] -and [$advRoll] -lt [&npcSTInfo3]|&result;successmixed --?[$saveRoll] -lt [&npcSTInfo3] -and [$advRoll] -ge [&npcSTInfo3]|&result;failuremixed --&tookDamage|0 --?"[*T:t-id]" -eq "[&npcSTInfo1]" -and [$AtkDamage] -gt 0|&initialDamage;1|&initialDamage;0 --?"[&result]" -inc "failure" -or [&initialDamage] -eq 1|&tookDamage;1 --&msg|Sv:[$saveRoll] A/D:[$advRoll] [b][&result][/b] --?"[&verboseOutput]" -eq "true"|[ --*[*[&npcSTInfo1]:t-name]|[&msg] --]| --?"[&AutoApplyDamage]" -eq "true" -and "[&tookDamage]" -eq 1|>ApplyDamage;[&npcSTInfo1];[&result] --?"[&AutoApplyDamage]" -ne "true" -and "[&result]" -ne "success"|[ --*[*[&npcSTInfo1]:t-name]|[rbutton]Apply Damage::ApplyDamage;[&npcSTInfo1]%[&result][/rbutton] --]| --<| --/|Add a stop here so re-entry doesn't fallthrough when not set to auto --X| --:ApplyDamage|NPCTokenID;Result --?"X[%1%]" -eq "X"|[ --&adParams|[&reentryval] --#hidecard|1 --]|[ --&adParams|[%1%]%[%2%] --]| --&adTID|[&adParams(split,%,0)] --/|Check damage modifiers. Already checked immunity previously -->Lib5E_CheckDamageModifiers|ResistType;[*R:spelldamagetype2] --=TotalDamage|[$SplashDamageRoll] [&ResistType] --/|Check if initial target to add any piercing damage and check result so that successful saving throws don't get splash damage --?"[&adTID]" -eq "[*T:t-id]"|[ --?"[&AutoApplyDamage]" -eq "true" -and "[&adParams(split,%,1)]" -inc "success"|=TotalDamage;0 --=TotalDamage|[$TotalDamage] [SPLASH] + [$AtkDamage] [ATTACK] --]| --?"[&verboseOutput]" -eq "true"|[ --*Applying Damage|[$TotalDamage] damage to bar [&HPBar] of [b][*[&adTID]:t-name][/b] --]| --!t:[&adTID]|bar[&HPBar]_value:-=[$TotalDamage] --<| --/|Add a stop here so re-entry doesn't fallthrough when not set to auto --X| --/|From Kurt J's dnd5elib library but porting over here to make scriptcard self contained --:Lib5E_CheckDamageModifiers|damageVariableName;damageType --&[%1%]| --?"[*T:npc_vulnerabilities]" -inc "[%2%]"|>_Lib5E_IsVulnerable;[%1%] --?"[*T:npc_resistances]" -inc "[%2%]"|>_Lib5E_IsResistant;[%1%] --?"[*T:npc_immunities]" -inc "[%2%]"|>_Lib5E_IsImmune;[%1%] --<| --:_Lib5E_IsVulnerable| --&[%1%]| * 2 [Vulnerable] --<| --:_Lib5E_IsResistant| --&[%1%]| \ 2 [Resistant] --<| --:_Lib5E_IsImmune| --&[%1%]| * 0 [Immune] --<| --:NotFound|FeatureName --#emoteText|Not Found --+ERROR|[%1%] not found. --^Done| --:InsufficientResources| --#emoteText|Out of spell slots --+Out of Uses|No more remaining spells for [&FeatureName] --^Done| --:Lib5eCasting_GetAvailableSpellSlots|CharacterID;MinimumSpellLevel;ArrayNameToSet --~|array;define;[%3%] --%SpellLvlLoop|[%2%];9;1 --?[*[%1%]:lvl[&SpellLvlLoop]_slots_total] -le 0|%! --?[*[%1%]:lvl[&SpellLvlLoop]_slots_expended] -le 0|% --~|array;add;[%3%];[&SpellLvlLoop] --%| --<| }} So when it's first run, the ScriptCard will whisper to the caster for which spell level to cast at using available spell slots: Then when the spell level is chosen it will display the results of the attack roll and what the splash damage is and it will whisper to the DM the NPCs impacted by the spell, the initial target and any adjacent NPCs and will provide a button for each NPC to roll the Dex save. When the GM clicks the Dexterity save button, it will roll the save and whisper the results and an apply damage button which will check for resistance or immunity to cold damage and apply the damage accordingly when the GM clicks the Apply Damage button. The other steps are configurable via those string variables near the top in the configuration section.
Wow!  Just Awesome!   Sorry haven't replied earlier... have been prepping for the weekly session on Sunday, and analyzing this script.    A lot in it I still don't understand, but some of it is starting to stick. We will certainly give this a shot tomorrow in session.  I didn't have ANY of these scripts availble the last session we played... {had a couple of canceled session}  so I'm hoping my players will really love the changes! Thanx again!    Muchly!!  
1719105354

Edited 1719106111
Dink
Pro
ok.. it's working fine,.. only still can't use it.  I'll have to do some more research.   this version looks for spell slot availability and auto deducts spell slots...  that's not gonna work in our game.  I was wondering why the first time I tried to cast it, it didn't offer me a 5th level option... then after trying it once and calling it at 4th level... the next running didn't offer that either.  I'll have to learn this scripting and figure out how to alter it cause I can't find those lines.... usually denoted by something like...    --=SlotLevel|?{Spell Slot Level?|1|2|3|4|5|6|7|8|9} but these are different... I don't think I'm ready for this level of scripting... there is a lot of codeing in there that I'm sure is designed to reduce the lines of code and lessen the length of the entire script, but I'm just not ready to see those yet....or at least not understanding them at least...  I have been removing the lines of script from most that i find that have anything to do with automatically editing a character or target sheet.   (e.g. spell slots or HP or.. anything...)   Until I understand exactly what it's editing,.. I'd rather just let the players edit their own,.. or i'll edit the NPC sheets manually. Also,.. the "saving throw" part is throwing me errors because it's not finding something.  I usually take those executions out also since I use the "Group Check" API anyway...   the errors look like this...  I'm pretty sure the number is just the id for the target, but something is obviously wrong with my NPC sheet. No ability was found for %{-1994552523_6799188|Saves} I use a LOT of custom critters and I'm sure it's just because I failed to enter something on the sheet.
1719106641

Edited 1719107448
So the Saves ability should only be prompting for Player characters that are adjacent. Player characters in this sense as defined by the array;pagetokens pc filter which means a token that is linked to a character and that is controlled by a player. The npc filter is a token linked to a character that does not have a player controlledby. So if your game assigns a controlledby for NPCs as well, then that array;pagetoken filter won't work to determine if the adjacent token is a PC or an NPC. So your game doesn't look for available spell slots? You would rather your players be able to cast at any spell level without deducting a spell? EDIT: This is the section where it checks if there are PC token's adjacent and the Saves ability button. --:DetermineTokensInArea| --/|Check for friendly fire first --~pcTokenCount|array;pagetokens;PCTokenArr;[*C:playerpageid];pc --%pctid|foreach;PCTokenArr -->CheckAdjacency|[*T:t-id];[&pctid];PCAdjacent --?[&PCAdjacent] -eq 1|[ --+Friendly Fire|[b][*[&pctid]:t-name][/b] needs to make a [sheetbutton][*R:spellsave]::[*[&pctid]:character_name]::Saves[/sheetbutton] --]| --%| In my games, I don't assign a player to control NPCs so the the npc filter works in my games. --~|array;define;AdjancentNPCTokenArr;[*T:t-id] --~npcTokenCount|array;pagetokens;NPCTokenArr;[*C:playerpageid];npc --%npctid|foreach;NPCTokenArr --?"[&npctid]" -eq "[*T:t-id]"|% -->CheckAdjacency|[*T:t-id];[&npctid];NPCAdjacent --?[&NPCAdjacent] -eq 1|[ --~|array;add;AdjancentNPCTokenArr;[&npctid] --]| --%| So that npc filter works and then will find adjacent NPC tokens. It doesn't prompt for the Saves ability, which is an ability I have on my player's character sheets but it doesn't really come up much since they don't get caught in Ice Knife. Anyway that's some explanations for that. Sorry it doesn't work for your games. 
The saves part isn't really an issue,.. I would just kind of ignore that part for the NPC's and just do my usual with GroupCheck. As far as the spell slot thing...  And I'd be lying if i said I was absolutely sure my players were religiously deducting from their sheets,.. but they've been pretty awesome with the honor system concept, and I usually track what they use during a session and check after the sessions.  It makes a little more work for me sometimes,. but I find that they are really good about deducting their own and knowing what they have available.  Somehow I think that's a part of the "mechanics" of the game that they enjoy,.. the keeping track of their resources, so I'm not inclined to take that away.  I've not applied that kind of policy with any others and doing so now would prolly cause issues with them deducting slots.....after the script already did.  If I could apply that sort of script?  or policy? or app? or whatever to every spell cast, and have it auto-deduct, then I might consider it.   But, I don't think that kind of application exists and making them guess which are doing it automatically and not...  might just cause more issues than the value of ease that the automaicality (<--not sure that's a word) of the function provides. My players aren't perfect by any means,..but neither is our game.  They do however somehow,... with some interestingly subtle tacticity? (<--not sure of that word either).. but they check each other.   We often have commentary like... "are you sure You can do that?"  or  "didn't You just use Your only 5th level slot"... (they are all 9th level currently)  or... "aren't You already concentrating on somethin else?"    So... i don't think,.. at this point at least, I'm inclined to have it have to see if there's availability or auto-deduct anything.
and NO need to appologize.. LoL.. You've done FAR more than I could ever hope for to further my education on this and I'm emmencely grateful!!!