Merge pull request #4449 from Citadel-Station-13/upstream-merge-33627

[MIRROR] dock() re-organization
This commit is contained in:
LetterJay
2017-12-27 07:01:40 -06:00
committed by GitHub
13 changed files with 262 additions and 218 deletions
+6
View File
@@ -75,3 +75,9 @@
#define SHUTTLE_DOCKER_LANDING_CLEAR 1
#define SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT 2
#define SHUTTLE_DOCKER_BLOCKED 3
//Shuttle defaults
#define SHUTTLE_DEFAULT_TURF_TYPE /turf/open/space
#define SHUTTLE_DEFAULT_BASETURF_TYPE /turf/open/space
#define SHUTTLE_DEFAULT_SHUTTLE_AREA_TYPE /area/shuttle
#define SHUTTLE_DEFAULT_UNDERLYING_AREA /area/space
+2 -2
View File
@@ -400,7 +400,7 @@ SUBSYSTEM_DEF(shuttle)
if(M.request(getDock(destination)))
return 2
else
if(M.dock(getDock(destination)) != DOCKING_SUCCESS)
if(M.initiate_docking(getDock(destination)) != DOCKING_SUCCESS)
return 2
return 0 //dock successful
@@ -415,7 +415,7 @@ SUBSYSTEM_DEF(shuttle)
if(M.request(D))
return 2
else
if(M.dock(D) != DOCKING_SUCCESS)
if(M.initiate_docking(D) != DOCKING_SUCCESS)
return 2
return 0 //dock successful
+1 -1
View File
@@ -110,7 +110,7 @@
anchored = TRUE
/obj/effect/shuttle_build/New()
SSshuttle.emergency.dock(SSshuttle.getDock("emergency_home"))
SSshuttle.emergency.initiate_docking(SSshuttle.getDock("emergency_home"))
qdel(src)
//Arena
+1 -1
View File
@@ -206,7 +206,7 @@
if(engines_cooling)
return "[.] - Engines cooling."
/obj/docking_port/mobile/pirate/dock(obj/docking_port/stationary/new_dock, movement_direction, force=FALSE)
/obj/docking_port/mobile/pirate/initiate_docking(obj/docking_port/stationary/new_dock, movement_direction, force=FALSE)
. = ..()
if(. == DOCKING_SUCCESS && new_dock.z != ZLEVEL_TRANSIT)
engines_cooling = TRUE
+1 -1
View File
@@ -137,7 +137,7 @@
hyperspace_sound(HYPERSPACE_LAUNCH, areas) //for the new guy
setTimer(dockTime)
/obj/docking_port/mobile/arrivals/dock(obj/docking_port/stationary/S1, force=FALSE)
/obj/docking_port/mobile/arrivals/initiate_docking(obj/docking_port/stationary/S1, force=FALSE)
var/docked = S1 == assigned_transit
sound_played = FALSE
if(docked) //about to launch
+1 -1
View File
@@ -10,7 +10,7 @@
return ..()
/obj/docking_port/mobile/assault_pod/dock(obj/docking_port/stationary/S1)
/obj/docking_port/mobile/assault_pod/initiate_docking(obj/docking_port/stationary/S1)
. = ..()
if(!istype(S1, /obj/docking_port/stationary/transit))
playsound(get_turf(src.loc), 'sound/effects/explosion1.ogg',50,1)
+230
View File
@@ -0,0 +1,230 @@
//this is the main proc. It instantly moves our mobile port to stationary port new_dock
/obj/docking_port/mobile/proc/initiate_docking(obj/docking_port/stationary/new_dock, movement_direction, force=FALSE)
// Crashing this ship with NO SURVIVORS
if(new_dock.get_docked() == src)
remove_ripples()
return DOCKING_SUCCESS
if(!force)
if(!check_dock(new_dock))
return DOCKING_BLOCKED
if(!canMove())
return DOCKING_IMMOBILIZED
var/obj/docking_port/stationary/old_dock = get_docked()
// The turf that gets placed under where the shuttle moved from
var/underlying_turf_type = SHUTTLE_DEFAULT_TURF_TYPE
// The baseturf that the gets assigned to the turf_type above
var/underlying_baseturf_type = SHUTTLE_DEFAULT_BASETURF_TYPE
// The area that gets placed under where the shuttle moved from
var/underlying_area_type = SHUTTLE_DEFAULT_UNDERLYING_AREA
// The baseturf cache is a typecache of what counts as a baseturf to be left behind
var/list/baseturf_cache
if(old_dock) //Dock overwrites
underlying_turf_type = old_dock.turf_type
underlying_baseturf_type = old_dock.baseturf_type
underlying_area_type = old_dock.area_type
baseturf_cache = old_dock.baseturf_cache
else
baseturf_cache = typecacheof(underlying_baseturf_type)
/**************************************************************************************************************
Both lists are associative with a turf:bitflag structure. (new_turfs bitflag space unused currently)
The bitflag contains the data for what inhabitants of that coordinate should be moved to the new location
The bitflags can be found in __DEFINES/shuttles.dm
*/
var/list/old_turfs = return_ordered_turfs(x, y, z, dir)
var/list/new_turfs = return_ordered_turfs(new_dock.x, new_dock.y, new_dock.z, new_dock.dir)
CHECK_TICK
/**************************************************************************************************************/
// The underlying old area is the area assumed to be under the shuttle's starting location
// If it no longer/has never existed it will be created
var/area/underlying_old_area = locate(underlying_area_type) in GLOB.sortedAreas
if(!underlying_old_area)
underlying_old_area = new underlying_area_type(null)
var/rotation = 0
if(new_dock.dir != dir) //Even when the dirs are the same rotation is coming out as not 0 for some reason
rotation = dir2angle(new_dock.dir)-dir2angle(dir)
if ((rotation % 90) != 0)
rotation += (rotation % 90) //diagonal rotations not allowed, round up
rotation = SIMPLIFY_DEGREES(rotation)
if(!movement_direction)
movement_direction = turn(preferred_direction, 180)
var/list/moved_atoms = list() //Everything not a turf that gets moved in the shuttle
var/list/areas_to_move = list() //unique assoc list of areas on turfs being moved
remove_ripples()
. = preflight_check(old_turfs, new_turfs, areas_to_move, rotation, underlying_turf_type, baseturf_cache)
if(.)
return
/*******************************************Hiding turfs if necessary*******************************************/
// TODO: Move this somewhere sane
var/list/new_hidden_turfs
if(hidden)
new_hidden_turfs = list()
for(var/i in 1 to old_turfs.len)
CHECK_TICK
var/turf/oldT = old_turfs[i]
if(old_turfs[oldT] & MOVE_TURF)
new_hidden_turfs += new_turfs[i]
SSshuttle.update_hidden_docking_ports(null, new_hidden_turfs)
/***************************************************************************************************************/
if(!force)
if(!check_dock(new_dock))
return DOCKING_BLOCKED
if(!canMove())
return DOCKING_IMMOBILIZED
CHECK_TICK
takeoff(old_turfs, new_turfs, moved_atoms, rotation, movement_direction, old_dock, underlying_old_area)
CHECK_TICK
cleanup_runway(new_dock, old_turfs, new_turfs, areas_to_move, moved_atoms, rotation, movement_direction, underlying_old_area, underlying_turf_type, underlying_baseturf_type)
CHECK_TICK
/*******************************************Unhiding turfs if necessary******************************************/
if(new_hidden_turfs)
SSshuttle.update_hidden_docking_ports(hidden_turfs, null)
hidden_turfs = new_hidden_turfs
/****************************************************************************************************************/
check_poddoors()
new_dock.last_dock_time = world.time
setDir(new_dock.dir)
return DOCKING_SUCCESS
/obj/docking_port/mobile/proc/preflight_check(
list/old_turfs,
list/new_turfs,
list/areas_to_move,
rotation,
underlying_turf_type,
baseturf_cache,
)
for(var/i in 1 to old_turfs.len)
CHECK_TICK
var/turf/oldT = old_turfs[i]
var/turf/newT = new_turfs[i]
if(!newT)
return DOCKING_NULL_DESTINATION
if(!oldT)
return DOCKING_NULL_SOURCE
var/area/old_area = oldT.loc
var/move_mode = old_area.beforeShuttleMove(shuttle_areas) //areas
var/list/old_contents = oldT.contents
for(var/k in 1 to old_contents.len)
CHECK_TICK
var/atom/movable/moving_atom = old_contents[k]
if(moving_atom.loc != oldT) //fix for multi-tile objects
continue
move_mode = moving_atom.beforeShuttleMove(newT, rotation, move_mode) //atoms
move_mode = oldT.fromShuttleMove(newT, underlying_turf_type, baseturf_cache, move_mode) //turfs
move_mode = newT.toShuttleMove(oldT, move_mode , src) //turfs
if(move_mode & MOVE_AREA)
areas_to_move[old_area] = TRUE
old_turfs[oldT] = move_mode
/obj/docking_port/mobile/proc/takeoff(
list/old_turfs,
list/new_turfs,
list/moved_atoms,
rotation,
movement_direction,
old_dock,
area/underlying_old_area,
)
for(var/i in 1 to old_turfs.len)
var/turf/oldT = old_turfs[i]
var/turf/newT = new_turfs[i]
var/move_mode = old_turfs[oldT]
if(move_mode & MOVE_CONTENTS)
for(var/k in oldT)
var/atom/movable/moving_atom = k
if(moving_atom.loc != oldT) //fix for multi-tile objects
continue
moving_atom.onShuttleMove(newT, oldT, movement_force, movement_direction, old_dock, src) //atoms
moved_atoms[moving_atom] = oldT
if(move_mode & MOVE_TURF)
oldT.onShuttleMove(newT, movement_force, movement_direction) //turfs
if(move_mode & MOVE_AREA)
var/area/shuttle_area = oldT.loc
shuttle_area.onShuttleMove(oldT, newT, underlying_old_area) //areas
/obj/docking_port/mobile/proc/cleanup_runway(
obj/docking_port/stationary/new_dock,
list/old_turfs,
list/new_turfs,
list/areas_to_move,
list/moved_atoms,
rotation,
movement_direction,
area/underlying_old_area,
underlying_turf_type,
underlying_baseturf_type,
)
underlying_old_area.afterShuttleMove()
// Parallax handling
// This needs to be done before the atom after move
var/new_parallax_dir = FALSE
if(istype(new_dock, /obj/docking_port/stationary/transit))
new_parallax_dir = preferred_direction
for(var/i in 1 to areas_to_move.len)
CHECK_TICK
var/area/internal_area = areas_to_move[i]
internal_area.afterShuttleMove(new_parallax_dir) //areas
for(var/i in 1 to old_turfs.len)
CHECK_TICK
if(!(old_turfs[old_turfs[i]] & MOVE_TURF))
continue
var/turf/oldT = old_turfs[i]
var/turf/newT = new_turfs[i]
newT.afterShuttleMove(oldT, underlying_turf_type, underlying_baseturf_type, rotation) //turfs
for(var/i in 1 to moved_atoms.len)
CHECK_TICK
var/atom/movable/moved_object = moved_atoms[i]
if(QDELETED(moved_object))
continue
var/turf/oldT = moved_atoms[moved_object]
moved_object.afterShuttleMove(oldT, movement_force, dir, preferred_direction, movement_direction, rotation)//atoms
for(var/i in 1 to old_turfs.len)
CHECK_TICK
// Objects can block air so either turf or content changes means an air update is needed
if(!(old_turfs[old_turfs[i]] & MOVE_CONTENTS | MOVE_TURF))
continue
var/turf/oldT = old_turfs[i]
var/turf/newT = new_turfs[i]
oldT.blocks_air = initial(oldT.blocks_air)
oldT.air_update_turf(TRUE)
newT.blocks_air = initial(newT.blocks_air)
newT.air_update_turf(TRUE)
+1 -1
View File
@@ -7,4 +7,4 @@
movement_force = list("KNOCKDOWN" = 0, "THROW" = 0)
/obj/docking_port/mobile/elevator/request(obj/docking_port/stationary/S) //No transit, no ignition, just a simple up/down platform
dock(S, TRUE)
initiate_docking(S, TRUE)
+1 -1
View File
@@ -290,7 +290,7 @@
if(SHUTTLE_CALL)
if(time_left <= 0)
//move emergency shuttle to station
if(dock(SSshuttle.getDock("emergency_home")) != DOCKING_SUCCESS)
if(initiate_docking(SSshuttle.getDock("emergency_home")) != DOCKING_SUCCESS)
setTimer(20)
return
mode = SHUTTLE_DOCKED
+1 -1
View File
@@ -222,7 +222,7 @@
existing_shuttle.jumpToNullSpace()
preview_shuttle.dock(D)
preview_shuttle.initiate_docking(D)
. = preview_shuttle
// Shuttle state involves a mode and a timer based on world.time, so
+15 -208
View File
@@ -159,9 +159,9 @@
/obj/docking_port/stationary
name = "dock"
turf_type = /turf/open/space
baseturf_type = /turf/open/space
area_type = /area/space
turf_type = SHUTTLE_DEFAULT_TURF_TYPE
baseturf_type = SHUTTLE_DEFAULT_BASETURF_TYPE
area_type = SHUTTLE_DEFAULT_UNDERLYING_AREA
var/list/baseturf_cache
@@ -203,7 +203,7 @@
for(var/i in 1 to assigned_turfs.len)
var/turf/T = assigned_turfs[i]
if(T.type == turf_type)
T.ChangeTurf(/turf/open/space,/turf/open/space)
T.ChangeTurf(SHUTTLE_DEFAULT_TURF_TYPE, SHUTTLE_DEFAULT_BASETURF_TYPE)
T.flags_1 |= UNUSED_TRANSIT_TURF_1
/obj/docking_port/stationary/transit/Destroy(force=FALSE)
@@ -224,9 +224,9 @@
name = "shuttle"
icon_state = "pinonclose"
area_type = /area/shuttle
area_type = SHUTTLE_DEFAULT_SHUTTLE_AREA_TYPE
var/list/area/shuttle/shuttle_areas
var/list/shuttle_areas
var/timer //used as a timer (if you want time left to complete move, use timeLeft proc)
var/last_timer_length
@@ -400,7 +400,7 @@
var/obj/docking_port/stationary/S0 = get_docked()
var/obj/docking_port/stationary/S1 = assigned_transit
if(S1)
if(dock(S1) != DOCKING_SUCCESS)
if(initiate_docking(S1) != DOCKING_SUCCESS)
WARNING("shuttle \"[id]\" could not enter transit space. Docked at [S0 ? S0.id : "null"]. Transit dock [S1 ? S1.id : "null"].")
else
previous = S0
@@ -413,9 +413,9 @@
// Not in a fancy way, it just ceases.
var/obj/docking_port/stationary/current_dock = get_docked()
var/turf_type = /turf/open/space
var/baseturf_type = /turf/open/space
var/underlying_area_type = /area/space
var/turf_type = SHUTTLE_DEFAULT_TURF_TYPE
var/baseturf_type = SHUTTLE_DEFAULT_BASETURF_TYPE
var/underlying_area_type = SHUTTLE_DEFAULT_UNDERLYING_AREA
// If the shuttle is docked to a stationary port, restore its normal
// "empty" area and turf
if(current_dock)
@@ -474,197 +474,6 @@
for(var/obj/machinery/door/poddoor/shuttledock/pod in GLOB.airlocks)
pod.check()
//this is the main proc. It instantly moves our mobile port to stationary port new_dock
/obj/docking_port/mobile/proc/dock(obj/docking_port/stationary/new_dock, movement_direction, force=FALSE)
// Crashing this ship with NO SURVIVORS
if(new_dock.get_docked() == src)
remove_ripples()
return DOCKING_SUCCESS
if(!force)
if(!check_dock(new_dock))
return DOCKING_BLOCKED
if(!canMove())
return DOCKING_IMMOBILIZED
var/obj/docking_port/stationary/old_dock = get_docked()
// The turf that gets placed under where the shuttle moved from
var/underlying_turf_type = /turf/open/space
// The baseturf that the gets assigned to the turf_type above
var/underlying_baseturf_type = /turf/open/space
// The area that gets placed under where the shuttle moved from
var/underlying_area_type = /area/space
// The baseturf cache is a typecache of what counts as a baseturf to be left behind
var/list/baseturf_cache
if(old_dock) //Dock overwrites
if(old_dock.turf_type)
underlying_turf_type = old_dock.turf_type
if(old_dock.baseturf_type)
underlying_baseturf_type = old_dock.baseturf_type
if(old_dock.area_type)
underlying_area_type = old_dock.area_type
if(old_dock.baseturf_cache)
baseturf_cache = old_dock.baseturf_cache
if(!baseturf_cache)
baseturf_cache = typecacheof(underlying_baseturf_type)
/**************************************************************************************************************
old_turfs is an associative list with a turf:bitflag structure
new_turfs is a standard list composed of turf instances
The bitflag contains the data for what inhabitants of that coordinate should be moved to the new location
The bitflags can be found in __DEFINES/shuttles.dm
*/
var/list/old_turfs = return_ordered_turfs(x, y, z, dir)
var/list/new_turfs = return_ordered_turfs(new_dock.x, new_dock.y, new_dock.z, new_dock.dir)
/**************************************************************************************************************/
// The underlying old area is the area assumed to be under the shuttle's starting location
// If it no longer/has never existed it will be created
var/area/underlying_old_area = locate(underlying_area_type) in GLOB.sortedAreas
if(!underlying_old_area)
underlying_old_area = new underlying_area_type(null)
var/rotation = 0
if(new_dock.dir != dir) //Even when the dirs are the same rotation is coming out as not 0 for some reason
rotation = dir2angle(new_dock.dir)-dir2angle(dir)
if ((rotation % 90) != 0)
rotation += (rotation % 90) //diagonal rotations not allowed, round up
rotation = SIMPLIFY_DEGREES(rotation)
if(!movement_direction)
movement_direction = turn(preferred_direction, 180)
remove_ripples()
var/list/moved_atoms = list() //Everything not a turf that gets moved in the shuttle
var/list/areas_to_move = list() //unique assoc list of areas on turfs being moved
CHECK_TICK
/****************************************All beforeShuttleMove procs*****************************************/
for(var/i in 1 to old_turfs.len)
CHECK_TICK
var/turf/oldT = old_turfs[i]
var/turf/newT = new_turfs[i]
if(!newT)
return DOCKING_NULL_DESTINATION
if(!oldT)
return DOCKING_NULL_SOURCE
var/area/old_area = oldT.loc
var/move_mode = old_area.beforeShuttleMove(shuttle_areas) //areas
var/list/old_contents = oldT.contents
for(var/k in 1 to old_contents.len)
CHECK_TICK
var/atom/movable/moving_atom = old_contents[k]
if(moving_atom.loc != oldT) //fix for multi-tile objects
continue
move_mode = moving_atom.beforeShuttleMove(newT, rotation, move_mode) //atoms
move_mode = oldT.fromShuttleMove(newT, underlying_turf_type, baseturf_cache, move_mode) //turfs
move_mode = newT.toShuttleMove(oldT, move_mode , src) //turfs
if(move_mode & MOVE_AREA)
areas_to_move[old_area] = TRUE
old_turfs[oldT] = move_mode
/*******************************************Hiding turfs if necessary*******************************************/
var/list/new_hidden_turfs
if(hidden)
new_hidden_turfs = list()
for(var/i in 1 to old_turfs.len)
CHECK_TICK
var/turf/oldT = old_turfs[i]
if(old_turfs[oldT] & MOVE_TURF)
new_hidden_turfs += new_turfs[i]
SSshuttle.update_hidden_docking_ports(null, new_hidden_turfs)
/*******************************************All onShuttleMove procs******************************************/
CHECK_TICK
for(var/i in 1 to old_turfs.len)
var/turf/oldT = old_turfs[i]
var/turf/newT = new_turfs[i]
var/move_mode = old_turfs[oldT]
if(move_mode & MOVE_CONTENTS)
for(var/k in oldT)
var/atom/movable/moving_atom = k
if(moving_atom.loc != oldT) //fix for multi-tile objects
continue
moving_atom.onShuttleMove(newT, oldT, movement_force, movement_direction, old_dock, src) //atoms
moved_atoms[moving_atom] = oldT
if(move_mode & MOVE_TURF)
oldT.onShuttleMove(newT, movement_force, movement_direction) //turfs
if(move_mode & MOVE_AREA)
var/area/shuttle_area = oldT.loc
shuttle_area.onShuttleMove(oldT, newT, underlying_old_area) //areas
/******************************************All afterShuttleMove procs****************************************/
underlying_old_area.afterShuttleMove()
// Parallax handling
// This needs to be done before the atom after move
var/new_parallax_dir = FALSE
if(istype(new_dock, /obj/docking_port/stationary/transit))
new_parallax_dir = preferred_direction
for(var/i in 1 to areas_to_move.len)
CHECK_TICK
var/area/internal_area = areas_to_move[i]
internal_area.afterShuttleMove(new_parallax_dir) //areas
for(var/i in 1 to old_turfs.len)
CHECK_TICK
if(!(old_turfs[old_turfs[i]] & MOVE_TURF))
continue
var/turf/oldT = old_turfs[i]
var/turf/newT = new_turfs[i]
newT.afterShuttleMove(oldT, underlying_turf_type, underlying_baseturf_type, rotation) //turfs
for(var/i in 1 to moved_atoms.len)
CHECK_TICK
var/atom/movable/moved_object = moved_atoms[i]
if(QDELETED(moved_object))
continue
var/turf/oldT = moved_atoms[moved_object]
moved_object.afterShuttleMove(oldT, movement_force, dir, preferred_direction, movement_direction, rotation)//atoms
for(var/i in 1 to old_turfs.len)
CHECK_TICK
// Objects can block air so either turf or content changes means an air update is needed
if(!(old_turfs[old_turfs[i]] & MOVE_CONTENTS | MOVE_TURF))
continue
var/turf/oldT = old_turfs[i]
var/turf/newT = new_turfs[i]
oldT.blocks_air = initial(oldT.blocks_air)
oldT.air_update_turf(TRUE)
newT.blocks_air = initial(newT.blocks_air)
newT.air_update_turf(TRUE)
/*******************************************Unhiding turfs if necessary******************************************/
if(new_hidden_turfs)
SSshuttle.update_hidden_docking_ports(hidden_turfs, null)
hidden_turfs = new_hidden_turfs
check_poddoors()
new_dock.last_dock_time = world.time
setDir(new_dock.dir)
return DOCKING_SUCCESS
/obj/docking_port/mobile/proc/findRoundstartDock()
return SSshuttle.getDock(roundstart_move)
@@ -674,7 +483,7 @@
/obj/docking_port/mobile/proc/dock_id(id)
var/port = SSshuttle.getDock(id)
if(port)
. = dock(port)
. = initiate_docking(port)
else
. = null
@@ -694,9 +503,9 @@
// then try again
switch(mode)
if(SHUTTLE_CALL)
var/error = dock(destination, preferred_direction)
var/error = initiate_docking(destination, preferred_direction)
if(error && error & (DOCKING_NULL_DESTINATION | DOCKING_NULL_SOURCE))
var/msg = "A mobile dock in transit exited dock() with an error. This is most likely a mapping problem: Error: [error], ([src]) ([previous])"
var/msg = "A mobile dock in transit exited initiate_docking() with an error. This is most likely a mapping problem: Error: [error], ([src]) ([previous])"
WARNING(msg)
message_admins(msg)
mode = SHUTTLE_IDLE
@@ -705,7 +514,7 @@
setTimer(20)
return
if(SHUTTLE_RECALL)
if(dock(previous) != DOCKING_SUCCESS)
if(initiate_docking(previous) != DOCKING_SUCCESS)
setTimer(20)
return
if(SHUTTLE_IGNITING)
@@ -933,10 +742,8 @@
/obj/docking_port/mobile/pod/on_emergency_dock()
if(launch_status == ENDGAME_LAUNCHED)
dock(SSshuttle.getDock("[id]_away")) //Escape pods dock at centcom
initiate_docking(SSshuttle.getDock("[id]_away")) //Escape pods dock at centcom
mode = SHUTTLE_ENDGAME
/obj/docking_port/mobile/emergency/on_emergency_dock()
return
#undef DOCKING_PORT_HIGHLIGHT
+1 -1
View File
@@ -64,7 +64,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
return 2
return ..()
/obj/docking_port/mobile/supply/dock()
/obj/docking_port/mobile/supply/initiate_docking()
if(getDockedId() == "supply_away") // Buy when we leave home.
buy()
. = ..() // Fly/enter transit.
+1
View File
@@ -2301,6 +2301,7 @@
#include "code\modules\shuttle\arrivals.dm"
#include "code\modules\shuttle\assault_pod.dm"
#include "code\modules\shuttle\computer.dm"
#include "code\modules\shuttle\docking.dm"
#include "code\modules\shuttle\elevator.dm"
#include "code\modules\shuttle\emergency.dm"
#include "code\modules\shuttle\ferry.dm"