Files
Bubberstation/code/modules/shuttle/docking.dm
SkyratBot da30e9df00 [MIRROR] Should fix shuttles leaving without sections [MDB IGNORE] (#11407)
* Should fix shuttles leaving without sections(#64764)

Should(tm)

This was a suggestion by @ Mothblocks and it seemed easy to implement

Fixes #64546 (Icebox evac will sometimes leave without sections)
Fixes #64653 (You might have fixed the kilo whiteship by making it move, but you didn't fix all of it)

Uh people won't just randomly get yeeted into space with half of a shuttle.
Kinda funny for people watching but not if you die of pressure loss or get stuck on the station
Runtime man bad

(Sleeping in here in general is like admitting that we're ok with missing a few atoms, which is what this runtime is. S just missing is better then overtime. Supposedly --Lemon)

* Should fix shuttles leaving without sections

Co-authored-by: Jeremiah <42397676+jlsnow301@users.noreply.github.com>
2022-02-09 14:28:22 +00:00

222 lines
8.3 KiB
Plaintext

/// 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(admin_forced)
force = admin_forced
if(new_dock.get_docked() == src)
remove_ripples()
return DOCKING_SUCCESS
if(!force)
if(!check_dock(new_dock))
remove_ripples()
return DOCKING_BLOCKED
if(!canMove())
remove_ripples()
return DOCKING_IMMOBILIZED
var/obj/docking_port/stationary/old_dock = get_docked()
// The area that gets placed under where the shuttle moved from
var/underlying_area_type = SHUTTLE_DEFAULT_UNDERLYING_AREA
if(old_dock) //Dock overwrites
underlying_area_type = old_dock.area_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 = GLOB.areas_by_type[underlying_area_type]
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
. = preflight_check(old_turfs, new_turfs, areas_to_move, rotation)
if(.)
remove_ripples()
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))
remove_ripples()
return DOCKING_BLOCKED
if(!canMove())
remove_ripples()
return DOCKING_IMMOBILIZED
// Moving to the new location will trample the ripples there at the exact
// same time any mobs there are trampled, to avoid any discrepancy where
// the ripples go away before it is safe.
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)
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)
// remove any stragglers just in case, and clear the list
remove_ripples()
return DOCKING_SUCCESS
/obj/docking_port/mobile/proc/preflight_check(list/old_turfs, list/new_turfs, list/areas_to_move, rotation)
for(var/i in 1 to length(old_turfs))
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
for(var/atom/movable/moving_atom as anything in oldT.contents)
CHECK_TICK
if(moving_atom.loc != oldT) //fix for multi-tile objects
continue
move_mode = moving_atom.beforeShuttleMove(newT, rotation, move_mode, src) //atoms
move_mode = oldT.fromShuttleMove(newT, 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_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
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
/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_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/old_turf = old_turfs[i]
var/turf/new_turf = new_turfs[i]
new_turf.afterShuttleMove(old_turf, rotation) //turfs
var/turf/new_ceiling = get_step_multiz(new_turf, UP) // check if a ceiling is needed
if(new_ceiling)
// generate ceiling
if(istype(new_ceiling, /turf/open/openspace)) // why is this needed? because we have 2 different typepaths for openspace
new_ceiling.ChangeTurf(/turf/open/floor/engine/hull/ceiling, list(/turf/open/openspace))
else if (istype(new_ceiling, /turf/open/space/openspace))
new_ceiling.ChangeTurf(/turf/open/floor/engine/hull/ceiling, list(/turf/open/space/openspace))
var/turf/old_ceiling = get_step_multiz(old_turf, UP)
if(old_ceiling && istype(old_ceiling, /turf/open/floor/engine/hull/ceiling)) // check if a ceiling was generated previously
// remove old ceiling
var/turf/open/floor/engine/hull/ceiling/old_shuttle_ceiling = old_ceiling
old_shuttle_ceiling.ChangeTurf(old_shuttle_ceiling.old_turf_type)
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
// lateShuttleMove (There had better be a really good reason for additional stages beyond this)
underlying_old_area.lateShuttleMove()
for(var/i in 1 to areas_to_move.len)
CHECK_TICK
var/area/internal_area = areas_to_move[i]
internal_area.lateShuttleMove()
for(var/i in 1 to old_turfs.len)
CHECK_TICK
if(!(old_turfs[old_turfs[i]] & MOVE_CONTENTS | MOVE_TURF))
continue
var/turf/oldT = old_turfs[i]
var/turf/newT = new_turfs[i]
newT.lateShuttleMove(oldT)
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.lateShuttleMove(oldT, movement_force, movement_direction)