mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-26 14:39:58 +01:00
Enchanced docking behaviour for airlock_pump (#86944)
## About The Pull Request Now after docking pump measure pressure on docked airlock, if it's in safe range both airlock sides will open for easy boarding process, instead just switching them like access airlocks If docked entity pressure is lower then internal, then airlock will cycle only to external pressure, not to vacuum. Also if opening airlocks, eash door also measures external pressure, to safe the day from bad pilot, when half of doors docked and other half still looking into space. With new qol features pump now automatically detects docking\undocking to minimize vacuuming and extra headbumps. Described behaviours tested, and work even for airlocks installed on shuttles, evac included, but night coding is messy, so a review will be nice. ## Why It's Good For The Game If engis decide to build custom departure this feature should prevent crew from screaming "Malf AI" and speed up boarding\unboarding process (May be after this people will start to love those pumps) ## Changelog 🆑 qol: Airlock_pump now dock with shuttles in more pleasant way /🆑
This commit is contained in:
@@ -18,9 +18,9 @@
|
||||
update_appearance()
|
||||
|
||||
/// Forces the airlock to close and bolt
|
||||
/obj/machinery/door/airlock/proc/secure_close()
|
||||
/obj/machinery/door/airlock/proc/secure_close(force_crush = FALSE)
|
||||
locked = FALSE
|
||||
close(forced = TRUE)
|
||||
close(forced = TRUE, force_crush = force_crush)
|
||||
|
||||
locked = TRUE
|
||||
stoplag(0.2 SECONDS)
|
||||
|
||||
@@ -48,6 +48,8 @@
|
||||
var/allowed_pressure_error = ONE_ATMOSPHERE / 100
|
||||
///Minimal distro pressure to start cycling
|
||||
var/min_distro_pressure = ONE_ATMOSPHERE / 10
|
||||
///Which pressure holds docked vessel\station for override of external_pressure_target
|
||||
var/docked_side_pressure
|
||||
///Rate of the pump to remove gases from the air
|
||||
var/volume_rate = 1000
|
||||
///The start time of the current cycle to calculate cycle duration
|
||||
@@ -125,7 +127,31 @@
|
||||
/obj/machinery/atmospherics/components/unary/airlock_pump/post_machine_initialize()
|
||||
. = ..()
|
||||
set_links()
|
||||
// If we are on docked shuttle - setup docking variables
|
||||
// Example - 'build your own shuttle' evac vessel
|
||||
var/turf/local_turf = get_turf(src)
|
||||
if (!cycling_set_up || !isshuttleturf(local_turf))
|
||||
return
|
||||
|
||||
var/tile_air_pressure
|
||||
for(var/obj/machinery/door/airlock/external_airlock in external_airlocks)
|
||||
var/current_area = get_area(external_airlock)
|
||||
for(var/obj/machinery/door/airlock/other_airlock in orange(2, external_airlock)) // does not include src, extended because some escape pods have 1 plating turf exposed to space
|
||||
if(get_area(other_airlock) != current_area) // does not include double-wide airlocks unless actually docked
|
||||
// Cycle linking is only disabled if we are actually adjacent to another airlock
|
||||
external_airlock.shuttledocked = TRUE
|
||||
other_airlock.shuttledocked = TRUE
|
||||
if (other_airlock.cycle_pump)
|
||||
INVOKE_ASYNC(other_airlock.cycle_pump, TYPE_PROC_REF(/obj/machinery/atmospherics/components/unary/airlock_pump, on_dock_request), internal_pressure_target) // Only case when airlock pumps speaking to each other directly
|
||||
// Save external airlocks turf in case our own docking purpouses
|
||||
local_turf = get_turf(other_airlock)
|
||||
|
||||
if (local_turf)
|
||||
local_turf = get_step(local_turf, REVERSE_DIR(dir))
|
||||
tile_air_pressure = 0
|
||||
if (local_turf)
|
||||
tile_air_pressure = max(0, local_turf.return_air().return_pressure())
|
||||
on_dock_request(tile_air_pressure)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/airlock_pump/New()
|
||||
. = ..()
|
||||
@@ -239,6 +265,22 @@
|
||||
airlock.say("Airlock pair not found.")
|
||||
return
|
||||
if(airlock in external_airlocks)
|
||||
// If it's not null - we shuttledocked
|
||||
// (it may be 0. Maybe badmin set internal pressure to 0 as well, who knows)
|
||||
if(docked_side_pressure != null)
|
||||
// Space-faced airlock detection
|
||||
var/turf/external_tile = get_step(airlock, REVERSE_DIR(dir))
|
||||
// Map edge or space turf
|
||||
if (external_tile == null || is_space_or_openspace(external_tile))
|
||||
airlock.run_animation(DOOR_DENY_ANIMATION)
|
||||
return
|
||||
var/tile_air_pressure = max(0, external_tile.return_air().return_pressure())
|
||||
var/pressure_delta = docked_side_pressure - tile_air_pressure
|
||||
if (pressure_delta > 0 ? (pressure_delta > allowed_pressure_error*10) : (pressure_delta*-1 > allowed_pressure_error*10))
|
||||
// Disabled to avoid airlocks close-open spam
|
||||
airlock.run_animation(DOOR_DENY_ANIMATION)
|
||||
return
|
||||
|
||||
start_cycle(ATMOS_DIRECTION_SIPHONING, airlock)
|
||||
else if(airlock in internal_airlocks)
|
||||
start_cycle(ATMOS_DIRECTION_RELEASING, airlock)
|
||||
@@ -281,17 +323,12 @@
|
||||
if(is_cycling_audible)
|
||||
source_airlock.say("Pressurizing airlock.")
|
||||
else
|
||||
cycle_pressure_target = external_pressure_target
|
||||
cycle_pressure_target = docked_side_pressure != null ? docked_side_pressure : external_pressure_target
|
||||
var/pressure_delta = tile_air_pressure - cycle_pressure_target
|
||||
if(pressure_delta <= allowed_pressure_error)
|
||||
stop_cycle("Pressure nominal, cycle skipped.")
|
||||
return TRUE
|
||||
|
||||
for(var/obj/machinery/door/airlock/airlock as anything in external_airlocks)
|
||||
if(airlock.shuttledocked)
|
||||
stop_cycle("Shuttle docked, cycle skipped.")
|
||||
return TRUE
|
||||
|
||||
if(!source_airlock)
|
||||
source_airlock = external_airlocks[1]
|
||||
if(is_cycling_audible)
|
||||
@@ -307,6 +344,11 @@
|
||||
return FALSE
|
||||
on = FALSE
|
||||
|
||||
// In case we can open both sides safe_dock will do it for us
|
||||
// it also handles its own messages. If we can't - procceed
|
||||
if (docked_side_pressure != null && safe_dock(unbolt_only))
|
||||
return TRUE
|
||||
|
||||
var/list/obj/machinery/door/airlock/unlocked_airlocks = pump_direction == ATMOS_DIRECTION_RELEASING ? internal_airlocks : external_airlocks
|
||||
for(var/obj/machinery/door/airlock/airlock as anything in unlocked_airlocks)
|
||||
airlock.unbolt()
|
||||
@@ -323,6 +365,106 @@
|
||||
update_appearance()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/airlock_pump/proc/on_dock_request(requester_pressure = 0)
|
||||
if (docked_side_pressure != null)
|
||||
return
|
||||
|
||||
docked_side_pressure = requester_pressure
|
||||
|
||||
if (!powered() || !cycling_set_up)
|
||||
return
|
||||
|
||||
// We just finishing previous cycle
|
||||
if (airlocks_animating)
|
||||
say("Docking request queued.")
|
||||
stoplag(1.1 SECONDS) // Wait for opening animation
|
||||
if (airlocks_animating) // Should (almost) never happened
|
||||
say("ERROR: D11. Please re-initiate docking sequence.")
|
||||
return
|
||||
|
||||
if (on)
|
||||
// You can't go there, there is a shuttle now
|
||||
if (pump_direction == ATMOS_DIRECTION_SIPHONING)
|
||||
stop_cycle("Cycling sequence overriden by docking sequence.", TRUE)
|
||||
start_cycle(ATMOS_DIRECTION_RELEASING)
|
||||
// If cycling inside, docking will be handled by stop_cycle proc
|
||||
return
|
||||
|
||||
// Check if we need cycle in
|
||||
var/turf/local_turf = get_turf(src)
|
||||
var/tile_air_pressure = max(0, local_turf.return_air().return_pressure())
|
||||
var/pressure_delta = internal_pressure_target - tile_air_pressure
|
||||
if(pressure_delta <= allowed_pressure_error)
|
||||
// We fine
|
||||
safe_dock()
|
||||
else
|
||||
var/obj/machinery/door/airlock/source_airlock = pick(internal_airlocks)
|
||||
source_airlock.say("Docking sequence initiated")
|
||||
start_cycle(ATMOS_DIRECTION_RELEASING)
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/airlock_pump/proc/safe_dock(unbolt_only = FALSE)
|
||||
var/pressure_delta = internal_pressure_target - docked_side_pressure
|
||||
// Docked vessel has pressure higher then our internal
|
||||
if ((pressure_delta + allowed_pressure_error) < 0)
|
||||
return FALSE
|
||||
// Pressure is too different, its unsafe to open both sides
|
||||
else if (pressure_delta > allowed_pressure_error * 10)
|
||||
return FALSE
|
||||
// No power handles by stop_cycle pretty good
|
||||
else if (!powered())
|
||||
return FALSE
|
||||
|
||||
var/turf/local_turf = get_turf(src)
|
||||
var/tile_air_pressure = max(0, local_turf.return_air().return_pressure())
|
||||
pressure_delta = internal_pressure_target - tile_air_pressure
|
||||
// Chamber is not pressurised
|
||||
if(pressure_delta > allowed_pressure_error)
|
||||
return FALSE
|
||||
|
||||
for(var/obj/machinery/door/airlock/airlock as anything in (external_airlocks + internal_airlocks))
|
||||
if (airlock in external_airlocks)
|
||||
airlock.air_tight = TRUE
|
||||
local_turf = get_step(airlock, REVERSE_DIR(dir))
|
||||
// Map edge or space turf
|
||||
if (local_turf == null || is_space_or_openspace(local_turf))
|
||||
continue
|
||||
|
||||
tile_air_pressure = max(0, local_turf.return_air().return_pressure())
|
||||
pressure_delta = docked_side_pressure - tile_air_pressure
|
||||
// Do not open airlocks leading in space
|
||||
// If docked entity now has pressure lower or higher then was declared on docking
|
||||
// We will keep airlocks closed until redocking or fixing atmos
|
||||
if (pressure_delta > 0 ? (pressure_delta > allowed_pressure_error*10) : (pressure_delta*-1 > allowed_pressure_error*10))
|
||||
continue
|
||||
|
||||
airlock.unbolt()
|
||||
if(open_airlock_on_cycle && !unbolt_only)
|
||||
INVOKE_ASYNC(airlock, TYPE_PROC_REF(/obj/machinery/door/airlock, secure_open))
|
||||
|
||||
airlocks_animating = TRUE
|
||||
stoplag(1 SECONDS) // Wait for closing animation
|
||||
airlocks_animating = FALSE
|
||||
update_appearance()
|
||||
say("Docking complete.")
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/airlock_pump/proc/undock()
|
||||
if (docked_side_pressure == null)
|
||||
return
|
||||
docked_side_pressure = null
|
||||
if(!powered())
|
||||
return
|
||||
|
||||
for(var/obj/machinery/door/airlock/airlock as anything in external_airlocks)
|
||||
INVOKE_ASYNC(airlock, TYPE_PROC_REF(/obj/machinery/door/airlock, secure_close), TRUE)
|
||||
|
||||
say("Docking connection terminated.")
|
||||
airlocks_animating = TRUE
|
||||
stoplag(1 SECONDS) // Wait for closing animation
|
||||
airlocks_animating = FALSE
|
||||
|
||||
|
||||
///Update adjacent_turfs with atmospherically adjacent tiles
|
||||
/obj/machinery/atmospherics/components/unary/airlock_pump/proc/check_turfs()
|
||||
|
||||
@@ -167,19 +167,54 @@ All ShuttleMove procs go here
|
||||
|
||||
/obj/machinery/door/airlock/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
|
||||
. = ..()
|
||||
|
||||
if (cycle_pump)
|
||||
INVOKE_ASYNC(cycle_pump, TYPE_PROC_REF(/obj/machinery/atmospherics/components/unary/airlock_pump, undock))
|
||||
|
||||
for(var/obj/machinery/door/airlock/other_airlock in range(2, src)) // includes src, extended because some escape pods have 1 plating turf exposed to space
|
||||
other_airlock.shuttledocked = FALSE
|
||||
other_airlock.air_tight = TRUE
|
||||
if (other_airlock.cycle_pump)
|
||||
INVOKE_ASYNC(other_airlock.cycle_pump, TYPE_PROC_REF(/obj/machinery/atmospherics/components/unary/airlock_pump, undock))
|
||||
continue
|
||||
INVOKE_ASYNC(other_airlock, TYPE_PROC_REF(/obj/machinery/door/, close), FALSE, TRUE) // force crush
|
||||
|
||||
/obj/machinery/door/airlock/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
|
||||
. = ..()
|
||||
var/current_area = get_area(src)
|
||||
var/turf/local_turf
|
||||
var/tile_air_pressure
|
||||
for(var/obj/machinery/door/airlock/other_airlock in orange(2, src)) // does not include src, extended because some escape pods have 1 plating turf exposed to space
|
||||
if(get_area(other_airlock) != current_area) // does not include double-wide airlocks unless actually docked
|
||||
// Cycle linking is only disabled if we are actually adjacent to another airlock
|
||||
shuttledocked = TRUE
|
||||
other_airlock.shuttledocked = TRUE
|
||||
if (other_airlock.cycle_pump)
|
||||
local_turf = get_step(src, REVERSE_DIR(other_airlock.cycle_pump.dir))
|
||||
tile_air_pressure = 0
|
||||
if (local_turf)
|
||||
tile_air_pressure = max(0, local_turf.return_air().return_pressure())
|
||||
INVOKE_ASYNC(other_airlock.cycle_pump, TYPE_PROC_REF(/obj/machinery/atmospherics/components/unary/airlock_pump, on_dock_request), tile_air_pressure)
|
||||
// Save external airlocks turf in case our own docking purpouses
|
||||
local_turf = get_turf(other_airlock)
|
||||
|
||||
if (cycle_pump)
|
||||
tile_air_pressure = 0
|
||||
if (local_turf)
|
||||
local_turf = get_step(local_turf, REVERSE_DIR(cycle_pump.dir))
|
||||
if (local_turf)
|
||||
tile_air_pressure = max(0, local_turf.return_air().return_pressure())
|
||||
INVOKE_ASYNC(cycle_pump, TYPE_PROC_REF(/obj/machinery/atmospherics/components/unary/airlock_pump, on_dock_request), tile_air_pressure)
|
||||
else
|
||||
// In case, somebody decides to build an airlock on evac shuttle, we count CentComs blastdoors as valid docking airlock
|
||||
local_turf = get_step(src, REVERSE_DIR(cycle_pump.dir))
|
||||
if (local_turf)
|
||||
for(var/obj/machinery/door/poddoor/shuttledock/centcom_airlock in local_turf)
|
||||
// For some reason on docking moment those tiles are vacuum, and pump denies safe_dock attempt
|
||||
// To fix this we're lying, that external pressure is nominal
|
||||
INVOKE_ASYNC(cycle_pump, TYPE_PROC_REF(/obj/machinery/atmospherics/components/unary/airlock_pump, on_dock_request), ONE_ATMOSPHERE)
|
||||
break
|
||||
|
||||
|
||||
/obj/machinery/camera/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
|
||||
. = ..()
|
||||
|
||||
Reference in New Issue
Block a user