mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
Squashed 10 commits: Adds simple docking controllers Adds docking_controllers.dm Moves docking handshake code into its own type Keeps docking code separate from the code for messing with airlocks and doors. Improves handling of invalid states Adds docking controller to research shuttle dock Also adds the start of a nano-ui template. Resetting the dock controller resets the override Adds debug verbs Adds support for overriding docking checks Less confusing name for the docking program
332 lines
10 KiB
Plaintext
332 lines
10 KiB
Plaintext
//Handles the control of airlocks
|
|
|
|
#define STATE_WAIT 0
|
|
#define STATE_DEPRESSURIZE 1
|
|
#define STATE_PRESSURIZE 2
|
|
|
|
#define TARGET_NONE 0
|
|
#define TARGET_INOPEN -1
|
|
#define TARGET_OUTOPEN -2
|
|
|
|
|
|
/datum/computer/file/embedded_program/airlock
|
|
var/tag_exterior_door
|
|
var/tag_interior_door
|
|
var/tag_airpump
|
|
var/tag_chamber_sensor
|
|
var/tag_exterior_sensor
|
|
var/tag_interior_sensor
|
|
|
|
var/state = STATE_WAIT
|
|
var/target_state = TARGET_NONE
|
|
|
|
/datum/computer/file/embedded_program/airlock/New()
|
|
..()
|
|
memory["chamber_sensor_pressure"] = ONE_ATMOSPHERE
|
|
memory["external_sensor_pressure"] = 0 //assume vacuum for simple airlock controller
|
|
memory["internal_sensor_pressure"] = ONE_ATMOSPHERE
|
|
memory["exterior_status"] = list(state = "closed", lock = "locked") //assume closed and locked in case the doors dont report in
|
|
memory["interior_status"] = list(state = "closed", lock = "locked")
|
|
memory["pump_status"] = "unknown"
|
|
memory["target_pressure"] = ONE_ATMOSPHERE
|
|
memory["purge"] = 0
|
|
memory["secure"] = 0
|
|
|
|
/datum/computer/file/embedded_program/airlock/receive_signal(datum/signal/signal, receive_method, receive_param)
|
|
var/receive_tag = signal.data["tag"]
|
|
if(!receive_tag) return
|
|
|
|
if(receive_tag==tag_chamber_sensor)
|
|
if(signal.data["pressure"])
|
|
memory["chamber_sensor_pressure"] = text2num(signal.data["pressure"])
|
|
|
|
else if(receive_tag==tag_exterior_sensor)
|
|
memory["external_sensor_pressure"] = text2num(signal.data["pressure"])
|
|
|
|
else if(receive_tag==tag_interior_sensor)
|
|
memory["internal_sensor_pressure"] = text2num(signal.data["pressure"])
|
|
|
|
else if(receive_tag==tag_exterior_door)
|
|
memory["exterior_status"]["state"] = signal.data["door_status"]
|
|
memory["exterior_status"]["lock"] = signal.data["lock_status"]
|
|
|
|
else if(receive_tag==tag_interior_door)
|
|
memory["interior_status"]["state"] = signal.data["door_status"]
|
|
memory["interior_status"]["lock"] = signal.data["lock_status"]
|
|
|
|
else if(receive_tag==tag_airpump)
|
|
if(signal.data["power"])
|
|
memory["pump_status"] = signal.data["direction"]
|
|
else
|
|
memory["pump_status"] = "off"
|
|
|
|
else if(receive_tag==id_tag)
|
|
if(istype(master, /obj/machinery/embedded_controller/radio/airlock/access_controller))
|
|
switch(signal.data["command"])
|
|
if("cycle_exterior")
|
|
receive_user_command("cycle_ext_door")
|
|
if("cycle_interior")
|
|
receive_user_command("cycle_int_door")
|
|
if("cycle")
|
|
if(memory["interior_status"]["state"] == "open") //handle backwards compatibility
|
|
receive_user_command("cycle_ext")
|
|
else
|
|
receive_user_command("cycle_int")
|
|
else
|
|
switch(signal.data["command"])
|
|
if("cycle_exterior")
|
|
receive_user_command("cycle_ext")
|
|
if("cycle_interior")
|
|
receive_user_command("cycle_int")
|
|
if("cycle")
|
|
if(memory["interior_status"]["state"] == "open") //handle backwards compatibility
|
|
receive_user_command("cycle_ext")
|
|
else
|
|
receive_user_command("cycle_int")
|
|
|
|
|
|
/datum/computer/file/embedded_program/airlock/receive_user_command(command)
|
|
var/shutdown_pump = 0
|
|
switch(command)
|
|
if("cycle_ext")
|
|
begin_cycle_out()
|
|
|
|
if("cycle_int")
|
|
begin_cycle_in()
|
|
|
|
if("cycle_ext_door")
|
|
cycleDoors(TARGET_OUTOPEN)
|
|
|
|
if("cycle_int_door")
|
|
cycleDoors(TARGET_INOPEN)
|
|
|
|
if("abort")
|
|
state = STATE_PRESSURIZE
|
|
target_state = TARGET_NONE
|
|
memory["target_pressure"] = ONE_ATMOSPHERE
|
|
signalPump(tag_airpump, 1, 1, memory["target_pressure"])
|
|
process()
|
|
|
|
if("force_ext")
|
|
toggleDoor(memory["exterior_status"], tag_exterior_door, memory["secure"], "toggle")
|
|
|
|
if("force_int")
|
|
toggleDoor(memory["interior_status"], tag_interior_door, memory["secure"], "toggle")
|
|
|
|
if("purge")
|
|
memory["purge"] = !memory["purge"]
|
|
if(memory["purge"])
|
|
toggleDoor(memory["exterior_status"], tag_exterior_door, 1, "close")
|
|
toggleDoor(memory["interior_status"], tag_interior_door, 1, "close")
|
|
state = STATE_DEPRESSURIZE
|
|
target_state = TARGET_NONE
|
|
signalPump(tag_airpump, 1, 0, 0)
|
|
|
|
if("secure")
|
|
memory["secure"] = !memory["secure"]
|
|
if(memory["secure"])
|
|
signalDoor(tag_interior_door, "lock")
|
|
signalDoor(tag_exterior_door, "lock")
|
|
else
|
|
signalDoor(tag_interior_door, "unlock")
|
|
signalDoor(tag_exterior_door, "unlock")
|
|
|
|
if(shutdown_pump)
|
|
signalPump(tag_airpump, 0) //send a signal to stop pressurizing
|
|
|
|
|
|
/datum/computer/file/embedded_program/airlock/process()
|
|
if(!state)
|
|
if(target_state)
|
|
switch(target_state)
|
|
if(TARGET_INOPEN)
|
|
memory["target_pressure"] = memory["internal_sensor_pressure"]
|
|
if(TARGET_OUTOPEN)
|
|
memory["target_pressure"] = memory["external_sensor_pressure"]
|
|
|
|
//lock down the airlock before activating pumps
|
|
close_doors()
|
|
|
|
var/chamber_pressure = memory["chamber_sensor_pressure"]
|
|
var/target_pressure = memory["target_pressure"]
|
|
|
|
if(memory["purge"])
|
|
target_pressure = 0
|
|
|
|
if(chamber_pressure <= target_pressure)
|
|
state = STATE_PRESSURIZE
|
|
signalPump(tag_airpump, 1, 1, target_pressure) //send a signal to start pressurizing
|
|
|
|
else if(chamber_pressure > target_pressure)
|
|
state = STATE_DEPRESSURIZE
|
|
signalPump(tag_airpump, 1, 0, target_pressure) //send a signal to start depressurizing
|
|
|
|
//Check for vacuum - this is set after the pumps so the pumps are aiming for 0
|
|
if(!memory["target_pressure"])
|
|
memory["target_pressure"] = ONE_ATMOSPHERE * 0.05
|
|
else
|
|
//make sure to return to a sane idle state
|
|
if(memory["pump_status"] != "off") //send a signal to stop pumping
|
|
signalPump(tag_airpump, 0)
|
|
|
|
//the airlock will not allow itself to continue to cycle when any of the doors are forced open.
|
|
if (state && !check_doors_secured())
|
|
stop_cycling()
|
|
|
|
switch(state)
|
|
if(STATE_PRESSURIZE)
|
|
if(memory["chamber_sensor_pressure"] >= memory["target_pressure"] * 0.95)
|
|
cycleDoors(target_state)
|
|
|
|
state = STATE_WAIT
|
|
target_state = TARGET_NONE
|
|
|
|
if(memory["pump_status"] != "off")
|
|
signalPump(tag_airpump, 0) //send a signal to stop pumping
|
|
|
|
|
|
if(STATE_DEPRESSURIZE)
|
|
if(memory["purge"])
|
|
if(memory["chamber_sensor_pressure"] <= ONE_ATMOSPHERE * 0.05)
|
|
state = STATE_PRESSURIZE
|
|
signalPump(tag_airpump, 1, 1, memory["target_pressure"])
|
|
|
|
|
|
else if(memory["chamber_sensor_pressure"] <= memory["target_pressure"] * 1.05)
|
|
cycleDoors(target_state)
|
|
|
|
state = STATE_WAIT
|
|
target_state = TARGET_NONE
|
|
|
|
//send a signal to stop pumping
|
|
if(memory["pump_status"] != "off")
|
|
signalPump(tag_airpump, 0)
|
|
|
|
|
|
memory["processing"] = state != target_state
|
|
|
|
return 1
|
|
|
|
//these are here so that other types don't have to make so many assuptions about our implementation
|
|
|
|
/datum/computer/file/embedded_program/airlock/proc/begin_cycle_in()
|
|
state = STATE_WAIT
|
|
target_state = TARGET_INOPEN
|
|
|
|
/datum/computer/file/embedded_program/airlock/proc/begin_cycle_out()
|
|
state = STATE_WAIT
|
|
target_state = TARGET_OUTOPEN
|
|
|
|
/datum/computer/file/embedded_program/airlock/proc/close_doors()
|
|
toggleDoor(memory["interior_status"], tag_interior_door, 1, "close")
|
|
toggleDoor(memory["exterior_status"], tag_exterior_door, 1, "close")
|
|
|
|
/datum/computer/file/embedded_program/airlock/proc/stop_cycling()
|
|
state = STATE_WAIT
|
|
target_state = TARGET_NONE
|
|
|
|
/datum/computer/file/embedded_program/airlock/proc/done_cycling()
|
|
return (state == STATE_WAIT && target_state == TARGET_NONE)
|
|
|
|
//are the doors closed and locked?
|
|
/datum/computer/file/embedded_program/airlock/proc/check_doors_secured()
|
|
var/ext_closed = (memory["exterior_status"]["state"] == "closed" && memory["exterior_status"]["lock"] == "locked")
|
|
var/int_closed = (memory["interior_status"]["state"] == "closed" && memory["interior_status"]["lock"] == "locked")
|
|
return (ext_closed && int_closed)
|
|
|
|
/datum/computer/file/embedded_program/airlock/proc/signalDoor(var/tag, var/command)
|
|
var/datum/signal/signal = new
|
|
signal.data["tag"] = tag
|
|
signal.data["command"] = command
|
|
post_signal(signal)
|
|
|
|
/datum/computer/file/embedded_program/airlock/proc/signalPump(var/tag, var/power, var/direction, var/pressure)
|
|
var/datum/signal/signal = new
|
|
signal.data = list(
|
|
"tag" = tag,
|
|
"sigtype" = "command",
|
|
"power" = power,
|
|
"direction" = direction,
|
|
"set_external_pressure" = pressure
|
|
)
|
|
post_signal(signal)
|
|
|
|
//this is called to set the appropriate door state at the end of a cycling process, or for the exterior buttons
|
|
/datum/computer/file/embedded_program/airlock/proc/cycleDoors(var/target)
|
|
switch(target)
|
|
if(TARGET_OUTOPEN)
|
|
toggleDoor(memory["interior_status"], tag_interior_door, memory["secure"], "close")
|
|
toggleDoor(memory["exterior_status"], tag_exterior_door, memory["secure"], "open")
|
|
|
|
if(TARGET_INOPEN)
|
|
toggleDoor(memory["exterior_status"], tag_exterior_door, memory["secure"], "close")
|
|
toggleDoor(memory["interior_status"], tag_interior_door, memory["secure"], "open")
|
|
if(TARGET_NONE)
|
|
var/command = "unlock"
|
|
if(memory["secure"])
|
|
command = "lock"
|
|
signalDoor(tag_exterior_door, command)
|
|
signalDoor(tag_interior_door, command)
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
toggleDoor()
|
|
|
|
Sends a radio command to a door to either open or close. If
|
|
the command is 'toggle' the door will be sent a command that
|
|
reverses it's current state.
|
|
Can also toggle whether the door bolts are locked or not,
|
|
depending on the state of the 'secure' flag.
|
|
Only sends a command if it is needed, i.e. if the door is
|
|
already open, passing an open command to this proc will not
|
|
send an additional command to open the door again.
|
|
----------------------------------------------------------*/
|
|
/datum/computer/file/embedded_program/airlock/proc/toggleDoor(var/list/doorStatus, var/doorTag, var/secure, var/command)
|
|
var/doorCommand = null
|
|
|
|
if(command == "toggle")
|
|
if(doorStatus["state"] == "open")
|
|
command = "close"
|
|
else if(doorStatus["state"] == "closed")
|
|
command = "open"
|
|
|
|
switch(command)
|
|
if("close")
|
|
if(secure)
|
|
if(doorStatus["state"] == "open")
|
|
doorCommand = "secure_close"
|
|
else if(doorStatus["lock"] == "unlocked")
|
|
doorCommand = "lock"
|
|
else
|
|
if(doorStatus["state"] == "open")
|
|
if(doorStatus["lock"] == "locked")
|
|
signalDoor(doorTag, "unlock")
|
|
doorCommand = "close"
|
|
else if(doorStatus["lock"] == "locked")
|
|
doorCommand = "unlock"
|
|
|
|
if("open")
|
|
if(secure)
|
|
if(doorStatus["state"] == "closed")
|
|
doorCommand = "secure_open"
|
|
else if(doorStatus["lock"] == "unlocked")
|
|
doorCommand = "lock"
|
|
else
|
|
if(doorStatus["state"] == "closed")
|
|
if(doorStatus["lock"] == "locked")
|
|
signalDoor(doorTag,"unlock")
|
|
doorCommand = "open"
|
|
else if(doorStatus["lock"] == "locked")
|
|
doorCommand = "unlock"
|
|
|
|
if(doorCommand)
|
|
signalDoor(doorTag, doorCommand)
|
|
|
|
|
|
#undef STATE_WAIT
|
|
#undef STATE_DEPRESSURIZE
|
|
#undef STATE_PRESSURIZE
|
|
|
|
#undef TARGET_NONE
|
|
#undef TARGET_INOPEN
|
|
#undef TARGET_OUTOPEN |