# Multi-Z Writeup
This document outlines technical design for proper multi-z on wizden code. My goals with multi-z is to support space, shuttles, grid splitting, visualizing other z levels, better multi-z combat, etc. This doc is by no means final and will change as I work on the feature.
## Development Plan
Here I will list the planned order of development. I will link PRs here and if a section is in progress.
1. Saving/loading - In progress
2. Cheat Traversal
4. Fixtures
5. Roofs
6. Rendering
7. Traversal
8. Atmos and power
9. Shuttles
10. Space
11. Ruins
12. Planet map support if needed
13. Misc combat changes
## Map Data
Multi-z maps will be stored as a seperate map for each z-level with multiple grids for each z-level. These maps will be saved in the same .yml files and will be saved by a new command something like savemapmultiz(path, maps in order from lowest to highest). Multi-z maps will contain a multi-z map component on each map which specifies the parent(lowest z level) and its own level. Multi-z grids without maps (shuttles or ruins) could be saved as seperate grids in the same .yml with an object or component specifying what grids to load as higher levels. Potentially z-levels could be completly dynamic with z-level maps get generated/removed when requested by a grid, allowing for an infinite amount of positive or negative z-levels.
## Attaching Grids
Multi-z maps have two potential ways of functioning physics wise. First way is for floors of the higher level to act as roofs for the lower level. This would also mean higher levels are directly attached to lower levels, seperating when all wall or pillar connections are severed. The second way is to specify roofs and floors for each z-level, attaching them via dedicated entities. Below is a drawing of what I mean here.

Method one avoids dedicated roofs which avoids some potential confusion and is closest to the way 13 multi-z works, but makes shuttles and the top z-level a bit weird. Method 2 would solve the shuttle and top z-level issues entirely but potentially introduce mapping complexity, and needs a dedicated way of linking grids. This is where either anchors can come in as attachment points for grids. These anchors will not lock rotation unless two are used and can attach grids at off angles. The anchors should also support grid splitting and collisions natively. I will be going with method 2 but I think its important to outline the options here for clarity.
## Fixtures
Multi-z fixtures are entitys which exist on multiple z-levels at the same time. Examples are anchors(Mentioned above), pipe connectors and cable connectors. These should be functionally two seperate entitys which specifiy how they are connected in a component. Multi-z fixtures should be built sperately by players get linked by activating them somehow on one of the layers while they are close enough. Mappers should have a marker entity which spawns the two entitys and connects them on map initialization. Non anchor fixtures should have no physics linkage and should unlink when the two grids move away from eachother, possibly with a sfx. Anchor fixtures could have involnerable and destructable versions to avoid a whole station pivoting on a single anchor or other similar jank.
## Rendering
Rendering is something I still need to figure out on a higher level. There was an old PR which did multi-z by fully rendering all z-levels seperately and compositing them together afterwards. This is terrible for performance as it renders overlays twice and kills vram. Im not entirely sure how to do this properly yet but it must take heavy consideration to performance. Multi-z holes will likely use parallax and baked AO to give the illusion of depth between layers. Lighting will also work between z-levels but details need working out.
## Traversal
The main methods of traversal will be ladders, stairs, falling and moving in 0g. Ladders should work with lmb to go up and rmb to go down, with a doafter and sfx for each action. Stairs should raise and lower entity sprites when traversing until reaching the top, at which point they teleport to the target. Walking on stairs should be blocked by the celing/floor and should have seperate up/down sprite varients for clarity. Stairs should also block moving on/off of them from the sides to prevent janky movement. Stairs in particular should partially load the target map when getting close to keep them seemless, though all methods of z-level traversal should do this to some degree. Falling should lower the entities sprite quickly at a rate concistant(or close) with gravity. Moving in 0g(or any similar generic traversal) should have UI buttons and easy to use default keybindings.
## Shuttles
Open space should be as close to single z-level as possible, with multi-z being restricted to nearby multi-z stations or shuttles. This can be accomplished by forcing grids on higher z-levels to lower z-levels when getting too far away from multi-z anchors/grids. The existing multi-z maps stay attached to the primary map but have restricted access. This system would allow z-level counts of stations/shuttles/ruins to be independant of eachother while being on the same primary map.
Shuttles should be able to move up and down z-levels from the shuttle console when in multi-z range. This should be indicated using ghosts/holograms/tiles and sfx before the grid teleports, see cm/rmc dropships for an example. Entities or grids in the way shouldnt be crushed by shuttles and should instead the move should be delayed while the entities or grids get shoved out of the way, only making the move once the zone is clear.
## Ruins and the Roof Issue
Ruins and other space generation should be restricted entirely to the primary z-level map, unless a ruin has its own multi-z. An issue shows itself with ruins and multi-z shuttles however. Bringing a multi-z shuttle to a ruin or a ruin to a multi-z station will allow players to get ontop of the ruin. This will cause huge issues if the player is allowed to break in through the roof, bypassing ruins designed with single-z in mind.
One potential solution is to just autogenerate an invincible roof but this has a few issues of its own. Firstly this prevents single-z ruins from having sections of exposed sky without it introducing another unintended path of entry. Another issue is that players could potentially go under a single-z ruin with a negative multi-z shuttle and break in that way, though negative multi-z should idealy be unused outside of main station designs. Having invincibile roofs could also get exploited by players when building shuttles from a ruins grid. I dont have anymore ideas here yet so for now this is the only option.
## Combat
Combat is a big concern with multi-z as it can be either really bland or unfair depending on how its setup. Multi-z can let players on higher z-levels with line of sight downwards see players way before the lower players. This means a player at the bottom of stairs could walk up those stairs and get imedietly attacked the moment they teleport upwards. This also lets stairs function like teleporters where moving very slightly puts you entirely out of harms way in melee and ranged combat.
My solution to visability is to add indicators to nearby visable players who are up/down z-levels. These indicators should always be visable in normal view or maybe when combat mode is enabled. They should also show the sprite of the indicated player so bloodreds cant just camp stairs. My solution to stair combat feeling like teleporters is for a player on stairs to be hitable on both z-levels when standing on stairs. This should prevent stair abuse in combat
## Helpful links and notes
an issue outlining some multiz issues
https://github.com/space-wizards/space-station-14/issues/7925
the april fools multiz pr
https://github.com/space-wizards/space-station-14/pull/15033
https://github.com/space-wizards/space-station-14/pull/15009
MapID serialization support which was merged at the perfect time
https://github.com/space-wizards/RobustToolbox/pull/6165
Post in the discord about multiz
https://discord.com/channels/310555209753690112/1008709214006427689/1074877600431870032
### Projections
Projections were moved here because its not really relavent and should be its own thing.
Lighting and line of sight could be calcuated using projections from player eyes or light sources. The idea is to find an end polygon from a start polygon and a point. The point is either a players eye(based on the characters x,y position and hight) and the start polygon is the hole in the floor or celing. You can then scale the start polygon using the point as an orign and the distance between the startings level and targets level as the factor. This results in the target polygon which can be used for line of sight and lighting calculations. Refraction can also be added to the equation if we want to manipulate the effect that way, though its hard to tell how helpful that is without testing.
