From 5fae1db085750c01e50936ab7247eb0a9fc6a1df Mon Sep 17 00:00:00 2001 From: mwerezak Date: Thu, 5 Jun 2014 00:32:28 -0400 Subject: [PATCH] Initial commit Conflicts: code/game/machinery/embedded_controller/airlock_program.dm --- .../embedded_controller/airlock_program.dm | 340 ++++++++++++++++++ .../embedded_controller/docking_program.dm | 68 ++++ 2 files changed, 408 insertions(+) create mode 100644 code/game/machinery/embedded_controller/airlock_program.dm create mode 100644 code/game/machinery/embedded_controller/docking_program.dm diff --git a/code/game/machinery/embedded_controller/airlock_program.dm b/code/game/machinery/embedded_controller/airlock_program.dm new file mode 100644 index 00000000000..baf846ebf4e --- /dev/null +++ b/code/game/machinery/embedded_controller/airlock_program.dm @@ -0,0 +1,340 @@ +//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 + var/list/memory = list() + var/obj/machinery/embedded_controller/master + + var/id_tag + 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/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/proc/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/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/proc/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/proc/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 + toggleDoor(memory["exterior_status"], tag_exterior_door, 1, "close") + toggleDoor(memory["interior_status"], tag_interior_door, 1, "close") + + 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_closed()) + 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 subtypes don't have to make so many assuptions about our implementation + +/datum/computer/file/embedded_program/proc/begin_cycle_in() + state = STATE_WAIT + target_state = TARGET_INOPEN + +/datum/computer/file/embedded_program/proc/begin_cycle_out() + state = STATE_WAIT + target_state = TARGET_OUTOPEN + +/datum/computer/file/embedded_program/proc/stop_cycling() + state = STATE_WAIT + target_state = TARGET_NONE + +/datum/computer/file/embedded_program/proc/done_cycling() + return (state == STATE_WAIT && target_state == TARGET_NONE) + +/datum/computer/file/embedded_program/proc/post_signal(datum/signal/signal, comm_line) + if(master) + master.post_signal(signal, comm_line) + else + del(signal) + +/datum/computer/file/embedded_program/proc/check_doors_closed() + return (memory["interior_status"]["state"] == "closed" && memory["exterior_status"["state"] == "closed") + +/datum/computer/file/embedded_program/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/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/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/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 \ No newline at end of file diff --git a/code/game/machinery/embedded_controller/docking_program.dm b/code/game/machinery/embedded_controller/docking_program.dm new file mode 100644 index 00000000000..bdf049b6e5f --- /dev/null +++ b/code/game/machinery/embedded_controller/docking_program.dm @@ -0,0 +1,68 @@ + +#define STATE_UNDOCKED 0 +#define STATE_DOCKING 1 +#define STATE_UNDOCKING 2 +#define STATE_DOCKED 3 + +/datum/computer/file/embedded_program/docking_port + var/tag_target //the tag of the docking controller that we are trying to dock with + var/airlock_override = 0 //allows use of the docking port as a normal airlock (normally this is only allowed in STATE_UNDOCKED) + var/dock_state = STATE_UNDOCKED + +/datum/computer/file/embedded_program/docking_port/receive_signal(datum/signal/signal, receive_method, receive_param) + var/receive_tag = signal.data["tag"] + var/command = signal.data["command"] + + if(!receive_tag) return + + if(receive_tag==tag_target && command="request_undock") + begin_undock() + else if (command=="request_dock") + if (tag_target) //something is already docked here + //send an error message + else + tag_target = receive_tag + begin_dock() + + ..() + +/datum/computer/file/embedded_program/docking_port/receive_user_command(command) + +/datum/computer/file/embedded_program/docking_port/process() + ..() //process regular airlock stuff first + + switch(dock_state) + if(STATE_DOCKING) + if(done_cycling()) + state = STATE_DOCKED + + //send confirmation + + //open doors + toggleDoor(memory["interior_status"], tag_interior_door, memory["secure"], "open") + toggleDoor(memory["exterior_status"], tag_exterior_door, memory["secure"], "open") + if(STATE_UNDOCKING) + if() //check doors are closed or override + state = STATE_UNDOCKED + + + //send confirmation + tag_target = null + +/datum/computer/file/embedded_program/docking_port/cycleDoors(var/target) + if (state == STATE_UNDOCKED || airlock_override) + ..() + +//get the docking port into a good state for docking. +/datum/computer/file/embedded_program/proc/begin_dock() + dock_state = STATE_DOCKING + begin_cycle_in() + +//get the docking port into a good state for undocking. +/datum/computer/file/embedded_program/proc/begin_undock() + dock_state = STATE_UNDOCKING + stop_cycling() + + //close the doors + toggleDoor(memory["interior_status"], tag_interior_door, memory["secure"], "close") + toggleDoor(memory["exterior_status"], tag_exterior_door, memory["secure"], "close") \ No newline at end of file