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

Script to switch map levels and retain initiative

I've newly subscribed to Pro and was wondering if there's an API script that allows you to switch between floors or levels of a dungeon and still keep the party's initiative rolls.  The dungeon map we are in has quite a few floors and I'd rather not have my large party have to manually re-enter their initiative rolls every time they walk up and down some stairs. Thanks for your help.
May be you should have a larger map with all the levels on it separated by dynamic lighting lines, and just teleport them from level to level on the same map, using teleport script. 
Try Combat Master, among other things it seems to keep the turn order from map page to map page.
For the GM the turn order contains all tokens - regardless of page and layer. For the player the turn order shows the token on the token layer of the current player page. If you test a page change as GM, it looks like the initiative order is maintained (as they are still visibile in the turn order), this is not the case however. As the tokens are in the turnorder (and not the characters to which the tokers refer)  it is not a trivial to main the turnorder when changing pages/maps. The suggestion of Lionel is the one i always use.
The trouble is we are playing a pre-made adventure, Curse of Strahd.  So I can't easily change the map.  Castle Ravenloft is super complicated.
1657990034
The Aaron
Roll20 Production Team
API Scripter
Turn Order is tied to tokens, not characters, as mentioned above.  Mod Scripts can't create tokens that use Marketplace art directly, so the hardest case to handle would be switching map pages, but there's no tokens for the characters that are in the turn order already.  I can think of several ways of handling that from a script, but let me first as what your process is for moving between maps? 1) are you using a script that moves tokens to the new page (that could only work with user library tokens). 2) are you copy/pasting tokens to the new map page and moving the player ribbon? And another question: is it sufficient that the players have a turn entry, or do you need it to be tied to their character's token?  (I'm thinking AddCustomTurn for player turns would solve this issue)
1657991151
The Aaron
Roll20 Production Team
API Scripter
If you install AddCustomTurn and give your players these macros: Initiative !act 0 [[@{selected|initiative_style}+@{selected|initiative_bonus}@{selected|pbd_safe}]] --@{selected|token_name} Drop Initiative !dct @{selected|token_name} It will roll them in to the Turn Order with a custom turn named after their selected token and roll initiative as their character (assuming Roll20 5e Sheet).  The second will let them select their token and remove it from the turn order. Custom Turns show up regardless of page, so they will still have their turn entry when you move between pages. The drawbacks are: Other scripts won't see these as token turns, so things like Combat Master or TurnMarker1 won't be able to do the things they do. Some scripts (GroupInitiative) won't sort the turn order correctly with them. You won't be able to hover the entry and see the token associated with it.  Players won't be able to adjust the value directly There could still be other Mod Script solutions, but this is the one I would recommend if the drawbacks aren't a problem for you.
Hmm...that's an interesting idea and something I'll keep in mind as a backup, though I was planning on using TurnMarker1 and maybe Combat Master as well. As another possibility, is it possible to write a small script that would copy the character's current initiative into some variable in the character sheet? Then after the map switch, maybe a second script could read this info and use it to recreate the turn order list.  Is that sort of thing possible with the available API commands?  I'm familiar with scripting in general (I've written a lot of Python in the past) but I haven't done anything with the roll20 API.
Perhaps not in the character sheet, but there is game-global nonvolatile storage available in the state object.  This is where Mod authors can put data which needs to be preserved between invocations of a game.
1658188553
The Aaron
Roll20 Production Team
API Scripter
So, if you go back and describe what your process is for moving between maps, I think I can throw something together that would do what you want.  Here's what I'd propose: When a player is moved to a different map... Find all characters they control in the turn order... Find tokens representing that character on the new page... Add the found tokens with the same info and remove the old one. Could additionally perform the same logic when a token is added to a page that the player is on, but the character in the turn order is not on that page.
1658209854

Edited 1658211185
Oh much appreciated sir Aaron. My process is quite simple, I have the character and npc (tag along, pets, etc.) tokens already made. I copy paste the character+npc tokens from level 1 map to level 2 map (HP and player control is all synced as it's instancing the main token I initially made). I delete the greyed out tokens in the turn order and remake it then I move the player group ribbon to the new level 2. Essentially there is an instance of the tokens in each map.  Due to the issue with having to re-editing the turn order every time a character moves to a new level; I try to move my group at the same time instead of 1 player at a time on their turn. But at times some players like to go solo for a bit of exploring while the rest of the group is in a different level, or some rare game events that require each character on their own map. Which I would have to break the group ribbon. But sounds like what you propose would take care of that as well.
I've been writing my first javascript trying to solve the problem and I've gotten quite far with it, in case you are too busy, Aaron. Plus I was curious and wanted the experience since I will probably write other scripts soon.   I am able to store the current necessary information in the state object (thanks Bill!), so the 'store' function is complete and working.  I've written the 'restore' function as well, with one major exception: what is the command to input a token into the turn order?  Based on other scripts I've seen I can put a custom entry into the turn order and set it's initiative (for example, putting an entry in for a spell that lasts a few rounds, like Hunter's Mark) but I can't figure out how to properly put a character into the turn order even though I know the id of the token, as well as the initiative I want. I wrote the 'restore' function so that the GM selects the tokens that he wants to restore and then hits the 'restore' button. That way if only some of the party moves to the other map, it will still work. Our game is this Saturday, so I'd like to have it finished by then. Thanks!
1658438878

Edited 1658453147
Nevermind, I got it!  It works great.  To use it make a macro called !SaveTurnOrder and !LoadTurnOrder.   Run !SaveTurnOrder, then on another map select whatever tokens you want to add and run    !LoadTurnOrder. on("ready",function(){ on("chat:message",function(msg){ if(msg.type=="api" && msg.content.indexOf("!SaveTurnOrder")==0) { // Read in each init in the init order var turnorder; if(Campaign().get("turnorder") == "") turnorder = []; //NOTE: We check to make sure that the turnorder isn't just an empty string first. If it is treat it like an empty array. else turnorder = JSON.parse(Campaign().get("turnorder")); // Erase the stored turn order state.StoredTurnOrder = []; // Make a for loop and then turn each id into an array with the character name and init. If the character doesn't have an ID (-1) then skip it. for (let i = 0; i < turnorder.length; i++) { var ID = turnorder[i].id; if (ID != -1) { var tok = getObj("graphic",turnorder[i].id); if (tok != undefined) { var character = getObj("character", tok.get("represents")); if (character != undefined) { var CharName = character.get("name"); var Init = turnorder[i].pr; const ThisChar = [CharName, Init]; state.StoredTurnOrder.push( [CharName, Init] ); // For each read in init, store it in the state } } } } sendChat("","Turn order stored as "+String(state.StoredTurnOrder)); } if(msg.type=="api" && msg.content.indexOf("!LoadTurnOrder")==0) { // for each selected token, see if they are in the stored info. _.each(msg.selected,function(selectedItem) // for each selected item.... { if (selectedItem._type == "graphic"){ var turnorder; if(Campaign().get("turnorder") == "") turnorder = []; //NOTE: We check to make sure that the turnorder isn't just an empty string first. If it is treat it like an empty array. else turnorder = JSON.parse(Campaign().get("turnorder")); let FoundIt = 0; var tok = getObj("graphic",selectedItem._id); let character = getObj("character", tok.get("represents")); if(character == undefined) // if its not a character, skip. { sendChat("","Not a character. Skipping...."); return; } let CharName = character.get("name"); for (let i = 0; i < state.StoredTurnOrder.length; i++) { if(state.StoredTurnOrder[i][0]==CharName) // we found a selected character in the stored turn order. { FoundIt = 1; //Add them to the init using the character's stored init. turnorder.push({ id: selectedItem._id, pr: state.StoredTurnOrder[i][1], custom: "", _pageid: tok.get("pageid"), }); var orderFinal = turnorder; Campaign().set("turnorder", JSON.stringify(orderFinal)); } } if(FoundIt==0) { sendChat("","Could not find any info in the stored turn order for "+CharName+". Skipping adding to the turn order."); } } }) } }); });