# san7890's Mapping Reference Collection A collection of multiple miscellaneous tips pertinent to mapping for SS13, involving several different challenges and their solutions. ### *This is still Work-in-Progress, but I hope that these snippets can prove you some help as I continue to add and refine to this. Although I've still got a lot of planned work ahead of me, I'm still placing it in a permanent location since I feel all of the information written thus far is quite useful.* --- ### The "Warranty" > This information is likely to become dated rather quickly (although certain principles will likely never change). If you see something that is outdated or wrong, please reach out to me or anyone within the /tg/station HackMD organization to update anything. Feel free to send MD-formatted snippets to fill in any WIP holes. [color=#0000FF] ## Introduction Hello there! In BYOND/SS13 mapping, there's a few technical terms that everyone must encounter with at some point. These features remain hopelessly undocumented, so this will serve as a (hopefully) truthful/accurate storage of knowledge that I would otherwise have to type out and spread through word-of-mouth. I'll chunk everything out into sections so you can easily link people to the part that matters most to them, but you can also just read this straight through. If you already know/grasp some concepts, use the table-of-contents in the right sidebar to hop around rapidly. I hope to be able to siphon knowledge from other, primary sources, but that may not be feasible. This is all based off my "working knowledge" of maps, and is intended to also give you, the reader, a "beginner's knowledge" that can blossom into the "working knowledge". You'll have to do a bit of code-diving or soul-searching (or just map more) to get a more in-depth understanding, but I find that any level of knowledge is rather good food for the soul. This is also only meant to teach solid foundational principles, *not* [how to design a map](#On-Design). > There are a few nuggets of extremely good knowledge in here, and I've flagged their titles with the (!). If you only want to read a few things from here, read those! [color=#FF0000] ## **Getting Started (Important)** *I have a [Comphrensive Quick-Start Guide to Mapping](https://hackmd.io/@tgstation/SyVma0dS5) available.* If you are completely new to mapping, I would advise starting there. This guide will assume you have everything in that guide already set up and working, and you may find yourself in that guide as I cross-link between both of them. This is the reference for the stuff that would take too long to explain in that ~~short~~ guide. If you already know how to map, you're in the right spot. --- [ToC] ## Map Keys (no holds barred) *I'll include a TL;DR, although it won't make sense: A Map Key is how BYOND/Map Parser assigns the atoms of a tile coordinate based on a list assigned to an alphabet-based short-hand reference.* ### BYOND-level Explanation What *is* a map key? It's actually a rather straightforward concept with a name that just sounds confusing. To understand a map key and it's modern use, we must look at the BYOND-level use. I've checked out a commit from [November 3rd, 2016](https://github.com/tgstation/tgstation/commit/946ec1fec869eb59d6a84e32c90613af734fcd0e). You'll see why I had to go so far back in a bit. Maps are just advanced code. There is nothing special about a Dream Maker Map (DMM) file, it's just a bunch of text. In fact, here is how it is stored on the BYOND level (for RuntimeStation when it was first introduced into the codebase): ``` "aa" = (/turf/open/space/basic,/area/space) "ab" = (/obj/structure/lattice,/turf/open/space,/area/space) "ac" = (/turf/open/space,/area/space/nearstation) "ad" = (/turf/closed/wall/r_wall,/area/maintenance/maintcentral) "ae" = (/obj/structure/lattice,/obj/structure/grille,/turf/open/space,/area/space/nearstation) "af" = (/turf/open/floor/plating,/area/maintenance/maintcentral) "ag" = (/obj/structure/lattice,/turf/open/space,/area/space/nearstation) "ah" = (/turf/closed/wall/r_wall,/area/atmos) "ai" = (/obj/machinery/power/rtg/advanced,/turf/open/floor/plating/airless,/area/space/nearstation) "aj" = (/turf/closed/wall/r_wall,/area/engine/engineering) "ak" = (/turf/closed/wall/r_wall,/area/engine/gravity_generator) "al" = (/obj/machinery/airalarm{frequency = 1439;locked = 0;pixel_y = 23},/obj/structure/closet/secure_closet/atmospherics,/turf/open/floor/plating,/area/atmos) ``` You see each of those letters on the left-side with quotations? `"aa","ab","ac"`? Those are *map keys*! A map key is simply just how we assign the types of atoms (or contents) we want on a specified tile coordinate. They're randomly picked and made using a *CAPS-SENSITIVE* alphabet. If you open a DM-formatted map in a code editor ([like Visual Studio Code with the extension](https://hackmd.io/QBaz0CaTRhOp7pEnUlXnzQ#Ingredients)) and scroll down... ![](https://i.imgur.com/0j5CGTq.png) That's the original version of RuntimeStation built using map keys! This is how BYOND assembles maps. It reads the order the map keys are placed in, and reads it back by placing the atoms on the associated coordinate to form the "tile". Don't believe me? Check this out: ![](https://i.imgur.com/WYEpgzV.png) Can't you see the similarities? The truth has been revealed, your pre-conceptions of reality have been completely shattered. Well, maybe it's not so obvious due to the- ### TGM Format The TGM format (TG Map) is how /tg/station (and all relevant downstreams) store all the information and lines of code that makes up a map. The name comes from the fact that it was [developed by /tg/station developers](https://github.com/tgstation/tgstation/pull/10623). As RemieRichards (the original developer) put it: > This converts the internal syntax of a .dmm file (the Dream Maker Map format you saw above) to a format that can be read better by humans (shown below) but the best part is that this should reduce mapping conflicts. > > Mapping conflicts should now only occur when two or more people touch the EXACT SAME ITEM or EXACT SAME VARIABLE on map instances, where as at the moment it conflicts arise the moment people even remotely touch two turfs near each other. So, the syntax for another map key, "aab", looks something like this: ``` "aab" = ( /obj/docking_port/stationary{ dheight = 9; dir = 2; dwidth = 5; height = 22; id = "syndicate_n"; name = "north of station"; turf_type = /turf/space; width = 18 }, /turf/space, /area/space) ``` Compare that with what you saw above. Marked improvement, right? This was developed in *2015*, and after a few long years of transitioning, this header is now at the top of every single /tg/station map: > //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE They were right. [The TGM format was revolutionary in maintainability, as well as merge conflicts.](http://www.byond.com/forum/post/1896428) By putting everything on it's own line rather than having it all squished on the same line, the odds of having a horribly awful merge conflict were lessened dramatically. They still happen, but boy: they happen a lot less. We also no longer save the map in that big block of text in the TGM format. For example, you'll see something like `(1,1,1) = {"`, then `(2,1,1) = {"`, ``(3,1,1) = {"``... and so on, with each having it's own map keys contained within those curly braces on it's own lines. Great for codebases. Now, the built-in Dream Maker Mapping tool only saves stuff in the Dream Maker format. However, Dream Seeker ([the game client itself](http://www.byond.com/developer/articles/whitepaper)) can parse both the DMM and TGM formats. Now, both [actively maintained mapping projects](https://hackmd.io/@tgstation/SyVma0dS5#Mapping-Utilities) natively support the TGM format (reading and saving). This is mostly thanks to the fact that they're built on the same map parser ([SpacemanDMM](https://github.com/SpaceManiac/SpacemanDMM)), which was made by [SpaceManiac](https://github.com/SpaceManiac). The entire SpacemanDMM suite revolutionized the way we work with DM code and maps, and it's very nice to see that we were able to get that one consistent format down pat. Now, /tg/station13 *requires* the use of the TGM format. However, the aforementioned mapping utilities natively save in the TGM format (albeit a teeny bit differently than the way that mapmerge2 does), so you don't need to worry about manually converting this stuff any more. After a few years of development, more and more advancements were made to build the Map Merger, and it's gone from being stick-and-stone .BAT's and .PY's, it's now cleverly machined Git Hooks ([that you should definitely use](https://hackmd.io/@tgstation/SyVma0dS5#Git-Hooks)) to the sleeker thing we have today. Yet, merge conflicts still happen. However... they're not so bad when you know precisely how to tackle them. ## Assured Merge Conflict Resolution Alright, I'll be using GitHub Desktop. If you have the technical know-how to do it on another client, great! I do not. ### Getting It Map-Merged <img src="https://i.imgur.com/cXf8RCl.png" style="display: block; margin: 0 auto"/> Urgh, this sucks. If you have a [Merge Conflict](https://git-scm.com/docs/git-merge-file#_description) on your [Pull Request](https://hackmd.io/QBaz0CaTRhOp7pEnUlXnzQ?both#Blending-It-All-Together), you aren't able to get it merged into master, so you've definitely got to fix this. However, it's very easy to deal with when you know what to do. #### Updating Your Branch To Master Git is very versatile, and there are many paths to get to the same conclusion. This path is partially annoying on other Git clients, but I personally find it to work the best for myself. I used to advise rebasing your branch, but I've realized this is not the way to do it because of a false assumption I made four months ago. This is definitely the best way. Firstly, go to the `master` branch of your repository. For me, it will be `bruhstation/master`. <img src="https://i.imgur.com/InJX1YT.png" style="display: block; margin: 0 auto"/> If it says, the branch is behind, just go ahead and hit the "Fetch Upstream" button. You should see the following menu now, just hit `Update Branch`: <img src="https://i.imgur.com/kr4eAh3.png" style="display: block; margin: 0 auto"/> Quick sidebar, if you see something like this: <img src="https://i.imgur.com/tjwa6bB.png" style="display: block; margin: 0 auto"/> Your branch (which should be master in this case) is dirty and you should _definitely_ not use this branch for what we're about to do. Ninety-nine times out of a hundred, using a branch with "commits ahead" for will dirty your branch in ways that you probably can't crawl out of. Just double-check it before you do stuff, and you'll be fine from there. If you need to make a pull request from `tgstation/master` into your fork's master, you're probably not on the right track. If it adds cleanly, you should see something like this show up: <img src="https://i.imgur.com/q4o3Iln.png" style="display: block; margin: 0 auto"/> Alright, cool! However, you're not in the clear yet. You **must** now go into your branch in GitHub Desktop. Do not try and Fetch Upstream into your branch via GitHub.com, you must do it this way and merge master into your branch via the Git client (otherwise, those Git hooks will not work). So, once in GitHub Desktop and hit this button: <img src="https://i.imgur.com/C1vMekB.png" style="display: block; margin: 0 auto"/> Now, hit "Fetch Origin". After a few seconds, you should see the following (assume gitFUCK is master for the sake of this dated photograph): <img src="https://i.imgur.com/F9HJGdD.png" style="display: block; margin: 0 auto"/> Just "Pull Origin", and all the commits of code will automatically download from GitHub onto your machine. Very cool, and important. Once this is done and your local repository is now up to date with `tgstation/master` via the `master` branch of your fork, go **to the branch that the Pull Request is associated with** and hit this option (or do <kbd>Ctrl+Shift+U</kbd>): <img src="https://i.imgur.com/efpCBgg.png" style="display: block; margin: 0 auto"/> After a few seconds, you'll see something like this: <img src="https://i.imgur.com/XFX3Z6I.png" style="display: block; margin: 0 auto"/> If you have those [Git Hooks](https://hackmd.io/@tgstation/SyVma0dS5#Git-Hooks), it will automatically take it from there. If Git wants you to open up your conflicts in a text editor to manually resolve them, *you do not have the Git Hooks. Get the Git Hooks.* This might take a few steps and have a prompt with something like this: <img src="https://i.imgur.com/YvOc5BB.png" style="display: block; margin: 0 auto"/> This is actually a silent clue that you have Merge Conflict Markers on your map (more on this later!). However, you have Git Hooks (hence, No Conflicts Remaining), so just hit "Continue Rebase". This prompt won't show up sometimes, and that's perfectly fine. <img src="https://i.imgur.com/FVhGra0.png" style="display: block; margin: 0 auto"/> You're rewarded with a checkmark at the end now, just hit "Push Origin". This just adds the "merge commit" to your remote branch, quite similarly to any other commit. You will see any new commits interspersed with any commits you've made, though (won't show up on your PR or to anyone who checks out your branch). Now, when you go to your Pull Request and scroll down, you should see the following: <img src="https://i.imgur.com/lZglWeg.png" style="display: block; margin: 0 auto"/> There you go, you've done a Merge Conflict Resolution! Hopefully, this is all you need to do, but there could be a few more things, and we'll get into those in the next section. #### Post-warning Sometimes if something goes weird, it can lead to situations where literally everyone in CODEOWNERS gets assigned for a review to your PR (and you get every label in the codebase). If that happens, just keep calm, and someone will pass by to remove all the un-needed review requests (we're used to it). This path tends to be the most efficient and most fool-proof way though. --- ### Merge Conflict Markers <img src="https://i.imgur.com/UENE3WA.png" style="display: block; margin: 0 auto"/> Hey, what happened here? LLIIIIIIIIINNNTTEEEEEEEEERRRRRSSSS!!! Sometimes, you'll fail linters with the following problem: <img src="https://i.imgur.com/MOZ8PIk.png" style="display: block; margin: 0 auto"/> Or, the problem might appear like this: <img src="https://i.imgur.com/0vwWAps.png" style="display: block; margin: 0 auto"/> Or like this: <img src="https://i.imgur.com/NEVDYgh.png" style="display: block; margin: 0 auto"/> These all mean the same thing: [MapMerge2](https://github.com/tgstation/tgstation/tree/master/tools/mapmerge2) tried to merge both your map and another copy of the map (which should be the one that's up-to-date on the upstream), and ran into an issue with the specific [map key](#Map-Keys-no-holds-barred). Since it was unable to parse what the original intent was, it combined the contents of _both_ map keys, and left it on that same tile, while marking it. But, how do you know which tile conflicted? [/tg/station code as of July 4th, 2022 no longer uses the steps listed in the deprecated version of instructions.](https://github.com/tgstation/tgstation/pull/68039) However, several downstreams have ported the older version of our MapMerge2 tools (which still work perfectly fine). I will include the [old instructions](#The-Deprecated-Version) as well, but I do advise you port over the update whenever you get a chance. ### The Modern Version of dealing with Merge Conflict Markers Alright, you're running modern /tg/ code, great! First things first, you'll want to look up `/obj/merge_conflict_marker` in your environment tree. Then, double-click that entry in the environment tree and look to the `Prefabs` entry. <img src="https://i.imgur.com/aVqmQwU.png" style="display: block; margin: 0 auto"/> You *need* to <kbd>Right-Click</kbd> the version that says `---Merge Conflict Marker---` as the name. Do not use the one that says "Do Not Use", it says "Do Not Use" because you should never use it ever. Not even here. <img src="https://i.imgur.com/8e4q8gv.png" style="display: block; margin: 0 auto"/> Now, <kbd>Right-Click</kbd> this entry, and select `Search by Type`. You should then see something like this pop up in the `Search` tab. <img src="https://i.imgur.com/CAUEV1Q.png" style="display: block; margin: 0 auto"/> Now, just click on the magnifying-glass icon (`Jump To`) for each of those entries from the search, and then clean up that area. Note that if it's a Multi-Z map, it might show you the correct tile as far as X/Y Coordinates go... but it'll be on the wrong Z-Level. Just hop up and down using <kbd>Ctrl+Up/Ctrl+Down</kbd> until you get it. This is what it looks like for me: <img src="https://i.imgur.com/UGNopeI.png" style="display: block; margin: 0 auto"/> Now, let's right click each of those tiles and view the contents. <img src="https://i.imgur.com/Vbq5T7r.png" style="display: block; margin: 0 auto"/> Yeah, so that's what MapMerge2 did when it "dumped" the contents of both map keys onto that tile. You just want to go through and get rid of the stuff you don't need (or the stuff that actively works against your design), and just ensure everything looks like how you originally wanted it. *Keep an eye out for duplicate power cables or atmospherics piping, that tends to happen in this scenarios. If that does happen and you miss it, Linters will fail again.* <img src="https://i.imgur.com/7Jmcvet.png" style="display: block; margin: 0 auto"/> Alright, much better. Just save your map (ensure the Merge Conflict Markers you tended to are deleted), and then push your changes in a new commit. After you do this, Linters should no longer be failing, and you're all set from there.. at least until the next conflict. #### The Deprecated Version ##### *[IF YOU HAVE PORTED MAPMERGE2 AFTER JULY 4TH OF 2022, THIS WILL NO LONGER APPLY!](https://github.com/tgstation/tgstation/pull/68039)* Firstly, just click the `/obj` subtype in your Environment Tree. <img src="https://i.imgur.com/S9erD24.png" style="display: block; margin: 0 auto"/> Then (by default), look at the "Prefabs" tab on the right of your screen. <img src="https://i.imgur.com/sIUbzxn.png" style="display: block; margin: 0 auto"/> Alright, if you're seeing this, you are definitely on the older version of MapMerge2. I'm going to put the rest of the steps in the spoiler below: <details> <summary>Click To View The Rest Of The Steps For The Deprecated Version</summary> If you have Merge Conflict Markers, this prefab (short for pre-fabrication) should show up. Just click on the `---Merge conflict marker---` Prefab, then right-click that prefab. Then, select the option that says "Search by Prefab ID". You should now see something like this: <img src="https://i.imgur.com/gnk9q3d.png" style="display: block; margin: 0 auto"/> Now, you can hit the Magnifying Glass Icon on any of the "results" from your search, and jump to that specific tile coordinate. Note that if it's a Multi-Z map, it might show you the correct tile as far as X/Y Coordinates go... but it'll be on the wrong Z-Level. Just hop up and down (`Ctrl+Up/Ctrl+Down`) until you get it. This is what it looks like for me: <img src="https://i.imgur.com/SWXP67x.png" style="display: block; margin: 0 auto"/> Now, you just wanna right-click all of those tiles with the "Counter-Strike: Source" missing texture, and view the contents: <img src="https://i.imgur.com/dv7ouwR.png" style="display: block; margin: 0 auto"/> Yeah, so that's what MapMerge2 when it "dumped" the contents of both map keys onto that tile. You just want to go through and get rid of the stuff you don't need (or the stuff that actively works against your design), and just ensure everything looks like how you originally wanted it. *Keep an eye out for duplicate power cables or atmospherics piping, that tends to happen in this scenarios. If that does happen and you miss it, Linters will fail again.* <img src="https://i.imgur.com/7Jmcvet.png" style="display: block; margin: 0 auto"/> Alright, much better. Just save your map (ensure the Merge Conflict Markers you tended to are deleted), and then push your changes in a new commit. After you do this, Linters should no longer be failing, and you're all set from there.. at least until the next conflict. --- I strongly encourage that you port over the modern version of MapMerge2's Merge Conflict Markers for a few reasons: * You can control the variables tied to the actual explicit `merge_conflict_marker` atom, and not be reliant on whatever the base `/obj` defines to. This means that you can: * Have a seperate plane (make the conflict marker show up on the highest plane so it's not obscured by anything weird, which was a common occurence) * Have a specific name that shows up should someone map it in manually, versus having it be placed by MapMerge2. * Have a specific description that tells new mappers how they should deal with this item. * And more! It's a great idea, and I do hope that you can [port](https://github.com/tgstation/tgstation/pull/68039) it over. I, san7890, the author of that PR, give explicit permission that any codebase not on aGPL code license (for code) / CC 3.0 BY-SA license (for assets) may port it as a sublicense to literally any codebase running any license, all I ask is that you let me know via Discord (@san7890#7890) or via my email address. If you are unsure if I am being genuine, or have any follow-up questions- my public-facing email address should be tied to later Git commits, or can be accessible [here](https://san7890.com/contact). </details> ### UpdatePaths And You (!) #### *[Read the ReadMe Here!](https://github.com/tgstation/tgstation/blob/master/tools/UpdatePaths/readme.md)* Sometimes, the codebase undergoes large "repathing" in order to either better organize variables, or make things more sane, or to just replace something "old" with something "new". It is nearly compulsory for people to include an UpdatePaths Script for these changes, otherwise people's mapping projects could just brick out in certain circumstances. The UpdatePaths Script is quite intelligent, and it will go ahead and replace every single instance of the "old" pathing with the "new" pathing. For example, let's say that I want to repath this object from: ``` /obj/structure/deez/nuts ``` to this new pathing: ``` /obj/structure/deez_nuts ``` That means that when StrongDMM boots up after you resolve the merge conflict, the "old" pathing `/obj/structure/deez/nuts` will no longer exist on any map, and it will be discarded for being an invalid path. You don't want to completely discard a once-existing object from a map, so you definitely want to follow these instructions: Whenever you boot up StrongDMM and are met with the following message (after resolving your merge conflict): TODO: (screenshot of discarded types) You should immediately go to (from the root of your repository folder) `tools/UpdatePaths`. From there, you should see something like the following: TODO: (screenshot of file explorer) Just simply go ahead and "drag" the `.txt` files onto `UpdatePaths.bat`. You can find out which `.txt` file you need by checking if a large Pull Request with these changes was just merged and seeing the file that the contributor added to this directory. You can also ask around in either mapping or coding channels, and someone is likely to be help you figure that out. Once you see this following line (after a listing of several map files): ``` Press any key to continue... ``` The Path Update should have gone through successfully. Keep in mind that this typically will only happen if the repathing touched the same thing you were working on in your PR, since they'll likely have done this exact step on their end. Sometimes, people don't write UpdatePaths scripts... and it is your forsworn duty to remind them to do that. StrongDMM 1.9.1 has this feature by default (not present in StrongDMM 2.0 as of Mar/9/2023), but in an ideal world you should either use an already existing UpdatePaths (to save you the typing) or create a new UpdatePaths (so that others may use it as well, and your work becomes extremely helpful). ## Mapping [Jargon](https://www.merriam-webster.com/dictionary/jargon) [Lingo](https://www.merriam-webster.com/dictionary/lingo) This is just a short collection of a lot of terms we throw out a lot regularly when discussing mapping that a lot of newer people won't understand. I hope my definitions remain accurate in their utilization, please inform me if I am full of shit. #### Active Turfs Without going too much into how LINDA and how /tg/'s Atmospherics works: an Active Turf occurs when at the very start of a round, the system has to calculate air differentials between two open turfs. This wastes processing time at the start of a shift, and is what leads to this warning which you may have seen once or twice in either CI or the [map_errors.log](https://hackmd.io/QBaz0CaTRhOp7pEnUlXnzQ?both#Checking-Logs): <img src="https://i.imgur.com/oGD2p1u.png" style="display: block; margin: 0 auto"/> To fix this, you would just have to standardize the turfs in that region to use one common gasmix to ensure there are no active turfs. If it's not standardizable (e.g. "outside zone" versus "inside zone"), just close off the space where the two different zones meet. This is a bit abstract to explain, but it basically boils down to "you used the wrong turfs in this area, use the correct ones". If a turf with the desired gasmix doesn't exist, it's not difficult at all to create one code-side. One day someone should write a comphrensive guide on tackling this, but let's just explain what the issue is for now. #### Directionals Internally, these are known as "[dir](https://www.byond.com/docs/ref/#/atom/var/dir)". This is how we assign the cardinal direction that a certain atom should face, and have the sprite update according. Do note that if an atom doesn't have sprites that allow it to face in several directions, you will be locked to "2" or "SOUTH". The reason why it's like this is because directions are actually bitflags (read the documentation it's in the first sentence of this paragraph). The following image may be of use: <img src="https://i.imgur.com/uEFcPA7.png" style="display: block; margin: 0 auto"/> #### Map Depot The repository /tg/station has in order to preserve maps, as well as keep them maintained to the best-level possible. You may find it at: https://github.com/tgstation/map_depot. #### Maptainer A /tg/station maintainer who specializes in reviewing PRs specifically designed to alter any existing DMM file, as well as performing additional Quality Control on any other PRs that include edits to DMM files. #### Pre-fabrication More on this here (link WIP). In summary, it's a type of atom that has had its variables edited, and thus deviates from the variables the atom holds in code. You can easily select and place this variant of an atom anywhere on the map, and you can generate even more pre-fabs (shorthand for Pre-fabrications) by adjusting stuff like the direction it holds, or maybe even it's color. #### Room A walled-off space, typically with a door and windows. (wip wap :( ) --- ## Pre-Commit Checklist The following checklist is provided so you can really nail down what you might want to double-check right before you [commit your changes to your branch](https://hackmd.io/@tgstation/SyVma0dS5#Back-To-Gitting). This is most useful for station mapping, so feel free to skip the parts you don't need for other maps. The following is also meant as a general "sanity" thing, as opposed to *hard* guidelines. I'll also touch on some of the concepts introduced here later on in this reference. We'll work through issues as they come up. - [x] Are floors with or without air, as they should be? (regular or airless) - You can test this one out by looking for [Active Turfs](https://hackmd.io/koZLICNhTBa9mhb7Ts_wqg#Active-Turfs). - [x] Does the area have an APC? - [x] Does the area have an Air Alarm? - [x] Does the area have a Request Console? - Not every area needs this, look at other stations. - [x] Does the area have lights? - [When you compile your map for testing](https://hackmd.io/@tgstation/SyVma0dS5#Testing-Your-Map), make sure the lighting is adequate. You don't want any unwarranted "dark" spots in your rooms. If you're going for "warm" or "cold" lighting, make sure it all matches. - [x] Does the area have a light switch? - [x] Does the area have enough security cameras? (Use the [Debug Verbs](https://hackmd.io/@tgstation/SyVma0dS5#Things-To-Look-Out-For) for help) - [x] Does the area have enough intercoms? (The verb `Intercom-Range-Display` in the [Mapping Debug Verbs](https://hackmd.io/@tgstation/SyVma0dS5#Things-To-Look-Out-For) helps with this.) - [x] Are all the vents in this area connected to the vent air loop (distro)? - [x] Are all the scrubber in this area connected to the scrubber air loop (waste)? - [x] Is everything wired properly? - [x] Does the area have a fire alarm and firelocks? - Typically, doors leading into maintenance do not need firelocks. Do not place firelocks on doors facing the exterior of the station (like space or the planet). - [x] Do all airlocks work properly? - [x] Are accesses set properly on doors, buttons, etc? - For typical airlocks, you can use the [Airlock Mapping Helpers](https://github.com/tgstation/tgstation/pull/65580). Otherwise, consult the [reference for Door Accesses](#On-Access). - [x] Are all items placed properly? - In summary, are your objects all on tables as needed? Are tables or other objects obscuring your vents/scrubbers? - [x] Does the disposal system work properly from all the disposal units in this room as well as the pipes of which pass through this room? - Just throw yourself through a few disposals systems that seem to pass through the area you touched. Easy to forget. - [x] Check for any misplaced or stacked piece of pipe. - /tg/station also [lints](#Linters) for this to catch you if you forget. - [x] Check for any misplaced or stacked piece of wire. - /tg/station also [lints](#Linters) for this to catch you if you forget. - [x] Identify how hard it is to break into the area and where the weak points are, and balance the area accordingly. - For example, the [Vault](https://tgstation13.org/wiki/Vault) should be made of reinforced structures and electrified windows, the [Kitchen](https://tgstation13.org/wiki/Kitchen_and_Freezer) should not. Be reasonable, not everything has to be an overly-secure structure to prevent the "tide" or other events. You will be vetted on this, just make your best choice. - [x] Check if the area has too much empty space. - You don't want vast, bald spots in your rooms that serve little purpose. Fill it up with stuff if you can, or just trim the fat entirely. Whatever works best for the station and your design. - [x] Are there any indestructible turfs where they shouldn't be? --- ## Verbose Mapping Knowledge This section is a modern review of /tg/station's original "[Guide to Mapping](https://tgstation13.org/wiki/index.php?title=Guide_to_mapping&oldid=37972)". A lot of the photographs and practices denoted in that link are very much out-of-date, but a link is provided for sentimental purposes. The following serves as a fundamental rewrite touching the same aspects this historic guide did. This is all quite /tg/-centric, just use what works for your codebase. --- ### First Things First Since the following sections are in the same vein as the historic "Guide To Mapping", the following snippets will assume you have already read the [modern A-Z Guide To Mapping](https://hackmd.io/@tgstation/SyVma0dS5) to get a basic "framework" of mapping knowledge. They should all work independently, but if you have no idea where to start, go back and read the modern guide. --- ### Placing Stuff On Walls (WIP), but you typically should just use the `directional` variants of an object, and place it on tiles until it makes sense. --- ### General Stationwide Guidelines This section serves as a general guide for *station* mapping. Although some of the advice here will not apply to other forms of mapping, take what you need. This will be stuff that maptainers look for while reviewing your Pull Request. If you can reasonably justify not adding in a specific change as follows, we'll help you from there. #### In General * If you can avoid it, don't run pipes/cables/disposals through walls. Otherwise it's a pain to repair or sabotage them, especially under reinforced walls. * Try to connect departments to maintenance through a back or side door. This lets players escape and allows antags to break in. * If you aren't sure what to do for a certain functionality, feel free to look at other maps and re-utilize what they do. Always make sure to [test your changes](https://hackmd.io/@tgstation/SyVma0dS5#Testing-Your-Map). #### Atmospherics Quick-Checks * Each area should have at least one air alarm. More than one air alarm may be needed for larger spaces on a case-by-case basis. * Each [room](#Room) should have at least one vent pump and scrubber, which is properly connected to its respective loop. Keep in mind that scrubbers don't detect gases/pressure; only air alarms do. * For the following, look at what current stations do with smartpipes (a special type of pipe object that automatically does the heavy-lifting of atmospherics piping for you when the game initializes). * The air supply loop's pipes should be colored blue, and be on layer four. * The scrubbers loop's pipes should be colored red, and be on layer two. * Some areas require special air alarm subtypes. Look at other stations to see what you should do for this, as the specifics on this bullet point are subject to change at any time. * Check for [Active Turfs](#Active-Turfs)! #### Power Quick-Checks * Each area (which requires power) should have one APC. For areas with a high roundstart power draw (like engineering), one of the subtypes with a higher amount of power capacity can be used. Again, look and see what other station maps might use. --- ### On Atmospherics Space Station 13 was created as an Atmospherics Simulator. It is the fundamental center to this game, and it's doubly important to ensure that your maps leverage atmospherics properly. If you've played Space Station and "get" Atmospherics: congratulations! Mapping has only a few variations from what you might do in game. However, most other people do not understand atmospherics, so have a small "crash course" on it (at least as far as /tg/-based atmospherics systems are concerned). Some details are withheld to avoid overloading the reader's brain, but if you're hungry for knowledge: [read on](https://tgstation13.org/wiki/Guide_to_Atmospherics). #### Pipes and Manifolds Atmospherics releases its cocktail of gases into the air supply loop (Distribrution, or "Distro" for short). This *supplies* the station with air to breathe (or toxic gases). These are found in the blue pipes. The station is also equipped with a scrubber loop (Waste), which ingests unwanted gases and sends them back to atmospherics for filtering and processing. These are found in the red pipes. If you're expanding Distro (Air Supply), you'll want to use `/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4` in normal rooms. If you want the pipes to be visible for any reason, use `/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/visible/layer4`. For expansion of Waste (Scrubber Filtration), `/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2` in normal rooms. If you want the pipes to be visible for any reason, use `/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/visible/layer2`. If you're building on Multi-Z Maps, use `/obj/machinery/atmospherics/pipe/multiz/**/visible/**` (replace the astericks depending on the system you're building) in order to connect either the distro or waste loop up across Z-Levels. If you're building something involving atmospherics that isn't the above two systems, definitely use other colored subtypes where applicable. If you're confused on some logistics, look at the station you're mapping on, or the same room on other stations. Throughout all of mapping, it's always good to "learn by example". Be sure to add as many or as little vents and scrubbers as you need in a room. #### Air Alarms Air Alarms are how the in-game system "detects" changes to atmospherics, as well as how anyone can control the vents or scrubbers in a specific *area*. Try and place this in a central position in a room when possible. Air alarms default to reading the tile they are placed on, but can be linked to a different tile in a different area via a `/obj/machinery/air_sensor/` and the `chamber_id` var. [See PR#78187](https://github.com/tgstation/tgstation/pull/75187) for the details. This is used in engines and burn chambers. #### [Active Turfs](#Active-Turfs) #### Atmospherics: The Department This also goes for stuff like ~~toxins~~ Ordnance. I personally don't know a good way to put this in words so like most other things, look at already existing station maps and take down notes on how stuff is done. You can also look at [the latest Pull Request](https://github.com/tgstation/tgstation/pull/65372) that conformationally changed the way that setting up stuff like burn chambers and that type of stuff worked. This is likely to change again, but hopefully not much more than it already has? Good luck. --- ### On Power Power is a bit easier to grasp than atmospherics. This does change a bit, but if you've messed with power in game, none of this should be a shocker to you. #### Area Power Controller (APC) Each new room needs at least one, this will provide all the power for the room (magically). Each piece of machinery inside the APC's area will draw power from either the lighting, equipment, or environmental channel based on the type of machinery they are. Any room that is very equipment heavy (Engineering as an example) may need a beefed up APC to prevent early blackouts. These start with higher capacity power cells. #### Wiring /tg/station uses smartwires, which automatically path wiring upon initialization of the game. Just use the `/obj/structure/cable` type (or the type on the first or third layers, if necessary). Make sure the wires lead from the main power grid, and to the APC(s) of your area. If any equipment in your new area requires a wire under it, line it up, connected to the main power grid, and under the machinery. Wires are also helpful when making electrical grilles (just place wire under a grille), ensure the wires touch the main power grid (or they won't shock people). --- ### On Equipment Equipment is just the general term we use for machinery that you'll typically use in your rooms. #### Lights Lights take up power, don't use too many! Make sure to put in just enough so the room is fully lit, but not so many that the equipment will go out in ten minutes of the round starting. If you want to enhance the visuals of your room, don't be afraid to experiment with the subtypes of lights that we have (like Cold and Dark lighting). This can greatly enhance the overall aesthetic of your room. #### Light Switch For mood lighting, or to show the room is currently not in use by the primary occupant. These disable the lighting equipment (and power drain associated) in the area, but not desk lamps. Best placed on walls, usually by a door. #### Request Consoles If a certain room has no need for materials, or produces no materials, do not give it a Request Console. If it does (for either case or both) make sure it has at least one, that is in a place where someone will see it. #### Intercoms At least every room should have one of these. You'll typically just want to use the base subtype in your station mapping, `/obj/item/radio/intercom/directional` (as well as the direction it's supposed to be placed on the wall in). If you're doing stuff with prisons/the AI, make sure you use the correct subtype. This is so radio signals can reach people even without head sets on. Larger room will require more than one at a time. #### Security Cameras Most areas (typically everything but Maintenance, few edge-cases here and there) should have these, enough to see the general area from a Human point of view, but not bunched together for the AI's sake. Larger rooms may require more than one. Definitely test this out to ensure you don't have any weird "dark spots" that aren't warranted. #### Holopads This is a nifty little thing. You typically want one of these in central/important areas, or somewhere where someone will want to ask the AI for help when communications are down. #### Fire Equipment You want one fire alarm per zone. I'm going to define a zone as "a section of a room where firelocks are able to isolate someone from the rest of the room". You want one fire alarm per zone, to ensure that people without crowbars aren't completely trapped with a fire. One fire alarm per room doesn't really cut it, unless the room is just in one "zone". Place firelocks per your design, where sub-sections of a room or various hallways have them at specified intervals. You don't need anything more than one "layer" of firelocks. Keep in mind that firelocks are able to respond to changes in most changes in atmospherics as well (not just fires, they detect cold conditions/depressurizations), they aren't just dependent on the fire alarm. Any spot that gets hot/cold as a normal function should not have a fire alarm/fire lock right next to the source. #### Other Equipment It would be impossible for me to cover them all, so just look at how current maps have them put in. Good luck. --- ### On Room Structure and Security #### On Access [This](https://tgstation13.org/wiki/Guide_to_door_access) is also slightly helpful. If something isn't working, check the values at [this part of the code](https://github.com/tgstation/tgstation/blob/master/code/__DEFINES/access.dm). For general airlocks, this has recently been made rather easy. You have two types of accesses to set using mapping helpers (`/obj/effect/mapping_helpers/airlock/access`), "any" and "all". <img src="https://i.imgur.com/nRdIAxB.png" style="display: block; margin: 0 auto"/> "Any" means that if you have *any* access on your card, you can enter that area. Let's paint an example (note: the following is not how it works). Let's say... [Supply's](https://tgstation13.org/wiki/Supplies) front door. That door will have an "any" access such that [Cargo Technicians](https://tgstation13.org/wiki/Cargo_Technician) with their General Cargo access can get in, or [Miners](https://tgstation13.org/wiki/Shaft_Miner) with their Mining access can also get in. The miner can get in even though they may lack that General Cargo access. However, what if you want to restrict a door in a specific way using "all" accesses? Let's go a bit deeper into the department, let's say the [Mining Dock](https://tgstation13.org/wiki/Mining_Dock). What if you don't want any jack-or-jill with Mining access to get in? You *want* them to have both General Cargo and Mining. Then, you could use the *all* variants of those mapping helpers on those doors, helping restrict it further. That door **will not open** unless they have General Cargo *and* Mining access. Do keep relative room security in mind if you do this, if it's horribly unbalanced, it might be requested to change. Also, if you're using a door that only has one access helper associated to it: use the "all" subtype. This will help us audit different access requirements should we need to down the line. The exception to this is the are the ones used for departmental maintenances... those should be kept as "any". #### On Relative Room Security Keeping accesses and the purpose of the room in mind, take the following into account as you map: Judge how high security the room will be, if it is high security, reinforced walls and electrified grill windows may be in order. Areas that do not need a lot of security can use basic walls, and windows to your liking (though normal glass windows break easily). Each room should have one place that's weaker than the rest (like a back door, side entrance, or a window), just because the main entrance might be out of commission (and realistically, for antagonists to break into). Before you finalize a map, check for any indestructible turfs. These turfs ignore things like external damage and are typically meant for things like special ruins/rooms where you want to avoid people trying to circumvent a path. Due to these characteristics, they have no real place on regular station maps and would probably lead to confusion for players more than anything. A room is only as secure as its necessity. Public rooms should not have many security functions (other than a fire alarm), but private work space must be more secure (based on job). The bartenders do not need reinforced walls around their storage, but engineers do. *The highest security rooms should utilize the highest security measures. The lowest security rooms should utilize the cheapest security measures.* #### On Room Planning Be smart about what will go in an area/room. Keep a fine balance between the size of the room and amount of equipment. Make sure to place equipment that make sense for the area (security computer in a security area or a medical vendor in a medical area). --- ### On The Step_X/Step_Y Syndrome So you compiled the map and suddenly whenever you move you no longer get the animation of moving but just 'appear' on the next tile? Step_x and step_y are BYOND variables introduced to allow pixel based movement. Space Station 13 does not utilize this. Step_x and step_y are variables that each [atom](https://www.byond.com/docs/ref/#/atom) has. The way they work is that as soon as you set any object on the map to use one of these variables, the game interprets that you overrode all default movement code and wrote your own - but you didn't (The code that makes the animation from tile to tile). To fix this problem you need to first save your map. Open your `.DMM` map file in a text editor ([Visual Studio Code](https://hackmd.io/@tgstation/SyVma0dS5#Mapping-Utilities) works great). Search (`Ctrl+F`) through the file for step_x and step_y and remove any reference to it. Once no more step_x or step_y variable edits are found in the file, save it and open it in StrongDMM once again. Once you go back and debug again, the code and movement should work fine once more. If you need help, [ask](https://hackmd.io/@tgstation/SyVma0dS5#More-Information-And-Where-To-Find-It)! --- ### On Shuttles ##### (WIP because I'm not knowledgeable on this subject matter) You can read about this [here](https://tgstation13.org/wiki/User:SpaceSmithers/guide_sandbox#Shuttles). Feel free to edit that sandbox page, or send me the information presented within in an MD-format so I can just paste it in here instead. #### Shuttle Sizes Tidbit If you're making a shuttle (of any size) larger than the Pubby Monastery Shuttle (43x80) and it's not some insanely good gimmick you should really re-think what you're doing due to the technical standpoint, shuttles are costly as hell to move. If you're wondering about an appropriate size, the safest tends to be anything within the bounds of 35 by 24, since that is what we want to assume will dock at any station's auxiliary port (for like white ships and stuff like that). --- ### On Multi-Z Multi-Z is a feature which allows a station map to have multiple Z-levels layered on top of each other, behaving as a single station with multiple floors. This feature is currently in use on the Tramstation and IceBoxStation maps. A station's multiple levels can be bundled into one map file. They could also be implemented across separate map files, but recent advancements in tooling have made the "single file" solution [the preferred method](https://github.com/tgstation/tgstation/pull/66615#pullrequestreview-962781309). The Z-Traits section of the map configuration JSON tells the map loader how to link the maps together. You can read more on this [here](https://github.com/tgstation/tgstation/blob/master/code/__DEFINES/maps.dm). * If you are building station rooms on a lower Z level, ensure that a turf of some type is mapped on the Z-Level above the room to function as a "ceiling". You can check the coordinates in the Mapping Editor to ensure you map over the correct dimensions of the room. When running [the server to test the map](https://hackmd.io/@tgstation/SyVma0dS5#Testing-Your-Map), you can go to the Debug tab and hit "Mapping Verbs - Enable", go to Mapping tab and hit Show ATs. If the list is empty, you are good. * Earlier versions of Multi-Z did not require a baseturf to be defined under each Z-Level's traits in the config JSON. Each level must now have a baseturf set. * The maploader will not load and link a map file without areas or turfs defined. An empty space (nothing but baseturf) map will runtime. If you are adding a Z-level to an existing map, be aware of this. * SS13 will cache a map's configuration JSON file in `data\next_map.json`. If you alter a map's configuration JSON locally, you must also clear this file by using the change-map verb in game, deleting the file, or replacing it with your updated JSON file. --- ### On Loading Maps For running maps on your local server or adjusting the code for accomodate for your Pull Request, reference [this file](https://github.com/tgstation/tgstation/blob/master/.github/guides/MAPS_AND_AWAY_MISSIONS.md). --- ### On Areas Areas are pretty neat, they're the abstract placement of what you want a "room" to be. Knowing how to place good areas just typically comes from learning how other station/ruins (typically the newer ones) do it. #### Station Area Placement Remember: Maintenance owns all walls of its tunnels. No exceptions. There might be some weirdness with how different maintenances "possess" certain walls different sections share, but as long as one of the two owns it, it's good. You may be wondering "why is this"? There's two reasons that are 100% correct: 1. There has to be _some_ standard, and this one looks a lot less ugly than having 1-tile wide strips of area that only own the floor. 2. We have engravings in the game that randomly spawn on _walls_ that are in a maintenance area. If maintenance doesn't own walls, these engravings don't show up. That's the key reason why the change was made (for station mapping). #### When do I make a new area? Typically every time you make a new map or do some sort of remap, you should use the best area possible. This could mean re-using an area from another map, or making your own. Whenever something breaks as far as CI or Linters, we might pass along the typepath of the area along with that error. This is incredibly useful for debugging stuff (especially in production, after your map is merged to the codebase), and some issues are nearly impossible to find if non-unique areas are used. This is really important with ruins because we typically name those areas something like "Unknown Ruin", which is completely useless as far as debugging. However, if the ruin has a unique area, it becomes incredibly easier to figure out which ruin the error corresponds to (especially since ruins are randomly placed in Space Ruin Z-Levels) In instances like station mapping, you should be re-using areas from other stations. If nothing really works, please do make your own! It's much better to be more explicit with area names and placements than it is to not be for players. --- ### On Design **This section intentionally left unhelpful.** This document is entirely meant to teach solid foundational and technical aspects to mapping. I categorically refuse to strangle thoughts of design out of your head before [you've even sat down to map](#The-Inexorable-Passage-of-Time---A-Closing-Note), and this is a common belief among maptainers. If we don't like your design (different types of maps have different standards for quality), or think it should be improved somehow, you should only be informed of this when it is solicited: either asking for help or creating a Pull Request. Creative death occurs when you are taught to be uncreative or follow someone else's idea of what something should be. You may learn what you need to learn from other maps that you've played on or experienced, but never take something as gospel. Beauty comes from within, the important thing to do is to do everything technically correct so everyone can focus on making your design better. --- ## StrongDMM - A Little Bit More I personally hold StrongDMM 2.0+ to be the best tool available for BYOND mapping. It's versatility and the gross amount of features sets it apart from anything available presently (even older versions of StrongDMM). I will always recommend StrongDMM to mappers, and stand by it overall. Let's talk a little bit about the special ways you can leverage it. ### What You Should Know We already went over [the basics in the Guide To Mapping](https://hackmd.io/@tgstation/SyVma0dS5#StrongDMM-and-You-The-Basics). This is just an expansive list of stuff you might need to know as you slowly become a more active mapper. (WIP, potential topics are pre-fabrications, variable edit panel, window shuffling, etc.) ## Mapping Maintainability Tools ### Linters We've already briefly spoken about linters [here](https://hackmd.io/@tgstation/ry4-gbKH5#Merge-Conflict-Markers). To keep it brief, linters are a bunch of sanity checks using [Grep](https://en.wikipedia.org/wiki/Grep) to find very common errors as a form of "sanity check". This runs relatively quickly, so it's worth sticking around after you add a new commit to your Pull Request to ensure these pass. If linters fail, it's not typically for no reason. You just want to hit "Details" in the Continous Integration (or CI, for short) portion of your Pull Request. <img src="https://i.imgur.com/gWrrYTW.png" style="display: block; margin: 0 auto"/> Then, expand this category here, and see the error messages that crop up. <img src="https://i.imgur.com/Wpj091G.png" style="display: block; margin: 0 auto"/> If you're confused, don't be afraid to reach out for help in Mapping/Coding Channels. The errors are typically verbose and are "whoopsies!" level errors that tend to be easy to rectify. Just go back to your map, fix it, and then push the changes and be set from there. ### MapDiffBot2 It shows you the difference in a map before and after a proposed Pull Request. It's broken right now or I'd flesh this part out a bit more. (WIP) ### Unit Tests A lot of pain that can come along with failing CI can be rectified by checking out [map_errors.log](https://hackmd.io/@tgstation/SyVma0dS5#Checking-Logs). Typically, error messages will explain what's wrong and how to fix it. If you can't figure out what's wrong, send the error message to someone a bit more knowledgeable with screenshots of the affected area (the message will typically come with X/Y coordinates along with the failing area so you can piece it together). (WIP) ### MapTileAggregator This is pretty much just like [UpdatePaths](#UpdatePaths-And-You-), but a lot more task-oriented to "flattening" tile corner turf decals into their aggregate form (opposing/half/anticorner/full). That doesn't make sense, just read the [README here](https://github.com/tgstation/tgstation/tree/master/tools/MapTileAggregator). If you like mapping out tile turf decals the "old way", feel free to just run this before your make your PR in order to save someone asking you to run this script or someone else having to clean up after you. ## Having Fun Mapping(?) ### Timeframes Expect a full station map to take _years_ to map. Away missions will also take some time to map out as well. Just work on it at a pace you're comfortable with, and don't be afraid to take breaks. Your git history will be waiting for you when you get back (just be sure to push it to remote lest you lose all your work!) The best things in life take time. (WIP) ## The Pull Request Process on the Technical and Emotional Levels ### As A Contributor Follow the Pull Request template! You might gloss over some comments, but it is a great tool to guide you on what you need to do. (WIP) ### General Advicing #### Anyone can help. Here's how. Let's say you're ~~stalking~~ passing through the GitHub, and you spy a change that you want to leave advice on. You don't want to browser-download the specific files they changed, since they could have done it on a different version of the codebase that doesn't really reflect your version of the codebase. That's why *checking it out* is the absolute best option. [You need a fork, of course](https://hackmd.io/@tgstation/SyVma0dS5#GitHubcom-Operations). Here's a few simple ways to get started: If you use GitHub Desktop or the [GitHub CLI](https://cli.github.com/), you can use either of these options from the page of the Pull Request. Let's use [one of my favorites](https://github.com/tgstation/tgstation/pull/64304) as an example. <img src="https://i.imgur.com/FQlAt1O.png" style="display: block; margin: 0 auto"/> By hitting the "Code" button in the top right, you get to "check out" that branch in one of two ways. You either paste that command into the GitHub CLI, or just hit that button to have GitHub Desktop automatically load it (this tends to be a little finicky, I personally have to hit that button a few times). If you think either of those options are for tools, here's a Git Bash command. Just replace ``{PRNUMBERHERE}`` with the PR of your choosing. For this example, it would be 64304. Note: 'Upstream' may be named something different on your system, frequently 'origin'. Use the command `git remote -v` to list the names of your remotes. ``` git fetch upstream pull/{PRNUMBERHERE}/head:{PRNUMBERHERE} && git checkout {PRNUMBERHERE} ``` Then, after that command is done, you should have their branch on your computer. All ready for review! There are a few things that are quite important to keep into account during reviews. #### A Primer on Reviews People tell you how to fix things, or make some things look better. (WIP) #### Good Reviewing Practices * Be constructive. Do not be unconstructive/mean, you will likely get pruned from the PR discussion. * Do not submit "balance" changes as potential "fixes". * If someone doesn't see the wider picture, politely explain to them why something is the way it is. Sometimes, you'll realize as you type out your explanation that you were actually in the wrong the whole time! That's fine, we're all here to learn. * If you really like something and want to see it shine, ask the PR author if they can make contributions to their branch! Collaboration doesn't only exist after the PR is in the repository, it can definitely exist beforehand. Those were just the brief helpful tips. There's a much better document on this sort of stuff [here](https://rewind.com/blog/best-practices-for-reviewing-pull-requests-in-github/). ## The Inexorable Passage of Time - A Closing Note #### *This entire document is packed with what I've learned over the last few years, in the hopes that you too can also learn. This, however, is a lot less technical. I advise reading all of it.* The passage of time upsets all things. If you need a break, take one, but take this note: *History belongs to those who are around to enjoy it.* This is a codebase that has been, and will continue to be, a codebase welcoming to those wanting to toy with new changes. Those who are around re-form the game how they want it to be played, and the less *old guard* around to stop them, the more they can take. Yet, people move on. What about hostility? Why do new contributors face such ridicule? It may seem that way at first, but if you aren't obviously griefing, maintainers will let you down gentler than what you might expect (being cutthroat and rude for no real reason), and might try to help you realize your idea in a better vision. I hope we don't ever lose that tactful trend. If you leave for a bit and your work has been washed away, mixed in with the sands of times... just remember the good times that you had. The time you spent working on it, the times you enjoyed as other people poked through it, or even your own sense of satisfication being able to finally play with it after hours of work and even more time testing/being reviewed like a microbe on a slide. At the end of the day, people and their works shall change and shall continue to change (hopefully for the better). However, things will retain their structure. If someone changes parts of a station, it's not likely they'll discard some of the design cues you introduced, they (hopefully will) retain as much parity as possible. If you rework a department, they might re-rework that department to an adaptation of your work. The minor things tend to bleed their way in too, and stick for the longest amounts of time. We constantly expand and build on each other's work to make something greater and better, and it would be great if you were still a part of that number... yet sometimes, life- the real stuff- gets in the way. I hope that we never *truly regress* in map quality as we go forward, and I also hope that you can still appreciate the broader aspects of other people's work when they build on top of yours. Yet, life goes on. Enjoy it while you're here. Despite knowing what I just told you, map with passion. *Map with love.* Do that for me, won't you? ###### tags: `Guide` `Mapping` {%hackmd theme-dark %}