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

Teleport Script for Misty Step Spell D&D 5E OGL Sheet

Hi All, I know there's an existing teleport script, but that's more for creating teleporting pads to get people to different building floors or different maps. What I'm looking for is something to teleport a token, specifically teleporting a token to a space up to 30 feet away, controlled by the player. I know that selecting empty grid spaces isn't really supported, but I can think of a few workarounds, like working in the SpawnDefaultToken script to create a token to teleport to. I've tried using several variations of the SpawnDefaultToken script, but I can't find a way to spawn a teleport token and then spawn the caster token and deleting the original caster token. Any help would be greatly appreciated.
1707809588
Gauss
Forum Champion
Hi Timothy,  I suspect there is a reason that simply picking up the token and moving it to the new location is not an acceptable solution?  Just curious if there is a more mundane solution than a script. 
Hey Timothy, You wouldn't even need SpawnDefaultToken if you have another token. You could have any token be the target and then change the source token's top and left properties to those of the target. The only thing Spawn would get you is the ability to delete the target token after. However that said, while I have lots of buttons I don't have one for Misty Step since I tend to agree with Gauss on this. This is one of those situations where the automation doesn't really add much. If Roll20 ever changes and adds a way to target an empty grid location, then I will certainly automate teleports like that but until that day, needing to move a different token to the location and then click something is actually more steps than just moving the actual token.
The only other suggestion I can offer is to use something like SpawnDefaultToken to spawn an invisible token right on top of the token before it moves, and add a 30' aura to the invisible token so that you can see the range where the token can move to.  But otherwise I agree that using a script to move a token 30' is not going to add much value. Another script that might be useful if you're not using it is this scriptlet by TheAaron that places a small marker under the token at the start of the turn order when the turn tracker is open. That can be helpful to make sure that a player doesn't accidentally move too far on their turn (or misty step too far away).
Thanks for the replies, ppl. I don't entirely agree with you that it's an unnecessary automation, if that's the case then all the automation would be unnecessary. Almost my entire game is automated bar this spell(and future spells my players don't have yet and spells out of combat). I understand what you're saying though, the work might exceed the reward. I'm gonna keep this low priority for now, as there are other things to work on.
1707875660
Gauss
Forum Champion
My question is more about what purpose the automation serves other than "being automated".  I am not sure what automation would achieve.  Example of no automation:  Click on token and hold, click "q" key, move token 30 feet, release.  Example of automation (if a destination click were possible):  Click on token, measure 30 feet, click destination.  It saves a keypress at most.  Am I missing something? A problem the automation would solve? If there is a problem perhaps there is a resolution other than automation.
I love automating things. I really do. I do disagree that all automation is equal though. If something has a lot of moving parts, especially those that are tedious or easily forgotten, I love to automate that. Like I said if there was a button and the player could click an empty square and it could check the distance, move the player's token to the square they clicked, and subtract the spell slot, I'm in. 100% I'm in. This one though you get the subtract the spell slot and the distance check because either way right now you still have to move some token to the spot you want to move the original token. I mean if you are really into this idea, I can help you do it. I've done a lot with ScriptCards and moving tokens around. I also use SpawnDefaultToken to bring out spell templates and re-entrant ScriptCards to evaluate all the tokens in the template area. I even wrote a tiny Mod to delete the token after because I couldn't find a small Mod that would delete. ScriptCards still doesn't allow for deletion of anything. ScriptCard will shell out to Spawn and then whisper a button to the sending player to push the button when the token is moved, the re-entry function will get the target token, probably by name, get its top and left properties, modify the source token's top and left properties to match those, and then if you want, the tiny crappy script I wrote could be called similar to this: --?"[&persistTemplate]" -ne "true"|[ --@tclean|_id [&TemplateTID] --]| Here is the quick little script I wrote to cleanup the templates: // Cleanup graphics by id // Useful for things like area templates and spell effects that stop being useful on("ready", function() { const version = '0.0.1'; log('.=> TemplateCleanup v' + version + ' <=.'); on("chat:message",function(msg){ if(msg.type=="api" && msg.content.indexOf("!tclean")==0) { const args = msg.content.split(/\s+--/); if (args.length < 2) { sendChat('TemplateCleanup', '/w gm Must pass a token id to TemplateCleanup. !tclean --id TOKEN_ID'); return; } let option = args[1].split(/\s+/)[0]; if (option != "id") { sendChat('TemplateCleanup', '/w gm Must pass a token id to TemplateCleanup. !tclean --id TOKEN_ID'); return; } let tokenid = args[1].split(/\s+/)[1]; let tok = getObj("graphic",tokenid); if (tok) { tok.remove(); } else { log('TokenCleanup Error: Cannot find token with id of ' + tokenid); return; } } }); }); Then it's just a matter of doing the distance check and the spell deduction which I know you have done previously. Here is even some ScriptCard functions I use to get the token id for the template so that I can get it's properties and then delete it. --:GetTokenIDbyCharacterName|CharacterName;StringVariableForTokenID --~|array;objects:character;GTIDCharArr;[%1%] --?[@GTIDCharArr(length)] -ne 1|[ --&[%2%]|NotFoundError --<| --]| -->GetTokenIDForCharacter|[@GTIDCharArr(0)];GTIDTempVar --&[%2%]|[&GTIDTempVar] --<| --/|GetTokenIDForCharacter returns the token-id for the current page with the player's ribbon for the corresponding character id --:GetTokenIDForCharacter|CharacterID;StringVariableToSetTokenID --~libTokenNum|array;pagetokens;libTokenArr;[*C:playerpageid];char --?[&libTokenNum] -eq 0|&[%2%];NoTokensError --=LastIndex|[&libTokenNum] - 1 --&[%2%]|NotFoundError --%loopCounter|0;[$LastIndex] --&libTID|[*[@libTokenArr([&loopCounter])]:t-id] --&Reps|[*[@libTokenArr([&loopCounter])]:t-represents] --?[&Reps] -eq [%1%]|[ --&[%2%]|[&libTID] --%!| --]| --%| --<| So the GetTokenIDbyCharacterName works ok with SpawnDefaultToken since that also needs to be the character name to summon. So if you have a character name TargetSquare or something you can use that to get the token id on the active page, grab its top and left, modify the source token's top and left, and then use the clean script and it's a teleport. So that is all pretty doable but I think it might even be more clicks but I do love automation so I won't argue if you think it will enhance your game. You know your players and your game way better than me. Let me know if you have any questions about any of that.
Gauss said: My question is more about what purpose the automation serves other than "being automated".  I am not sure what automation would achieve.  Example of no automation:  Click on token and hold, click "q" key, move token 30 feet, release.  Example of automation (if a destination click were possible):  Click on token, measure 30 feet, click destination.  It saves a keypress at most.  Am I missing something? A problem the automation would solve? If there is a problem perhaps there is a resolution other than automation. I think it depends on your goals for automation. I don't do it for efficiency, which is a completely legitimate reason to do it. Instead, I do it for the experience, for both me and my players. Also, because there's so much automation already in my game, giving everything automation codifies the game as a whole. Essentially, it may feel strange when everything is automated except one spell. Also, one of the reasons is, because it can be done, the whole "why climb a mountain" argument. I also think teleportation would be useful in lots of areas of the game, there are a number of spells that teleport etc. And, I know this is presumptuous of me, but I like having code out in the open for others to "borrow" and manipulate for their own purposes, because that's exactly what I do. I suspect that there is so much code out there not being shared and it makes the community feel very small. Don't get me wrong, there are a handful of very helpful, very knowledgeable users, but it feels like those are the only people active. I personally have about 80 spells, attacks and features automated, mostly unshared, so I'm definitely part of the problem. Sorry, this is a bit of a tangent. Anyhoo, I don't expect anyone to do it for me, even if it may be over my head. Although, Joshua may be correct that waiting for the ability to select unoccupied grid squares might be the appropriate course of action.
Here is one possible way to do this with ScriptCards, SpawnDefaultToken, and that TemplateCleanup script I posted above: !scriptcard {{ --/|Misty Step via spawning target token --/|Requires: SC 2.6.2+, SpawnDefaultToken, TemplateCleaner (available in previous post) --/|VARIABLES TO SET --&FeatureName|Misty Step --&SpellLevel|2 --&TargetCharacterName|TeleportTarget --/|Setting MaxRange because for some reason Misty Step's range is Self and the distance it can port is in the description --&MaxRange|30 --&RangeUnits|ft. --#whisper|self --#reentrant|[&FeatureName][*S:character_id] --#sourceToken|@{selected|token_id} --Rfind|[*S:character_id];[&FeatureName];repeating_spell-[&SpellLevel];spellname --?"[*R:spellname]" -eq "NoRepeatingAttributeLoaded"|>DisplayError;[&FeatureName] Not Found;ERROR;[&FeatureName] not found as a level [&SpellLevel] spell;true --?[*S:lvl[&SpellLevel]_slots_expended] -eq 0|>DisplayError;Out of Spells;ERROR;No remaining level [&SpellLevel] spells;true --@forselected|Spawn _offset|2,0 _name|[&TargetCharacterName] --:DisplayPromptButton| --+|Move target token to empty spot within [&MaxRange] [&RangeUnits] and click the button [rbutton][&FeatureName]::ExecTemplate;[&TargetCharacterName][/rbutton] --:Done| --X| --:ExecTemplate|TargetTokenName -->GetTokenIDbyCharacterName|[&reentryval];TargetTID --&MaxSquares|[= [&MaxRange] / 5] --~Distance|distance;[*S:t-id];[*[&TargetTID]:t-id] --?[$Distance] -gt [&MaxSquares]|[ -->DisplayError|Out of Range;ERROR;Target must be within [&MaxRange] [&RangeUnits] of starting location -->DisplayPromptButton| --]| --!t:[*S:t-id]|top:[*[&TargetTID]:t-top]|left:[*[&TargetTID]:t-left] --!a:[*S:character_id]|lvl[&SpellLevel]_slots_expended:-=1 --#whisper|0 --#emoteText|[*S:character_name] turns into mist and reappears nearby... --#leftsub|[*R:spellcastingtime] --+[&FeatureName]|[*R:spelldescription] --@tclean|_id [&TargetTID] --^Done| --:DisplayError|EmoteText;MessageHeader;MessageBody;Fatal(optional) --#emoteText|[%1%] --+[%2%]|[%3%] --?"[%4%]X" -ne "X"|Done --<| --:GetTokenIDbyCharacterName|CharacterName;StringVariableForTokenID --~|array;objects:character;GTIDCharArr;[%1%] --?[@GTIDCharArr(length)] -ne 1|[ --&[%2%]|NotFoundError --<| --]| -->GetTokenIDForCharacter|[@GTIDCharArr(0)];GTIDTempVar --&[%2%]|[&GTIDTempVar] --<| --/|GetTokenIDForCharacter returns the token-id for the current page with the player's ribbon for the corresponding character id --:GetTokenIDForCharacter|CharacterID;StringVariableToSetTokenID --~libTokenNum|array;pagetokens;libTokenArr;[*C:playerpageid];char --?[&libTokenNum] -eq 0|&[%2%];NoTokensError --=LastIndex|[&libTokenNum] - 1 --&[%2%]|NotFoundError --%loopCounter|0;[$LastIndex] --&libTID|[*[@libTokenArr([&loopCounter])]:t-id] --&Reps|[*[@libTokenArr([&loopCounter])]:t-represents] --?[&Reps] -eq [%1%]|[ --&[%2%]|[&libTID] --%!| --]| --%| --<| }} Right now it doesn't allow upcasting or any sort of limited use option, it's hardcoded to use a 2nd level spell slot which is obviously not ideal but it's a first draft of how you might go about this. It requires a character with a default token you want to use as a target for the Misty Step. This variable sets it --&TargetCharacterName. The range is set in a variable right now rather than parsing the description since Misty Step's spellrange is Self. It will check for the presence of the Misty Step spell, check if there are remaining level 2 spell slots, shell out to SpawnDefaultToken, and prompt the user to hit a button when the target token is moved to the location. Upon resuming, the script will get the target token id by the character name, check the distance from the source token (this currently assumes 1 square tokens (additional work would need to be done to account for larger tokens), re-prompt the user if distance is greater than max range, if within range will change the top and left token properties of the source token to match those of the target token, deduct the level 2 spell slot, display the spell description, and shell out that TemplateCleanup script (pasted in prior post) to delete the target template. There are probably other ways to accomplish all of those things but that is one way. Let me know if you have any questions.
1707935254

Edited 1707939297
I was just about to ask for some help on resolving an issue for this same concept.  I actually currently have a macro for this that uses FX and SpawnDefaultToken, though it is purely a visual effect. It's stored as an ability in the character's sheet, and marked as token action so that the token must be selected when used. You could pair it with ChatSetAttr if you need it to deduct spell slots.  /fx burn-smoke @{selected|token_id} !Spawn {{ --name| @{selected|character_name} <If the @{selected} calls don't want to work, just replace them with the name of the character using it.> --offset|?{Horizontal displacement? (in squares)| None,0| Left 1,-1| Left 2,-2| Left 3,-3| Left 4,-4| Left 5,-5| Left 6,-6| Right 1,1| Right 2,2| Right 3,3| Right 4,4| Right 5,5| Right 6,6},?{Vertical displacement? (in squares)| None,0| Up 1,-1| Up 2,-2| Up 3,-3| Up 4,-4| Up 5,-5| Up 6,-6| Down 1,1| Down 2,2| Down 3,3| Down 4,4| Down 5,5| Down 6,6} --bar1|@{selected|hp}/@{selected|hp|max} --bar2|@{selected|ac}/- --fx|burn-smoke --expand| 20,50 --resizeSource| 0,0 }} Things it does that are good: — Visual effects — Avoids needing a target token to move to because it bases the movement off of the source  token (caster)      — When run, it uses queries to ask for horizontal and vertical displacement from the source token, instead of direct distance      — Works well with the '--offset' feature of Spawn, which requires X,Y coordinates of the displacement  — Uses current and max hp from the character instead of the default token settings      — Spawn can sometimes overwrite the values and change them on the character sheet, this syntax avoids that — Animates both the new token arriving and the source token being deleted  Things it does that are unwanted:  — It will remove the source token from the initiative order if combat is happening I'm currently investigating a way, via the Meta Script Toolbox scripts, to automatically restore the initiative value for the new token, likely by storing the source token's intiative value and applying it to the new token once it has spawned. If that won't work, at least a quick way to report it to chat prior to being deleted so it can quickly be re-entered, either manually or via a chat button or similar. If anyone has any ideas on that front, feel free to suggest them, I am a complete novice with the Meta Toolbox scripts.  The '--offset' coordinates queries could be edited to apply for teleportation spells with more distance like Thunder Step, or less distance, like Blink, though if the distance gets too much larger, it would make more sense to leave the queries open-ended for manual entry instead of a writing a long list of every coordinate increment square like it is currently set for the constraints of Misty Step. If you need help with that, let me know.  Anyways, I hope that helps with your initial idea!
I'm curious as to why you chose to go with SpawnDefaultToken for this instead of something like TokenMod? Wouldn't TokenMod keep the token's settings and in the initiative order and you can set the position with your roll queries? Wrap that around your /fx calls and it would seem like that would solve your initiative order issue.
Joshua N. said: I'm curious as to why you chose to go with SpawnDefaultToken for this instead of something like TokenMod? Wouldn't TokenMod keep the token's settings and in the initiative order and you can set the position with your roll queries? Wrap that around your /fx calls and it would seem like that would solve your initiative order issue. Ultimately, it boils down to personal preference, but here's the reasoning:  I tried using both variations, and currently do also have a functioning TokenMod version that accomplishes ultimately the same thing. The difference is the visual presentation. When I tried it with TokenMod, I tried using a combination of the !Delay and !CFX scripts in order to delay the visual effects I wanted to occur in a sequence, instead of simultaneously. I ran into problems of the console crashing when using those two scripts in combination. I had previously used those two scripts to great effect in my campaign, but couldn't fix the issue, and it broke the previous visual effects I had set up for other spells and features, so I dropped them entirely. I reached out to the forums for assistance, but nothing has really come of it yet.  The SpawnDefaultToken version above, and use of a plain old /fx command accomplishes what I want visually, and though it does create a new issue, it's not one that ultimately bothers me. I've already figured out using Muler to store the original initiative value, now I'm just working on calling it to the tracker.  Is it like using a fire hose when a garden hose would work? Sure, but I'm learning more about the API's and the many ways to use them as I figure it out. 
1707992859

Edited 1708001756
The easiest way I can think of to maintain the turnorder, or more accurately add it after it is deleted, would be to use an attribute on the character sheet. Everything I use is custom and uses ScriptCards, so I can add a value to an attribute in the initiative macro that saves as the last initiative roll. Then  I can call to it in the misty step macro and add it back into the turnorder using ScriptCards. And, not to be combative, but to more legitimize this teleportation thing we have going on; my player's character leveled, switched misty step for another spell and took Thunder Step. Thunder Step does 3d10 damage to surrounding creatures from it's point of origin. That's a lot of hp management I get to skip and have a cool teleportation animation. You never know when one thing might lead to another, like NASA and velcro... EDIT: Hmm... having trouble figuring out a way to grab the new token id, trying with selectmanager. Keeps just giving me the old token_id
Timothy did you try my Misty Step ScriptCard? It can modified to also do the damage for Thunder Step.
1708008348

Edited 1708008437
I did, I can't get it to work though. So, I've set up the target token, it spawns fine but when I click on the Misty Step button, the caster token moves into the upper left corner of the map.  I've had another thought(so don't expect much), but wouldn't an easier way to do this be to use tokenmod to send the token to the GM layer, use token mod to move the token to the right square, and then use tokenmod bring it back to the token layer? It avoids having to delete anything, or create new tokens at all. EDIT: Joshua, just noticed I'm getting the error "TokenCleanup Error: Cannot find token with id of NotFoundError" in the output console.
So the GetTokenIDbyCharacterName isn't finding the token. Is your Spawned token set with the same name as the linked character? This variable  --&TargetCharacterName|TeleportTarget I am assuming that's set correctly since the token spawns for you. The lookup is done on the page with the player ribbon for graphic objects that have represents set to a character. That's how I have my templates setup with a default token that also represents that character. If your Spawn's default token isn't setup like that, you'll need to modify the lookup accordingly to match your setup. As for your idea, I'm not sure what you mean by using token mod in that way. Certainly token mod can move tokens to layers and change the top and left coordinates but how are you determining what the right square is? I don't really see a need for token mod in the ScriptCards setup. ScriptCards can do the right square just fine if the target token is found. I tend to think of a token mod solution as a different way to accomplish this and not really needed in the ScriptCards setup. If you want to describe your setup, I can help modify the lookup. Also if you have the character id of your target you can use that with the GetTokenIDForCharacter function and bypass the lookup by name.
Well, tokenmod has the move function which has degrees and distance. I know ScriptCards can affect tokens to some degree, like bars etc. But not move or change layers, definitely could be wrong about that, though.  You could get input from either dropdown menus or reentry buttons and simply move the token on the gm layer, as long as the players don't see it, it'll look like teleportation.
ScriptCards can move layers and move tokens. I use it all the time to do that. My StartBattle ScriptCard lists every NPC token and includes buttons to move them to the object layer or gmlayer. I also move tokens like in the Misty Step script by changing their top and left token properties. The token moves. Like I said, if you want to get input from Roll Queries like Rocklobster posted, TokenMod will work. The roll queries would even work in a ScriptCard option. If you want to move squares with a token mod script that would work too but it will also work within a scriptcard. !scriptcard {{ --/|Prompt for token movements --&SquarePixels|70 --#sourceToken|@{selected|token_id} --&Horizontal|?{Horizontal displacement? (in squares)| None,0| Left 1,-1| Left 2,-2| Left 3,-3| Left 4,-4| Left 5,-5| Left 6,-6| Right 1,1| Right 2,2| Right 3,3| Right 4,4| Right 5,5| Right 6,6} --&Vertical|?{Vertical displacement? (in squares)| None,0| Up 1,-1| Up 2,-2| Up 3,-3| Up 4,-4| Up 5,-5| Up 6,-6| Down 1,1| Down 2,2| Down 3,3| Down 4,4| Down 5,5| Down 6,6} --&leftDelta|[= [&Horizontal] * [&SquarePixels]] --&topDelta|[= [&Vertical] * [&SquarePixels]] --+Current|Left:[*S:t-left] Top:[*S:t-top] --+New|Left:[=[*S:t-left] + [&leftDelta]] Top:[=[*S:t-top] + [&topDelta]] --!t:[*S:t-id]|top:[=[*S:t-top] + [&topDelta]]|left:[=[*S:t-left] + [&leftDelta]] }} and if you want change a token's layer you can. This is a simple example that will toggle the selected token between the gmlayer and the object layer: !script {{ --/|Toggles token between GM layer and Object layer --#sourceToken|@{selected|token_id} --?"[*S:t-layer]" -eq "gmlayer"|&newLayer;objects|&newLayer;gmlayer --!t:[*S:t-id]|layer:[&newLayer] }} So you can modify the properties of a token within a ScriptCard if you want. TokenMod can do it as well. I just wanted to cleanup tokens rather than moving them to the gmlayer or off the grid which is why I wrote that little TemplateCleanup script. Like I said, there are multiple ways to move a token. If you prefer TokenMod, great. If you want ScriptCards to do it, it can as well. I just presented that Misty Step script as one possible way and it works. Sounds like it would work for you as well if the target token id gets found, either by the default token being linked to the Spawn character or by supplying the Spawn character's character id and doing the lookup with it. Whichever works for your game is best but I just wanted to show that ScriptCards can also use those Roll queries to move tokens if you prefer that method.
Dang, ScriptCards is takin over. I've got TokenMod to move the token to the gmlayer, then move spaces and then move it back to the object layer. But, it seems to be doing it out of order, if I just move it to the gmlayer it works, but if I move it to GM and then move it back to Object it doesn't appear to actually move it. As if it does it in a split second. I'll try scriptcards and see what happens.
Dang, I mean it works to move the token, but I can't get it to disappear on the gmlayer first and reappear after it moves. If I have two layer movements, nothing seems to happen. The token moves, but not in a z position, at least not noticeably. Like it's z position moves and then moves back before the token actually moves.
1708017812

Edited 1708022309
If you use delays it does kinda work. I just can't get the FX to work, but they barely work for GM's for some reason. !scriptcard {{ --/|**********Customizable Variables*************** --/|Formatting --#overridetemplate|mydnd --#dicefontsize|5.0em --#rollHilightColorNormal|#d3b63b --#rollHilightColorCrit|#3afc7a --#rollHilightColorFumble|#ff5456 --#dicefontcolor|Black --#Debug|0 --:DoSetup| --#sourceToken|@{selected|token_id} --&InitRoll|@{selected|init_roll} --&SpellLevel|3 --&SpellName|Thunder Step --&SpellRadius|2 --=SpellSaveDC|@{selected|spell_save_dc} --&SpellSaveType|Constitution --=FeatDamage|0 --&FeatDamageType|[FEAT] --Rfind|@{selected|character_id};[&SpellName];repeating_spell-[&SpellLevel];spellname --#emoteText|[*S:character_name] Casts [*R:spellname]. --#title|[*R:spellname] [*R:innate] --#leftsub|@{selected|character_name} (@{selected|caster_level}) --?[*R:spelllevel] -eq cantrip|&spllvl;cantrip --?[*R:spelllevel] -eq 1|&spllvl;1st-level --?[*R:spelllevel] -eq 2|&spllvl;2nd-level --?[*R:spelllevel] -eq 3|&spllvl;3rd-level --?[*R:spelllevel] -eq 4|&spllvl;4th-level --?[*R:spelllevel] -eq 5|&spllvl;5th-level --?[*R:spelllevel] -eq 6|&spllvl;6th-level --?[*R:spelllevel] -eq 7|&spllvl;7th-level --?[*R:spelllevel] -eq 8|&spllvl;8th-level --?[*R:spelllevel] -eq 9|&spllvl;9th-level --#rightsub|[i][&spllvl] [*R:spellschool][/i] --+Casting Time:|[*R:spellcastingtime] --+Range:|[*R:spellrange] --+Target:|[*R:spelltarget] --&zSCV|V --?"[*R:spellcomp_v]" -inc "v=1"|ENDSCV --&zSCV| --:ENDSCV| --&zSCS|S --?"[*R:spellcomp_s]" -inc "s=1"|ENDSCS --&zSCS| --:ENDSCS| --&zSCM|M --?"[*R:spellcomp_m]" -inc "m=1"|ENDSCM --&zSCM| --:ENDSCM| --?"[*R:spellcomp_m]" -ninc "m=1"|&materials;|&materials;([*R:spellcomp_materials]) --+Components:|[&zSCV][&zSCS][&zSCM] [&materials] --+Duration:|[*R:spellduration] --+|[*R:spelldescription] --~Len|string;length;[*R:spellathigherlevels] --?[$Len] -le 5|END_HV_CHECK --+|[b][i]At Higher Levels.[/i][/b][*R:spellathigherlevels] --:END_HV_CHECK| --&Horizontal|?{Horizontal displacement? (in squares)| None,0| Left 1,-1| Left 2,-2| Left 3,-3| Left 4,-4| Left 5,-5| Left 6,-6| Left 7,-7| Left 8,-8| Left 9,-9| Left 10,-10| Left 11,-11| Left 12,-12| Left 13,-13| Left 14,-14| Left 15,-15| Left 16,-16| Left 17,-17| Left 18,-18| Right 1,1| Right 2,2| Right 3,3| Right 4,4| Right 5,5| Right 6,6| Right 7,7| Right 8,8| Right 9,9| Right 10,10| Right 11,11| Right 12,12| Right 13,13| Right 14,14| Right 15,15| Right 16,16| Right 17,17| Right 18,18} --&Vertical|?{Vertical displacement? (in squares)| None,0| Up 1,-1| Up 2,-2| Up 3,-3| Up 4,-4| Up 5,-5| Up 6,-6| Up 7,-7| Up 8,-8| Up 9,-9| Up 10,-10| Up 11,-11| Up 12,-12| Up 13,-13| Up 14,-14| Up 15,-15| Up 16,-16| Up 17,-17| Up 18,-18} Down 1,1| Down 2,2| Down 3,3| Down 4,4| Down 5,5| Down 6,6| Down 7,7| Down 8,8| Down 9,9| Down 10,10| Down 11,11| Down 12,12| Down 13,13| Down 14,14| Down 15,15| Down 16,16| Down 17,17| Down 18,18} --/X| --/|****************DO NOT CHANGE****************** --&CasterToken|@{selected|token_id} --~|array;pagetokens;AllTokens;[&CasterToken] --/|*******************Main************************ -->IsWarlock| -->RollDamage| -->OutputText| --%CurrentToken|foreach;AllTokens --?[&CurrentToken] -eq [&CasterToken]|% --&CharName|[*[&CurrentToken]:character_name] --?[&CharName(length)] -le 0|% -->GetTargetDistance|[&CurrentToken] -->GetTargetAngle|[&CurrentToken] --?[$TargetDistance] -gt [&SpellRadius]|% --?"[*[&CurrentToken]:t-statusmarkers]" -ninc advantage -and "[*[&CurrentToken]:t-statusmarkers]" -ninc disadv|>MakeSavingThrow;[&CurrentToken];1d20;Normal --?"[*[&CurrentToken]:t-statusmarkers]" -inc disadv|>MakeSavingThrow;[&CurrentToken];2d20kl1;Disadvantage --?"[*[&CurrentToken]:t-statusmarkers]" -inc advantage|>MakeSavingThrow;[&CurrentToken];2d20kh1;Advantage --?[$TargetSave] -ge [$SpellSaveDC]|>SetSaveBool;Succeeds --?[$TargetSave] -lt [$SpellSaveDC]|>SetSaveBool;Fails --C[&SaveBool]|Fails:>CaseSaveFails;[&CurrentToken]|Succeeds:>CaseSaveSucceeds;[&CurrentToken] -->ReportDamage| -->ApplyDamage|[&CurrentToken];1;-[$TotalDamage] --*|[hr] --%| --&SquarePixels|70 --&leftDelta|[= [&Horizontal] * [&SquarePixels]] --&topDelta|[= [&Vertical] * [&SquarePixels]] --vtoken|[*S:t-id] nova-smoke --!t:[*S:t-id]|layer:gmlayer --w1:!t:[*S:t-id]|top:[=[*S:t-top] + [&topDelta]]|left:[=[*S:t-left] + [&leftDelta]] --w2:!t:[*S:t-id]|layer:objects --w2:vtoken|[*S:t-id] burn-smoke --w2:vtoken|[*S:t-id] ping moveall --X| --:IsWarlock| --?"[*S:level]" -le 2|=SlotLevel;1 --?"[*S:level]" -eq 3 -or "[*S:level]" -eq 4|=SlotLevel;2 --?"[*S:level]" -eq 5 -or "[*S:level]" -eq 6|=SlotLevel;3 --?"[*S:level]" -eq 7 -or "[*S:level]" -eq 8|=SlotLevel;4 --?"[*S:level]" -ge 9|=SlotLevel;5 --=DamageDice|[$SlotLevel] --=SlotsTotal|0 --=SlotsExpended|[*S:lvl[$SlotLevel]_slots_expended] --?[$SlotsExpended.Raw] -eq [$SlotsTotal.Raw]|[ -->NoSlotsLeft| --]|[ --?[$SlotLevel] -eq 0|NoSlot --=SlotsLeft|[$SlotsExpended] - 1 --!a:[*S:character_id]|lvl[$SlotLevel]_slots_expended:[$SlotsLeft] --]| --<| --/|****************Subroutines******************** --:RollDamage| --=DamageDice|[$SlotLevel]d10 --=Damage|[$DamageDice] + [$BonusDamage] -->DieLoop| --=DoubleDamage|[$Damage] * 2 --=HalfDamage|[$Damage] \ 2 --=QuarterDamage|[$Damage] \ 4 --<| --:DieLoop| --&DicePerRow|4 --&DieCounter|1 --&AllDice|[c][t width=100%][tr] --%RollC|1;[$DamageDice.RollCount] --&AllDice|+[td height=60px][d10][$DamageDice.RolledDice([&RollC])][/d10][/td] --?[= [&DieCounter] % [&DicePerRow] ] -eq 0|&AllDice;+[/tr][tr] -->IncrementCounter|DieCounter --%| --&AllDice|+[/tr][/t][/c] --+|[c][b]DC [$SpellSaveDC.Text] [&SpellSaveType] Saving Throw[/b][/c] --+|[&AllDice] --<| --:IncrementCounter| --&[%1%]|[= [&[%1%]] + 1] --<| --:OutputText| --+|[c][b]Total Damage[F:Contrail One:22][$DamageDice][/F][/b][/c] --+|[c][b]Level [$SlotLevel] Slots Left: [$SlotsLeft][/b][/c] --?[$BonusDamage] -ne 0|>OutputBonusDamage --<| --:OutputBonusDamage| --=AdditionalDamage|[$BonusDamage] + [&BonusDamageType] --+Bonus Damage|[$AdditionalDamage] --<| --:GetTargetDistance| --~TargetDistance|distance;@{selected|token_id};[%1%] --<| --:GetTargetAngle| --~TargetAngle|math;angle;@{selected|token_id};[%1%] --~TargetAngleRounded|math;round;[&TargetAngle] --<| --:MakeSavingThrow| --=TargetSave|[%2%] + [*[%1%]:constitution_save_bonus] --*[*[%1%]:character_name]|[&SpellSaveType] Save [$TargetSave] --*Roll|[%3%] --<| --:SetSaveBool| --&SaveBool|[%1%] --<| --:CaseSaveFails| --*|Save Fails! --@token-mod|_ignore-selected _ids [%1%] -->CalculateDamage|[$Damage];Normal --?"[*[%1%]:npc_vulnerabilities]" -inc [&DamageType]|>CalculateDamage;[$DoubleDamage];Vulnerable! --?"[*[%1%]:npc_resistances]" -inc [&DamageType]|>CalculateDamage;[$HalfDamage];Resistant! --?"[*[%1%]:npc_immunities]" -inc [&DamageType]|>CalculateDamage;0;Immune! --<| --:CaseSaveSucceeds| --*|Save Suceeds! -->CalculateDamage|[$HalfDamage];Normal --?"[*[%1%]:npc_vulnerabilities]" -inc [&DamageType]|>CalculateDamage;[$Damage];Vulnerable! --?"[*[%1%]:npc_resistances]" -inc [&DamageType]|>CalculateDamage;[$QuarterDamage];Resistant! --?"[*[%1%]:npc_immunities]" -inc [&DamageType]|>CalculateDamage;0;Immune! --<| --:CalculateDamage| --=TotalDamage|[%1%] --&CreatureResist|[%2%] --<| --:ReportDamage| --*Resistance|[&CreatureResist] --*|Creature takes [$TotalDamage] [&DamageType] Damage --<| --:ApplyDamage| --@token-mod|_ignore-selected _ids [%1%] _set bar[%2%]_value|[%3%] --<| }}
In fact thinking about it, Rocklobster this might be a ScriptCard version of what you are doing !scriptcard {{ --/|Prompt for token movements --&SquarePixels|70 --#sourceToken|@{selected|token_id} --&Horizontal|?{Horizontal displacement? (in squares)| None,0| Left 1,-1| Left 2,-2| Left 3,-3| Left 4,-4| Left 5,-5| Left 6,-6| Right 1,1| Right 2,2| Right 3,3| Right 4,4| Right 5,5| Right 6,6} --&Vertical|?{Vertical displacement? (in squares)| None,0| Up 1,-1| Up 2,-2| Up 3,-3| Up 4,-4| Up 5,-5| Up 6,-6| Down 1,1| Down 2,2| Down 3,3| Down 4,4| Down 5,5| Down 6,6} --&leftDelta|[= [&Horizontal] * [&SquarePixels]] --&topDelta|[= [&Vertical] * [&SquarePixels]] --&newLeft|[=[*S:t-left] + [&leftDelta]] --&newTop|[=[*S:t-top] + [&topDelta]] --vtoken|[*S:t-id] burn-smoke --w1:!t:[*S:t-id]|top:[&newTop]|left:[&newLeft] --w1:vtoken|[*S:t-id] burn-smoke }} Where it prompts for the horizontal and vertical change, does the burn-smoke vfx, waits 1 second, moves the token and does a burn-smoke at the new location. This would keep the token in the turnorder as well.
1708018729

Edited 1708018968
Yeah, if you add in the layer changes with the delays it works. I don't see the FX go off. But, sometimes they just don't work for me anyway. --vtoken|nova-smoke @{selected|token_id} --w1:!t:[*S:t-id]|layer:gmlayer --w2:!t:[*S:t-id]|top:[=[*S:t-top] + [&topDelta]]|left:[=[*S:t-left] + [&leftDelta]] --w3:!t:[*S:t-id]|layer:objects --w4:vtoken|burst-smoke @{selected|token_id} EDIT: The FX not showing up could be something to do with the rest of the macro with it maybe?
Hmm. In the scriptcard I pasted I see the vfx go off in both locations. I don't have many ScriptCards with vfx added in but they work. Although that said, they can lag a great deal at times.
No idea why it wasn't working, but I changed it from burst to burn and nova and it works now? I'll update my above code.
1708019887

Edited 1708022040
Yup, it works perfectly now with these delays.  --vtoken|[*S:t-id] nova-smoke --!t:[*S:t-id]|layer:gmlayer --w1:!t:[*S:t-id]|top:[=[*S:t-top] + [&topDelta]]|left:[=[*S:t-left] + [&leftDelta]] --w2:!t:[*S:t-id]|layer:objects --w2:vtoken|[*S:t-id] burn-smoke --w2:vtoken|[*S:t-id] ping moveall
1708792981

Edited 1708800924
Pak
Pro
Tim. I've been looking around for a Misty Step script myself and have seen a few options, but none that really worked the way I wanted. I basically use smartAOE API to generate a target token. The user then moves the target token to a new location and then clicks a token action ability to complete the teleport and the trigger token disappears! There is a little bit of prework to make it work and involves 2 different Scriptcards. (A) 1 scriptcard code gets assigned to a "targerting Mule" (see steps below). (B) the other can be added to your players character sheet as a clickable token action ability. Summary: (STEP 1) You'll need the following API's installed: 1- TokenMod     NOTE: Not sure if it matters, but I have "Players can use --ids:" toggled on in for TokenMod configuration 2- ScriptCards 3- MetaScriptToolbox 4- SmartAoE (STEP 2) 1- Create a token mule to use as your Misty Step "target" token. smartAOE installs its own targeting token/character sheet (named AoEControlToken) with pre-generated abilities already embedded in the tokens character sheet. You could use that, but I made my own since I will be adding my own ability and token action to it. Whatever name you give the new token needs to match the name referenced in the 1st smartcard script we use. NOTE: If you create your own token/character mule, make sure players can see/edit/control the character sheet. Also make sure the target token has vision turned on. 2- For this new targeting mule (or the AoEControlToken), create an ability and paste scriptcard code "A" (shown below) into the new ability and select "Show as token action" NOTE: both code "A" and code "B" require some tweaking depending on user preferences. Example, code "A" includes a line for playing audio. In my case, the audio being played is called "sizzle". You can change this to your preferred sound effect or just remove the line. (STEP 3) Create a macro your users can run or assign a macro to their specific character sheet (as an ability) using code "B". S elect "Show as token action" so your players can run the code. This code will actually summon the targeting token and turn on aura 1 with 30ft radius. And that's it... To run, the user just clicks their token ability to launch the target token script. They choose their spell slot to use. Then they move the token to the spot they want to teleport to. Then they click the token action on the trigger token to perform the teleport. And the teleport token disappears. <<< CODE BELOW >>> Code "A": Line 11 will need to be configured or removed by you depending on the sound you want to play. In my case, I'm playing a sound called "sizzle". !scriptcard  {{  --#sourceToken|@{selected|token_id} --#hideTitleCard|1 --#emoteState|1 --:GET COORDINATES| --=SeltopCord|[*S:t-top] --=SelleftCord|[*S:t-left] --:PLAY SOUND| --a|sizzle --:GET CASTER TOKEN ID| --&TokenID|[*S:caster_ID] --:VISUAL EFFECTS| --vtoken|[&TokenID] burst-frost --vtoken|@{selected|token_id} burst-frost --w|1 --:MOVE CASTER TOKEN AND REMOVE AURA| --@token-mod|_ids [&TokenID] _set top|[*S:t-top] left|[*S:t-left] _set aura1_radius|!30 --:DELETE TARGET TOKEN| --@forselected|smarttrigger --+|You used your bonus action to Misty Step! }} Code "B": Line 11 of this scriptcard is the actual smartAOE command. You will need to change the _controlTokName to match the name of the token mule you created in step 2 above. In my case, the token mule is named "SpellToken". !scriptcard  {{  --#title|Misty Step --#sourceToken|@{selected|token_id} --#leftsub|1 Bonus Action --#rightsub|2nd-Level Conjuration --#emoteText|[*S:character_name] Casts Misty Step. --#emotebackground| #ffffff -->WhatSpellSlot| --:SPAWN MISTY STEP TOKEN USING SMARTAOE API| --@forselected|smartaoe _title|Misty Step _instant|1 _radius|0ft _aoetype|circle, float _aoeColor|#00000000 _aoeOutlineColor|#00000000 _gridcolor|#00000000 _controlTokName|SpellToken _autoapply|1 _noSave|TRUE --:GET AND STORE CASTER TOKEN ID ONTO MISTY STEP TOKEN FOR LATER USE| --&TokenID|[*S:t-id] --!a:@{SpellToken|character_id}|!caster_ID:[&TokenID] --:TURN ON 30FT RADIUS FOR REFERENCE| --@forselected|token-mod _set aura1_radius|!30 aura1_color|#9fc5e8 --X| --:WhatSpellSlot|     --+At what level is the spell being cast?|     --+|[c][rbutton]2::WhatLVL;2[/rbutton] [rbutton]3::WhatLVL;3[/rbutton] [rbutton]4::WhatLVL;4[/rbutton] [rbutton]5::WhatLVL;5[/rbutton] [rbutton]6::WhatLVL;6[/rbutton] [rbutton]7::WhatLVL;7[/rbutton] [rbutton]8::WhatLVL;8[/rbutton] [rbutton]9::WhatLVL;9[/rbutton][/c]   --X| --:WhatLVL|     --=SlotLevel|[&reentryval]     --=SlotsTotal|0     --=SlotsExpended|[*S:lvl[$SlotLevel]_slots_expended]     --?[$SlotsExpended.Raw] -eq [$SlotsTotal.Raw]|[ -->NoSlotsLeft| --]|[     --?[$SlotLevel] -eq 0|NoSlot     --=SlotsLeft|[$SlotsExpended] - 1 --!a:[*S:character_id]|lvl[$SlotLevel]_slots_expended:[$SlotsLeft]     --+|Level [$SlotLevel] Slots Left: [$SlotsLeft]     --<| --X| --:NoSlot|   --X| --:NoSlotsLeft|   --+|[*S:character_name] has no level [$SlotLevel.Total] spell slots available.   --X|NoSlotsLeftStop }}
1708805196

Edited 1708805215
David M.
Pro
API Scripter
Neat! Note that since you are already using SmartAoE, you could use its --resource command to take care of all your spell slot testing/reduction. SmartAoE will whisper you the cost and remaining value of the resource (spell slots in this case), and will tell you if you don't have enough resources (preventing the control token being spawned). Then, moving the spell slot selection to a Roll20 query will prevent having to move the mouse all the way into the chat window to click an rbutton.  This would make your macro code "B" a lot shorter. Note I also changed the aura change to direct object modification instead of farming it out to token-mod, but that is just a personal preference. Modified Code "B" !scriptcard  {{    --#title|Misty Step   --#sourceToken|@{selected|token_id}   --#leftsub|1 Bonus Action   --#rightsub|2nd-Level Conjuration   --#emoteText|[*S:character_name] Casts Misty Step.   --#emotebackground| #ffffff   --:TURN ON AURA1|   --!t:[*S:t-id]|aura1_radius:30|aura1_color:#9fc5e8      --:SPAWN MISTY STEP TOKEN USING SMARTAOE API| SmartAoE will check for remaining spell slots of the chosen level automatically and prevent execution if slots are expended   --@forselected|smartaoe _title|Misty Step _controlTokName|SpellToken _aoeColor|#00000000 _aoeOutlineColor|#00000000 _gridcolor|#00000000 _instant|1 _radius|0ft _resource|lvl?{Cast at what level?|2|3|4|5|6|7|8|9}_slots_expended,1,Level ?{Cast at what level?} Slots }}  
Thanks David! I knew one of you wizards would find a way to streamline the code!!! The only "bug" handling the spell slots with smartAoE is the 30ft aura still turns on and stays on even if smartAoE doesn't detect enough spell slots. SmartAoE doesn't spawn the trigger but the scriptcard still runs the aura toggle.
1708807694
David M.
Pro
API Scripter
Ah. true. The two scripts can't communicate with each other, so that wouldn't be possible. Sounds like the scriptcard method for spell slots has its advantages! At some point I should probably add an aura option to SmartAoE that gives an indicator of spell range. 
I really like this way of handling it, Pak. It's a nice visual user friendly way of doing it. If I might suggest something; your token floats over to new location. If you incorporate the method that Joshua and I worked on, which puts the token on the gmlayer, moves it, and then puts it back on the object layer, it'll look like it teleported to the player. So, something like this for your Code "A" !scriptcard {{ --#sourceToken|@{selected|token_id} --#hideTitleCard|1 --#emoteState|1 --:GET COORDINATES| --=SeltopCord|[*S:t-top] --=SelleftCord|[*S:t-left] --:PLAY SOUND| --a|sizzle --:GET CASTER TOKEN ID| --&TokenID|[*S:caster_ID] --:VISUAL EFFECTS| --w2:vtoken|[&TokenID] burst-frost --w2:vtoken|@{selected|token_id} burst-frost --:MOVE CASTER TOKEN AND REMOVE AURA| --!t:[&TokenID]|aura1_radius:0 --!t:[&TokenID]|layer:gmlayer --w1:!t:[&TokenID]|top:[*S:t-top]|left:[*S:t-left] --w2:!t:[&TokenID]|layer:objects --:DELETE TARGET TOKEN| --@forselected|smarttrigger --+|You used your bonus action to Misty Step! }}
Timothy, THAT'S AWESOME!  Perfect effect! Great suggestion!