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] Room management - dynamic lighting and doors that can be toggled

1422398241

Edited 1435461063
<a href="https://github.com/RandallDavis/roll20-roomScript" rel="nofollow">https://github.com/RandallDavis/roll20-roomScript</a> With this, you can import any image and declare it a "room". Rooms can be quickly customized to draw dynamic lighting around them, including doors that can be toggled. A closed door blocks line of sight - an open door lets line of sight through but not through the surrounding walls. Adhoc walls and doors can be used to piece together more complex rooms. Everything is done through one command that intuitively presents action buttons based on what is selected. This includes extensive (and interactive) help documentation. Type !api-room in the chat window to get started! Tutorial video
1422398920
The Aaron
Pro
API Scripter
Neat, I can't wait to try it out! I might suggest you rename the file room.js from room.txt. that will allow github to context highlight it.
Will do - thanks!
1422549531
Stephen S.
Pro
Marketplace Creator
Sheet Author
API Scripter
Interesting.
Anyone tested this yet? Stephen, I think this is kinda what you and I discussed. This will be really cool if it isn't to complicated for us dummies ;)
I upgraded the script (and the description above). There are now commands for everything.
1422588925

Edited 1422590185
1422723020

Edited 1422723034
Slight upgrade - if the room is on the GM layer, dynamic lighting walls aren't drawn. As soon as you move the room to the map or token layer, dynamic lighting starts drawing again. This way you can build a room or object and hide it from your players entirely.
I added a tutorial video if anyone wants to see what this script actually does.
Loving it. now, if this can be updated with the ability to place doors off-center and have it still update correctly, I would use it constantly.- perhaps have the door image placed along the edge of the drawing, and have it force the door to that location? I dunno, I'm sure you can think of something, if you do decide to update
Before building this, I went over a lot of possibilities on how to handle off-center doors, walls with multiple doors, and alternate door images / sizes. The solution I came up with (which is next on my list to build) is "adhoc doors" and "adhoc walls". Basically a room that needs this sort of complexity will have one or more "empty sides", and then adhoc walls and doors are placed on the page to give you the freedom to do whatever you want. Adhoc walls will be pretty simple walls that you drag around and resize however you want, and they'll block light. Adhoc doors will allow for any combination of open / closed door images with the same toggle feature that you're seeing on the room's doors. Light will be blocked whenever the door is closed. I'm going to be pretty busy this week, but this won't be that hard to build, so I'll probably get that released next weekend or a little later.
1422901689

Edited 1422903402
Rand, How do I name the doors so that the script will recognize them as open / closed doors? What and where? What I am trying to attempt is to use the open door / closed door in a pre drawn map. Instead of drawing a room and adding the door to it, I would like to be able to just add a door onto a map and have it work as you show in your video. Is this possible? Thanks
looks like you have to set the image URL's for door open and door closed in the settings.js file. not sure if it can handle more than 1 of each.
On settings.js, you want to put the imgsrc values of the doors you're adding. You can find this by finding the door image in Roll20's search, and then right there in the search results, right click on the picture and click "Copy Image URL" (the wording can be different depending on your browser). If you change "thumb" in that URL to "max", it should be what the script would see if they were dragged onto the page. Right now, I have it set that you can only have 1 dedicated image for open doors and 1 dedicated image for closed doors. It would be easy to allow multiples of each if people want that.
would you consider shifting from a specific imgsource to pulling the image from a rollable table? it makes for simple in game set up, and the code is out there already to intergrate into your script... somewhere...
1423228384

Edited 1423258778
Sorry about the late reply - this week has been insane. For declaring which door images to use, Michael's suggestion is interesting... I have a few obvious ways to do it that I'd like to get opinions on: You manually set the door images in settings.js. This requires some looking up of what the door image is. You manually set the door images in settings.js, but I provide a function that tells you what the image url is, to remove any guesswork. You'd select the image and then type !roomImageUrl or something. I provide a function to let you set the image up. You would select an image and type !roomSetImageDoorClosed or !roomSetImageDoorOpen . You create a rollable table with the images you want, and the script looks for images of the same URLs for capturing.
I would say option 4, as it is the most versatile method here as I understand it, and can be set while in game easily. I also believe with a little bit of fiddling about with naming conventions of the table elements, you could set up several 'sets' of door images that it keeps track of, allowing as much complexity as a GM wants to allow in types of doors, and even adding new open/closed doors while in play (allowing for doors, gates, portcullis, or simple curtains and other such things to be switched in an on/off (open/closed) kind of scenario. example: Table : ToggleDoors (script searches for this rollable table, and if it does not find it, prompts user to create it. table entry: Basic -open table entry: Basic -closed table entry: Curtain -open table entry: Curtain -closed table entry: RedCurtain -open table entry: RedCurtain -closed this script pulls the door image url the same way, adding whatever door you specify during the command or printing an error saying image unavailable, please check your spelling, or something like that. this also opens up an opportunity to allow manual set up of doors very easily as an extension of this script: Tto set up a custom positioned door quickly in any position you would like to have it placed in, all you would need to do is have a character sheet entry called whatever you like, with a token bound to it of the right door. when you drop the door in the right place, 'draw' a line through it to match up with whatever you want the dynamic lighting line to line up with, and then run a command to 'set' the door in place. because its a token, you can set permissions on it (using scripts or just through token settings) and if anyone moves the token, the door switches states; the tokens position itself can be 'locked' so that once the door is set, it can't be moved without running another command to 'unstick' it from the map. of course, without permission to interact with the token, noone can move the door, meaning only the GM can open/close it. can all be set up on the token layer, and once its 'set' as a thing, the dynamic lighting layer moves to the GM layer while 'open' and to the dynamic lighting layer when closed. the token itself either stays on the token layer, or is set to the map layer, depending on GM preferences set during setup (i would use state for that, so it can be easily edited during gameplay if they change their mind - thats Aarons fault, by the way, he's the one who has set up this standard of ease of use while in game. its wonderful, and will soon become the simpler way to do it all as the API repository is formalised and 'locked', allowing GMs to have scripts added in a plug and play style of format. Thank you Aaron.) a point of note: if you move the doors to the map layer, a token image of some sort of locking mechanism will be needed to place over the door itself, so the GM can interact with it. a token of a cog, or a doorknob, or something else that is set up with the door and the line as they are set up. then it could be used instead of the door itself as the token, leaving the door on the map layer safely and allowing a token to act as a switch (if token moves, then token is reset to previous location, and the door toggles between open and closed)
1423289749
The Aaron
Pro
API Scripter
(You're welcome, Michael! =D)
That's a great answer and gave me a lot to think about. I like the ideas of multiple door options with pairing them up as well as a setting to let players control doors without GM intervention, but I want to clean out some other TODO items first. I had some time to work on the script a bit today (using namespaces, state, and some other badassery conventions I saw in The Aaron's scripts). As part of this cleanup, there is now only one script (room.js). As a quick fix for the issue of setting up rooms, I created a command to set image URLs for doors and save them in the state object. In order to set the door images it should look for, select an image for your door, and type !roomDoorImageSet &lt;type&gt; . The valid types are open and closed .
Door images are now created automatically, so you don't have to create doors and have the room capture them any more.
1423350271

Edited 1423350663
The Aaron
Pro
API Scripter
Rand said: Door images are now created automatically, so you don't have to create doors and have the room capture them any more. Caveat : You won't be able to create tokens with an imgsrc that is not in a user library. Also, you can only create tokens with an imgsrc of the thumb variety. Creating the max version will fail. Annoyingly, things dragged onto the VTT have the max name. You can call this function on an imgsrc to clean it up and check it's validity: <a href="https://wiki.roll20.net/API:Cookbook#getCleanImgsr" rel="nofollow">https://wiki.roll20.net/API:Cookbook#getCleanImgsr</a>... var getCleanImgsrc = function (imgsrc) { var parts = imgsrc.match(/(.*\/images\/.*)(thumb|max)(.*)$/); if(parts) { return parts[1]+'thumb'+parts[3]; } return; }; For images that are in the right library, it will return the correct url for creating it. Otherwise, it returns undefined.
Nice - I think I successfully worked through those issues already, but I'll take a look at that link (I'm a noob here, so I'm soaking up all this info as quickly as I can). What I did is this: door image URLs are now part of the state object, and default to empty strings. When creating a door, I check to see if the image URLs in the state have any length, and if not, I alert in chat that setup needs to be done. The the new command lets you set the image URLs into the state object, based on images that are on the page (and should thus be in the user's library). When I set it into the state, I replace "max.png" for "thumb.png". Am I covered here? I'm learning the "gotchas" as I go. :)
1423374991
The Aaron
Pro
API Scripter
Images on the page that were pulled in from the marketplace will have /marketplace/ in the imgsrc and not have /images/ in it. Dragging an image in that was purchased from the marketplace will have the marketplace URL. Sounds like you're handling the max/thumb issue, but you will probably still get bitten by the marketplace issue... Confirmed : setDoorURL() will set a URL in the state for a marketplace image. Another note, you're assuming the image will be a PNG, but it might be a GIF or a JPEG. Subbing for just max will allow you to support those other file types. Nice job on the reorganization. You could move your anonymous graphic change and chat message functions into the closure (say, around line 819) and give them names. You then wouldn't need reference the object by name (no more APIRoomManagement. drawRooms() ) or need to export so many functions in the returned object. Also, it would probably be a good idea to wrap the on('graphic:change',...) and on('chat:message',...) calls in on('ready',...). That would prevent them from getting called during loading up the VTT. Probably not as big a deal as on('graphic:add',...), but still a good idea to get in the habit.
Sweet - I'll make all the stated changes and let everyone know here. I really appreciate the critique.
Okay - all of those changes have been incorporated.
1423459327
The Aaron
Pro
API Scripter
Looking pretty clean!
Now, beyond just having rooms, we have adhoc doors and walls! These are good for situations where drawing a door or wall is just too complex for what the normal room setup provides. For example, if you have a side of a room that should have more than one door, or perhaps have them off center, or if there are stand-alone walls in the middle of a room (such as a bookcase). I'll post a new video soon, but the description at the top of the thread has been updated.
This is awesome.
Learning again from my peers, I just did an overhaul of the command structure and created a pretty intricate help system. !api-room help is the starting point. Hopefully it's super intuitive, but let me know if it's not...
1423632210
The Aaron
Pro
API Scripter
Cool! I'll have to check it out!!
The Aaron said: Cool! I'll have to check it out!! It'll look familiar.. it's heavily "borrowed" from your scripts. I just broke it into sections because there's so much content.
There's now a command !api-room setDoorPrivsDefault &lt;gm|players&gt; . The API defaults to "gm". If it's set to "players", all players can open / close doors. Also, if it's set to "players", doors are drawn on the token layer (even when the room is on the map layer) so that players can get at the doors.
Ugg - realized I had inconsistent naming on that ... it's now called !api-room doorPrivsDefaultSet &lt;gm|players&gt; ...
Wow, awesome work mate. This API would have taken a lot of effort. I was finding myself wishing that this was a thing in the last session I played where I was constantly switching to the light layer and drawing and deleting doors. I contemplated an API that did this but dismissed it as it would not be a trivial task. The way you have addressed the problem is quite elegant, well done.
Hey everyone - I want to thank you all for the feedback and encouragement. There's a brand new tutorial video at the top that goes over all of the features... enjoy!
Version 1.1 takes advantage of the recent API improvements. The main difference is that old objects are deleted rather than moved into a trash pile.
I'll have to try this out ! looks great !
1426932019

Edited 1426932308
Hi, me again. First off, Awesome job on the doors, I love em, and great work with the adhoc stuff. Makes this script my go-to script for any token based game now (and the only one not written by theAaron). BUT... I have a few suggestions. Or questions, that lead to suggestions. :P I can't help it. Macro buttons are a thing now, yes? I've seen them, and used them on occasion. But do they work when the API outputs them to chat? I believe so, having seen the pathfinder monster token script thingy in action. I can only assume yes, and if so, all the commands you have to type in could be further simplified by printing a list of options in the chat that guide you through the setup quickly and efficiently. want to add a room? !api-room addRoom could set the room in the script, but also print out a list of the options from there: a menu of sorts, that lets you add walls, doors, and anything else that this script offers or might offer in the future. This would also make your list of help options easier to navigate: simply click the buttons instead of retyping commands every page to get to the next part of the help file (typing it out as a full api command of course would still work as well) and then follow each prompt to move to the next help section; possibly with buttons inserted there that would actually quide the GM through the setup itself quite nicely (following the help to get to certain things, then clicking the command button there to execute the command; imagine following help through to where it explains setting doors to gm only or player accessible - follow it through the help, then click to make it either one. no more having to type out the help commands, then typing out the command itself. one command to rule them all, in effect. I dunno, maybe i'm just whining for better stuff like all the other kids these days cause I'm just spoiled, but it seems logical to me to work out how to add that kind of functionality into your script, as it would save time exponentially - every map made using the buttons to execute the commands instead of typing (no matter how practiced you are at it) is more time saved by this awesome script for both gaming and creating devious traps to run players through... edit: just realised that you could make a handout with all the commands set out nicely by section, for the GM to add things as they go by simply pulling up the handout and using the buttons on that to run it, assuming I understand how the macro buttons can be run. another thing that might be worth looking into, if it does work that way.
Michael H. said: This would also make your list of help options easier to navigate: simply click the buttons instead of retyping commands every page to get to the next part of the help file (typing it out as a full api command of course would still work as well) and then follow each prompt to move to the next help section; possibly with buttons inserted there that would actually quide the GM through the setup itself quite nicely (following the help to get to certain things, then clicking the command button there to execute the command; imagine following help through to where it explains setting doors to gm only or player accessible - follow it through the help, then click to make it either one. no more having to type out the help commands, then typing out the command itself. one command to rule them all, in effect. Great suggestion - this is now implemented. Help documents can be clicked through. As far as the clickable user interface for managing rooms, I'm still mulling that over - essentially that's a user interface that will sit on top of everything else. This comes along with some obvious pros, but some less obvious cons. While there is certainly a "normal case" for room setup, room modification and room/side removal don't have any normal cases (that would be improved by avoiding using the text commands). So I could create a sort of wizard for room creation pretty easily, but I'm not seeing a way to create a wizard for anything else. My fear is that people get used to using the wizard for 90% of their activities, and get scared of the text commands that they need for the other 10% of activities - that's when things get scary - manual deletions of things, etc. that can cause unexpected behavior. I'm interested in this though - please feel free to debate it with me.
How about adding a doorLocked option? Player is moving the door and it's not opening. Make a GM only post to the chat window with a button activation a macro to open the door. GM roll-playing: "The door seems to be locked". Player making a picklock skill check. GM clicking button in chat window to open door. One could do something similar with a doorTrapped option. Player roll-playing: "I examine the door for hidden traps." Player is moving the door. Make a GM only post to the chat window with a button activation a macro to open the door and disabled the trap. And a button to activate the trap. Player failed: The door image changes to a trap image. GM roll-playing: "You hear a soft click sound when oppening the door. A trapdoor opens beneath your feed." Player succeeded: Door is open.
Rand said: As far as the clickable user interface for managing rooms, I'm still mulling that over - essentially that's a user interface that will sit on top of everything else. This comes along with some obvious pros, but some less obvious cons. While there is certainly a "normal case" for room setup, room modification and room/side removal don't have any normal cases (that would be improved by avoiding using the text commands). So I could create a sort of wizard for room creation pretty easily, but I'm not seeing a way to create a wizard for anything else. My fear is that people get used to using the wizard for 90% of their activities, and get scared of the text commands that they need for the other 10% of activities - that's when things get scary - manual deletions of things, etc. that can cause unexpected behavior. I'm interested in this though - please feel free to debate it with me. I mulled this over and actually think there's something here worth doing - let me put something together and see what you guys think.
Bo KH said: How about adding a doorLocked option? Player is moving the door and it's not opening. Make a GM only post to the chat window with a button activation a macro to open the door. GM roll-playing: "The door seems to be locked". Player making a picklock skill check. GM clicking button in chat window to open door. One could do something similar with a doorTrapped option. Player roll-playing: "I examine the door for hidden traps." Player is moving the door. Make a GM only post to the chat window with a button activation a macro to open the door and disabled the trap. And a button to activate the trap. Player failed: The door image changes to a trap image. GM roll-playing: "You hear a soft click sound when oppening the door. A trapdoor opens beneath your feed." Player succeeded: Door is open. I'm a little scared to tie the map functionality to any type of rules or actual gameplay, since it, like tokens and other Roll20 map functionality, is rules agnostic. As far as what seems to be your situation, I have a suggestion though. If I understand it correctly, you use the setting such that players can normally interact with doors, but you have rare situations where specific doors shouldn't budge when a player tries to interact with it. To disable a door for players, just double click on the door token and in the "Controlled By" section, remove "All Players". This will make it that that single door can't be toggled by anyone but the GM. In my opinion, it would be a regular gameplay / conversation situation to convince the GM to toggle the door.
1427005334

Edited 1427033994
Okay - the "intuitive interface" is completed! (Thanks, Michael H. for the idea). The way this works is that if you type !api-room with no arguments (I recommend creating a macro for it), it presents clickable actions that you can take. Theoretically, you won't need the text commands at all any more. If you have nothing selected, it brings up the help documentation. If you have an image selected, it gives you actions that you can take on that image. Let me know if everyone likes this better than the text commands. If so, I'll thin out the help documentation accordingly.
I jumped the gun. The help documentation has now been streamlined based on the intuitive interface. You now have to know absolutely no commands except !api-room .
A new tutorial video is up, since this was such a major overhaul of the user interface.
1427143672

Edited 1427153820
wow. I went to work for a few days and I come back to find all this done. Its like R20 christmas in here! Seriously though, thats cool to see, I can't wait to test it out. I thought it would take a LITTLE longer to have it implemented to be honest. Also, I guess this means I don't need to debate this one out :P Edit: (in leu of debate, I'm just going to make another suggestion) if you have a door selected, (one thats bound to a room etc) the script can detect that, yea? why not have it bring up a locked/unlocked button that basically just toggles 'all players' tag in the controlled-by field of the token? That would be system agnostic enough to allow any kind of system to do the rolls needed to for an unlock attempt, where the GM manually unlocks the door based on the rolls he sees (its just a button for convienience, really) On that note, if you can hook into a door tokens gmnotes and detect if anything is written there, that would be great too. then a GM could write whatever he likes there, and when the door is messed with in any way, he can 'activate' the surprise, printing out whatever was in the GM notes directly to chat. a few options for formatting and putting buttons in there would be cool too (perhaps the GM has another script he wants to activate for effect - if your script presents the option to put in a manual api button for their commands it would allow people to custom add scripts that can hook into this very easily, even without a real knowledge of programming) for example: players have been moving through a dungeon, opening doors as they go, but the GM knows for a fact that when they open the next door, its going to set off a time sensitive trap, requiring initiative to be rolled, AND checks for the players to make a save throw or be caught in the initial blast (lets say a concussive blast of some kind, burning those in the radius of the effect, which sets off a cave in, making the tunnel collapse at initiative 10, trapping anyone left under it. in GM notes he could have already added a few lines to simulate this, printing to all chat the words: As the door opens, a fiery blast erupts suddenly around you, setting alight any flammables (save vs spell to negate) and doing [[2d6]] damage to those within its flames (15ft cone from the door.) immediately, you hear a deep rumbling coming from the ceiling above you... in a GM whisper, he can have already setup the button that starts the initiative script, opening combat for the group, however that is managed, and notes on what is happening: [start combat(!init)] a feiry blast weakens the roof, making a 10ft section collapse atop your players, they have until the initiative count of 10 to get out of the way.... anything of course could be written there, and much more is possible, of course. it all depends on the imagination of the GM involved. locked doors would be similar. On the subject of controlledBy, if you're going to use this method (and I really hope you do!) you would need an additional note somewhere that lets it be controlledBy all players, but doesn't trigger the open door script GMNotes: you attempt to open the door, but find it locked.... The token, instead of shifting back and toggling the door open simply places itself back, and prints ^ comment instead. GM whisper: locked door, DC 23 to open, [unlock door (!api-room)] The token will change from a locked door to an unlocked one, once the GM presses the button that activates the !api-room script again. (note: as a special usecase i would have this be a special case, so that it clicking the button opens the door directly, without a second menu being printed out: !api-room toggleLocked or somesuch) allowing the player to, on a subsequent attempt, actually open the door. of course, you'd have to write in something for the toggling of locked doors, as well as a way to detect if a door is locked without actually activating the opening of the door, if you were to add this kind of functionality (if you did not want to do that yourself, make it an optional dependency on the maplock script that is active in forums, and have it not toggle until that script unlocks the token. probably easier to add something to your own code, would fit more elegantly that way I'm sure, but I'm not a programmer). If it were up to me, I would probably put a big fat 0 in bar3, to show its unlocked, and a 1, to show its a locked door. Of course, this allows the players to see if its locked or unlocked, and possibly change it on their own. so it would probably be better to hide it in GMnotes again, in a special tag. {{locked}} or something similar, so long as its in the GMNotes somewhere. (still have it addable or removable via the script of course)
(Ps. Let me know if I'm starting to get annoying. I just keep seeing more and more possibility for your script, and mostly expand on ideas that I see or that others suggest as I see them. I swear, I'm not hoarding up a bunch of ideas to slow trickle down to you)
I'm working on an alternate implementation for adding more features to doors - updates to follow. If anyone happens to be a kind-hearted altruistic artistic type (even having a good eye for things), please PM me. I'm trying to introduce some hard-to-explain visual features that could use some minor help...
I'm in the middle of making some changes to the script. One thing I did is fixed a bug where toggling an adhoc door twice during lag could cause it to become gigantic. Unfortunately, my fix isn't so perfect or backward compatible. Please turn "move mode" on, then move all of your adhoc doors and put them back where they belong. You can then turn "move mode" back off and proceed as normal. This should make them compatible with the new code. Sorry about that. :( If you pull the updated code, you'll notice some animation logic I'm playing with...
I thought of a way to make adhoc doors backward compatible - everything should be safe now.