From 4c910f0f2e1f2c5e8f1dda4ef0639761be97555c Mon Sep 17 00:00:00 2001 From: Leshana Date: Sun, 4 Feb 2018 15:05:08 -0500 Subject: [PATCH] Port cycle_to_external_air mode for airlock controllers. * Adds a flag to controllers that instructs the airlock program to always purge between IN/OUT and also to pump air to "outside" instead of tanks when purging to go OUT. * Tweak the way the airlock fudges target pressures so it more reliably operates when trying to pump down to vacuum. * Adds an exterior airlock sensor that reads the air pressure in *front* of it, so it can be mounted on a shuttle but measure air outside the shuttle. --- code/game/machinery/doors/airlock_control.dm | 7 ++ .../airlock_controllers.dm | 1 + .../embedded_controller/airlock_program.dm | 69 ++++++++++++++----- .../Leshana - vplk-airlocks-cycle-to-ext.yml | 4 ++ 4 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 html/changelogs/Leshana - vplk-airlocks-cycle-to-ext.yml diff --git a/code/game/machinery/doors/airlock_control.dm b/code/game/machinery/doors/airlock_control.dm index 1fd5eb34c6..295a7ff24f 100644 --- a/code/game/machinery/doors/airlock_control.dm +++ b/code/game/machinery/doors/airlock_control.dm @@ -218,6 +218,13 @@ obj/machinery/airlock_sensor/airlock_interior obj/machinery/airlock_sensor/airlock_exterior command = "cycle_exterior" +// Return the air from the turf in "front" of us (Used in shuttles, so it can be in the shuttle area but sense outside it) +obj/machinery/airlock_sensor/airlock_exterior/shuttle/return_air() + var/turf/T = get_step(src, dir) + if(isnull(T)) + return ..() + return T.return_air() + obj/machinery/access_button icon = 'icons/obj/airlock_machines.dmi' icon_state = "access_button_standby" diff --git a/code/game/machinery/embedded_controller/airlock_controllers.dm b/code/game/machinery/embedded_controller/airlock_controllers.dm index 3a79a686b0..b5895cd300 100644 --- a/code/game/machinery/embedded_controller/airlock_controllers.dm +++ b/code/game/machinery/embedded_controller/airlock_controllers.dm @@ -11,6 +11,7 @@ var/tag_airlock_mech_sensor var/tag_shuttle_mech_sensor var/tag_secure = 0 + var/cycle_to_external_air = 0 /obj/machinery/embedded_controller/radio/airlock/initialize() . = ..() diff --git a/code/game/machinery/embedded_controller/airlock_program.dm b/code/game/machinery/embedded_controller/airlock_program.dm index 418f3db2c1..5ebbac93ae 100644 --- a/code/game/machinery/embedded_controller/airlock_program.dm +++ b/code/game/machinery/embedded_controller/airlock_program.dm @@ -9,6 +9,8 @@ #define TARGET_INOPEN -1 #define TARGET_OUTOPEN -2 +#define MIN_TARGET_PRESSURE (ONE_ATMOSPHERE * 0.05) // Never try to pump to pure vacuum, its not happening. +#define SKIPCYCLE_MARGIN 1 // Skip cycling airlock (just open the doors) if pressures are within this range. /datum/computer/file/embedded_program/airlock var/tag_exterior_door @@ -23,6 +25,10 @@ var/state = STATE_IDLE var/target_state = TARGET_NONE + var/cycle_to_external_air = 0 + var/tag_pump_out_external + var/tag_pump_out_internal + /datum/computer/file/embedded_program/airlock/New(var/obj/machinery/embedded_controller/M) ..(M) @@ -38,6 +44,10 @@ if (istype(M, /obj/machinery/embedded_controller/radio/airlock)) //if our controller is an airlock controller than we can auto-init our tags var/obj/machinery/embedded_controller/radio/airlock/controller = M + cycle_to_external_air = controller.cycle_to_external_air + if(cycle_to_external_air) + tag_pump_out_external = "[id_tag]_pump_out_external" + tag_pump_out_internal = "[id_tag]_pump_out_internal" tag_exterior_door = controller.tag_exterior_door? controller.tag_exterior_door : "[id_tag]_outer" tag_interior_door = controller.tag_interior_door? controller.tag_interior_door : "[id_tag]_inner" tag_airpump = controller.tag_airpump? controller.tag_airpump : "[id_tag]_pump" @@ -74,7 +84,7 @@ memory["interior_status"]["state"] = signal.data["door_status"] memory["interior_status"]["lock"] = signal.data["lock_status"] - else if(receive_tag==tag_airpump) + else if(receive_tag==tag_airpump || receive_tag==tag_pump_out_internal) if(signal.data["power"]) memory["pump_status"] = signal.data["direction"] else @@ -110,7 +120,7 @@ switch(command) if("cycle_ext") //If airlock is already cycled in this direction, just toggle the doors. - if(!memory["purge"] && IsInRange(memory["external_sensor_pressure"], memory["chamber_sensor_pressure"] * 0.95, memory["chamber_sensor_pressure"] * 1.05)) + if(!memory["purge"] && abs(memory["external_sensor_pressure"] - memory["chamber_sensor_pressure"]) <= SKIPCYCLE_MARGIN) toggleDoor(memory["exterior_status"], tag_exterior_door, memory["secure"], "toggle") //only respond to these commands if the airlock isn't already doing something //prevents the controller from getting confused and doing strange things @@ -118,7 +128,7 @@ begin_cycle_out() if("cycle_int") - if(!memory["purge"] && IsInRange(memory["internal_sensor_pressure"], memory["chamber_sensor_pressure"] * 0.95, memory["chamber_sensor_pressure"] * 1.05)) + if(!memory["purge"] && abs(memory["internal_sensor_pressure"] - memory["chamber_sensor_pressure"]) <= SKIPCYCLE_MARGIN) toggleDoor(memory["interior_status"], tag_interior_door, memory["secure"], "toggle") else if(state == target_state) begin_cycle_in() @@ -156,6 +166,10 @@ if(shutdown_pump) signalPump(tag_airpump, 0) //send a signal to stop pressurizing + if(cycle_to_external_air) + signalPump(tag_pump_out_internal, 0) + signalPump(tag_pump_out_external, 0) + /datum/computer/file/embedded_program/airlock/process() @@ -175,6 +189,9 @@ //make sure to return to a sane idle state if(memory["pump_status"] != "off") //send a signal to stop pumping signalPump(tag_airpump, 0) + if(cycle_to_external_air) + signalPump(tag_pump_out_internal, 0) + signalPump(tag_pump_out_external, 0) if ((state == STATE_PRESSURIZE || state == STATE_DEPRESSURIZE) && !check_doors_secured()) //the airlock will not allow itself to continue to cycle when any of the doors are forced open. @@ -190,24 +207,37 @@ //purge apparently means clearing the airlock chamber to vacuum (then refilling, handled later) target_pressure = 0 state = STATE_DEPRESSURIZE - signalPump(tag_airpump, 1, 0, 0) //send a signal to start depressurizing + if(!cycle_to_external_air || target_state == TARGET_OUTOPEN) // if going outside, pump internal air into air tank + signalPump(tag_airpump, 1, 0, target_pressure) //send a signal to start depressurizing + else + signalPump(tag_pump_out_internal, 1, 0, target_pressure) // if going inside, pump external air out of the airlock + signalPump(tag_pump_out_external, 1, 1, 15000) // make sure the air is actually going outside else if(chamber_pressure <= target_pressure) state = STATE_PRESSURIZE - signalPump(tag_airpump, 1, 1, target_pressure) //send a signal to start pressurizing + if(!cycle_to_external_air || target_state == TARGET_INOPEN) // if going inside, pump air into airlock + signalPump(tag_airpump, 1, 1, target_pressure) //send a signal to start pressurizing + else + signalPump(tag_pump_out_internal, 1, 1, target_pressure) // if going outside, fill airlock with external air + signalPump(tag_pump_out_external, 1, 0, 0) else if(chamber_pressure > target_pressure) - state = STATE_DEPRESSURIZE - signalPump(tag_airpump, 1, 0, target_pressure) //send a signal to start depressurizing - + if(!cycle_to_external_air) + state = STATE_DEPRESSURIZE + signalPump(tag_airpump, 1, 0, target_pressure) //send a signal to start depressurizing + else + memory["purge"] = 1 // should always purge first if using external air, chamber pressure should never be higher than target pressure here //Make sure the airlock isn't aiming for pure vacuum - an impossibility - memory["target_pressure"] = max(target_pressure, ONE_ATMOSPHERE * 0.05) + memory["target_pressure"] = max(target_pressure, MIN_TARGET_PRESSURE) if(STATE_PRESSURIZE) if(memory["chamber_sensor_pressure"] >= memory["target_pressure"] * 0.95) //not done until the pump has reported that it's off if(memory["pump_status"] != "off") signalPump(tag_airpump, 0) //send a signal to stop pumping + if(cycle_to_external_air) + signalPump(tag_pump_out_internal, 0) + signalPump(tag_pump_out_external, 0) else cycleDoors(target_state) state = STATE_IDLE @@ -215,15 +245,17 @@ if(STATE_DEPRESSURIZE) - if(memory["chamber_sensor_pressure"] <= memory["target_pressure"] * 1.05) - if(memory["purge"]) - memory["purge"] = 0 - memory["target_pressure"] = memory["internal_sensor_pressure"] - state = STATE_PREPARE - target_state = TARGET_NONE - - else if(memory["pump_status"] != "off") + if(memory["chamber_sensor_pressure"] <= max(memory["target_pressure"] * 1.05, MIN_TARGET_PRESSURE)) + if(memory["pump_status"] != "off") signalPump(tag_airpump, 0) + if(cycle_to_external_air) + signalPump(tag_pump_out_internal, 0) + signalPump(tag_pump_out_external, 0) + else if(memory["purge"]) + memory["purge"] = 0 + memory["target_pressure"] = (target_state == TARGET_INOPEN ? memory["internal_sensor_pressure"] : memory["external_sensor_pressure"]) + if (memory["target_pressure"] > SKIPCYCLE_MARGIN) + state = STATE_PREPARE // Skip pressurizing if target pressure is already close enough. else cycleDoors(target_state) state = STATE_IDLE @@ -239,10 +271,12 @@ /datum/computer/file/embedded_program/airlock/proc/begin_cycle_in() state = STATE_IDLE target_state = TARGET_INOPEN + memory["purge"] = cycle_to_external_air /datum/computer/file/embedded_program/airlock/proc/begin_cycle_out() state = STATE_IDLE target_state = TARGET_OUTOPEN + memory["purge"] = cycle_to_external_air /datum/computer/file/embedded_program/airlock/proc/close_doors() toggleDoor(memory["interior_status"], tag_interior_door, 1, "close") @@ -368,6 +402,7 @@ send an additional command to open the door again. if(doorCommand) signalDoor(doorTag, doorCommand) +#undef SKIPCYCLE_MARGIN #undef STATE_IDLE #undef STATE_DEPRESSURIZE diff --git a/html/changelogs/Leshana - vplk-airlocks-cycle-to-ext.yml b/html/changelogs/Leshana - vplk-airlocks-cycle-to-ext.yml new file mode 100644 index 0000000000..3f59f30fea --- /dev/null +++ b/html/changelogs/Leshana - vplk-airlocks-cycle-to-ext.yml @@ -0,0 +1,4 @@ +author: Leshana and mustafakalash +delete-after: True +changes: + - rscadd: "A new 'planetary' mode for airlocks which makes them purge the chamber contents to the exterior atmosphere before filling with clean air, and vice versa."