diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
index 9be950ddd08..eaf95077d46 100644
--- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
@@ -1,269 +1,269 @@
-/obj/machinery/atmospherics/binary/dp_vent_pump
- icon = 'icons/atmos/vent_pump.dmi'
- icon_state = "map_dp_vent"
-
- //node2 is output port
- //node1 is input port
-
- req_one_access_txt = "24;10"
-
- name = "dual-port air vent"
- desc = "Has a valve and pump attached to it. There are two ports."
-
- can_unwrench = 1
-
- level = 1
-
- connect_types = list(1,2,3) //connects to regular, supply and scrubbers pipes
-
- var/on = 0
- var/pump_direction = 1 //0 = siphoning, 1 = releasing
-
- var/external_pressure_bound = ONE_ATMOSPHERE
- var/input_pressure_min = 0
- var/output_pressure_max = 0
-
- var/frequency = ATMOS_VENTSCRUB
- var/id_tag = null
- var/datum/radio_frequency/radio_connection
- var/advcontrol = 0//does this device listen to the AAC
-
- settagwhitelist = list("id_tag")
-
- var/pressure_checks = 1
- //1: Do not pass external_pressure_bound
- //2: Do not pass input_pressure_min
- //4: Do not pass output_pressure_max
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/New()
- ..()
- if(!id_tag)
- assign_uid()
- id_tag = num2text(uid)
- icon = null
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/Destroy()
- if(SSradio)
- SSradio.remove_object(src, frequency)
- radio_connection = null
- return ..()
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/atmos_init()
- ..()
- if(frequency)
- set_frequency(frequency)
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume
- name = "large dual port air vent"
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume/on
- on = TRUE
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume/New()
- ..()
- air1.volume = 1000
- air2.volume = 1000
-
-/obj/machinery/atmospherics/binary/volume_pump/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- add_underlay(T, node1, turn(dir, -180))
- add_underlay(T, node2, dir)
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/update_icon(var/safety = 0)
- ..()
-
- if(!check_icon_cache())
- return
-
- overlays.Cut()
-
- var/vent_icon = "vent"
-
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
-
- if(T.intact && node1 && node2 && node1.level == 1 && node2.level == 1 && istype(node1, /obj/machinery/atmospherics/pipe) && istype(node2, /obj/machinery/atmospherics/pipe))
- vent_icon += "h"
-
- if(!powered())
- vent_icon += "off"
- else
- vent_icon += "[on ? "[pump_direction ? "out" : "in"]" : "off"]"
-
- overlays += GLOB.pipe_icon_manager.get_atmos_icon("device", , , vent_icon)
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- if(T.intact && node1 && node2 && node1.level == 1 && node2.level == 1 && istype(node1, /obj/machinery/atmospherics/pipe) && istype(node2, /obj/machinery/atmospherics/pipe))
- return
- else
- if(node1)
- add_underlay(T, node1, turn(dir, -180), node1.icon_connect_type)
- else
- add_underlay(T, node1, turn(dir, -180))
- if(node2)
- add_underlay(T, node2, dir, node2.icon_connect_type)
- else
- add_underlay(T, node2, dir)
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/process_atmos()
- ..()
- if(!on)
- return 0
-
- var/datum/gas_mixture/environment = loc.return_air()
- var/environment_pressure = environment.return_pressure()
-
- if(pump_direction) //input -> external
- var/pressure_delta = 10000
-
- if(pressure_checks&1)
- pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure))
- if(pressure_checks&2)
- pressure_delta = min(pressure_delta, (air1.return_pressure() - input_pressure_min))
-
- if(pressure_delta > 0)
- if(air1.temperature > 0)
- var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
-
- var/datum/gas_mixture/removed = air1.remove(transfer_moles)
-
- loc.assume_air(removed)
-
- parent1.update = 1
- air_update_turf()
- else //external -> output
- var/pressure_delta = 10000
-
- if(pressure_checks&1)
- pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound))
- if(pressure_checks&4)
- pressure_delta = min(pressure_delta, (output_pressure_max - air2.return_pressure()))
-
- if(pressure_delta > 0)
- if(environment.temperature > 0)
- var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION)
-
- var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
-
- air2.merge(removed)
-
- parent2.update = 1
- air_update_turf()
- return 1
-
-//Radio remote control
-/obj/machinery/atmospherics/binary/dp_vent_pump/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/proc/broadcast_status()
- if(!radio_connection)
- return 0
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
- "tag" = id_tag,
- "device" = "ADVP",
- "power" = on,
- "direction" = pump_direction?("release"):("siphon"),
- "checks" = pressure_checks,
- "input" = input_pressure_min,
- "output" = output_pressure_max,
- "external" = external_pressure_bound,
- "sigtype" = "status"
- )
- radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
-
- return 1
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/receive_signal(datum/signal/signal)
- if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command") || (signal.data["advcontrol"] && !advcontrol))
- return 0
- if(signal.data["power"] != null)
- on = text2num(signal.data["power"])
-
- if(signal.data["power_toggle"] != null)
- on = !on
-
- if(signal.data["direction"] != null)
- pump_direction = text2num(signal.data["direction"])
-
- if(signal.data["checks"] != null)
- pressure_checks = text2num(signal.data["checks"])
-
- if(signal.data["purge"])
- pressure_checks &= ~1
- pump_direction = 0
-
- if(signal.data["stabilize"])//the fact that this was "stabalize" shows how many fucks people give about these wonders, none
- pressure_checks |= 1
- pump_direction = 1
-
- if(signal.data["set_input_pressure"] != null)
- input_pressure_min = between(
- 0,
- text2num(signal.data["set_input_pressure"]),
- ONE_ATMOSPHERE*50
- )
-
- if(signal.data["set_output_pressure"] != null)
- output_pressure_max = between(
- 0,
- text2num(signal.data["set_output_pressure"]),
- ONE_ATMOSPHERE*50
- )
-
- if(signal.data["set_external_pressure"] != null)
- external_pressure_bound = between(
- 0,
- text2num(signal.data["set_external_pressure"]),
- ONE_ATMOSPHERE*50
- )
-
- if(signal.data["status"])
- spawn(2)
- broadcast_status()
- return //do not update_icon
-
- spawn(2)
- broadcast_status()
- update_icon()
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/attackby(var/obj/item/W as obj, var/mob/user as mob)
- if(istype(W, /obj/item/multitool))
- update_multitool_menu(user)
- return 1
-
- return ..()
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/multitool_menu(var/mob/user,var/obj/item/multitool/P)
- return {"
-
- "}
-
-/obj/machinery/atmospherics/binary/dp_vent_pump/multitool_topic(var/mob/user, var/list/href_list, var/obj/O)
- . = ..()
- if(.)
- return .
- if("toggleadvcontrol" in href_list)
- advcontrol = !advcontrol
- return TRUE
+/obj/machinery/atmospherics/binary/dp_vent_pump
+ icon = 'icons/atmos/vent_pump.dmi'
+ icon_state = "map_dp_vent"
+
+ //node2 is output port
+ //node1 is input port
+
+ req_one_access_txt = "24;10"
+
+ name = "dual-port air vent"
+ desc = "Has a valve and pump attached to it. There are two ports."
+
+ can_unwrench = 1
+
+ level = 1
+
+ connect_types = list(1,2,3) //connects to regular, supply and scrubbers pipes
+
+ var/on = 0
+ var/pump_direction = 1 //0 = siphoning, 1 = releasing
+
+ var/external_pressure_bound = ONE_ATMOSPHERE
+ var/input_pressure_min = 0
+ var/output_pressure_max = 0
+
+ var/frequency = ATMOS_VENTSCRUB
+ var/id_tag = null
+ var/datum/radio_frequency/radio_connection
+ var/advcontrol = 0//does this device listen to the AAC
+
+ settagwhitelist = list("id_tag")
+
+ var/pressure_checks = 1
+ //1: Do not pass external_pressure_bound
+ //2: Do not pass input_pressure_min
+ //4: Do not pass output_pressure_max
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/New()
+ ..()
+ if(!id_tag)
+ assign_uid()
+ id_tag = num2text(uid)
+ icon = null
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/Destroy()
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
+ radio_connection = null
+ return ..()
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/atmos_init()
+ ..()
+ if(frequency)
+ set_frequency(frequency)
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume
+ name = "large dual port air vent"
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume/on
+ on = TRUE
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume/New()
+ ..()
+ air1.volume = 1000
+ air2.volume = 1000
+
+/obj/machinery/atmospherics/binary/volume_pump/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ add_underlay(T, node1, turn(dir, -180))
+ add_underlay(T, node2, dir)
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/update_icon(var/safety = 0)
+ ..()
+
+ if(!check_icon_cache())
+ return
+
+ overlays.Cut()
+
+ var/vent_icon = "vent"
+
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+
+ if(T.intact && node1 && node2 && node1.level == 1 && node2.level == 1 && istype(node1, /obj/machinery/atmospherics/pipe) && istype(node2, /obj/machinery/atmospherics/pipe))
+ vent_icon += "h"
+
+ if(!powered())
+ vent_icon += "off"
+ else
+ vent_icon += "[on ? "[pump_direction ? "out" : "in"]" : "off"]"
+
+ overlays += GLOB.pipe_icon_manager.get_atmos_icon("device", , , vent_icon)
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ if(T.intact && node1 && node2 && node1.level == 1 && node2.level == 1 && istype(node1, /obj/machinery/atmospherics/pipe) && istype(node2, /obj/machinery/atmospherics/pipe))
+ return
+ else
+ if(node1)
+ add_underlay(T, node1, turn(dir, -180), node1.icon_connect_type)
+ else
+ add_underlay(T, node1, turn(dir, -180))
+ if(node2)
+ add_underlay(T, node2, dir, node2.icon_connect_type)
+ else
+ add_underlay(T, node2, dir)
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/process_atmos()
+ ..()
+ if(!on)
+ return 0
+
+ var/datum/gas_mixture/environment = loc.return_air()
+ var/environment_pressure = environment.return_pressure()
+
+ if(pump_direction) //input -> external
+ var/pressure_delta = 10000
+
+ if(pressure_checks&1)
+ pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure))
+ if(pressure_checks&2)
+ pressure_delta = min(pressure_delta, (air1.return_pressure() - input_pressure_min))
+
+ if(pressure_delta > 0)
+ if(air1.temperature > 0)
+ var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
+
+ var/datum/gas_mixture/removed = air1.remove(transfer_moles)
+
+ loc.assume_air(removed)
+
+ parent1.update = 1
+ air_update_turf()
+ else //external -> output
+ var/pressure_delta = 10000
+
+ if(pressure_checks&1)
+ pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound))
+ if(pressure_checks&4)
+ pressure_delta = min(pressure_delta, (output_pressure_max - air2.return_pressure()))
+
+ if(pressure_delta > 0)
+ if(environment.temperature > 0)
+ var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION)
+
+ var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
+
+ air2.merge(removed)
+
+ parent2.update = 1
+ air_update_turf()
+ return 1
+
+//Radio remote control
+/obj/machinery/atmospherics/binary/dp_vent_pump/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ if(frequency)
+ radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/proc/broadcast_status()
+ if(!radio_connection)
+ return 0
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ signal.data = list(
+ "tag" = id_tag,
+ "device" = "ADVP",
+ "power" = on,
+ "direction" = pump_direction?("release"):("siphon"),
+ "checks" = pressure_checks,
+ "input" = input_pressure_min,
+ "output" = output_pressure_max,
+ "external" = external_pressure_bound,
+ "sigtype" = "status"
+ )
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+
+ return 1
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/receive_signal(datum/signal/signal)
+ if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command") || (signal.data["advcontrol"] && !advcontrol))
+ return 0
+ if(signal.data["power"] != null)
+ on = text2num(signal.data["power"])
+
+ if(signal.data["power_toggle"] != null)
+ on = !on
+
+ if(signal.data["direction"] != null)
+ pump_direction = text2num(signal.data["direction"])
+
+ if(signal.data["checks"] != null)
+ pressure_checks = text2num(signal.data["checks"])
+
+ if(signal.data["purge"])
+ pressure_checks &= ~1
+ pump_direction = 0
+
+ if(signal.data["stabilize"])//the fact that this was "stabalize" shows how many fucks people give about these wonders, none
+ pressure_checks |= 1
+ pump_direction = 1
+
+ if(signal.data["set_input_pressure"] != null)
+ input_pressure_min = between(
+ 0,
+ text2num(signal.data["set_input_pressure"]),
+ ONE_ATMOSPHERE*50
+ )
+
+ if(signal.data["set_output_pressure"] != null)
+ output_pressure_max = between(
+ 0,
+ text2num(signal.data["set_output_pressure"]),
+ ONE_ATMOSPHERE*50
+ )
+
+ if(signal.data["set_external_pressure"] != null)
+ external_pressure_bound = between(
+ 0,
+ text2num(signal.data["set_external_pressure"]),
+ ONE_ATMOSPHERE*50
+ )
+
+ if(signal.data["status"])
+ spawn(2)
+ broadcast_status()
+ return //do not update_icon
+
+ spawn(2)
+ broadcast_status()
+ update_icon()
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/attackby(var/obj/item/W as obj, var/mob/user as mob)
+ if(istype(W, /obj/item/multitool))
+ update_multitool_menu(user)
+ return 1
+
+ return ..()
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/multitool_menu(var/mob/user,var/obj/item/multitool/P)
+ return {"
+
+ "}
+
+/obj/machinery/atmospherics/binary/dp_vent_pump/multitool_topic(var/mob/user, var/list/href_list, var/obj/O)
+ . = ..()
+ if(.)
+ return .
+ if("toggleadvcontrol" in href_list)
+ advcontrol = !advcontrol
+ return TRUE
diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
index b255e2836c9..05da130494a 100644
--- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
@@ -1,192 +1,192 @@
-/obj/machinery/atmospherics/binary/passive_gate
- //Tries to achieve target pressure at output (like a normal pump) except
- // Uses no power but can not transfer gases from a low pressure area to a high pressure area
- icon = 'icons/atmos/passive_gate.dmi'
- icon_state = "map"
-
- name = "passive gate"
- desc = "A one-way air valve that does not require power"
-
- can_unwrench = 1
-
- var/on = 0
- var/target_pressure = ONE_ATMOSPHERE
-
- var/frequency = 0
- var/id = null
- var/datum/radio_frequency/radio_connection
-
-/obj/machinery/atmospherics/binary/passive_gate/atmos_init()
- ..()
- if(frequency)
- set_frequency(frequency)
-
-/obj/machinery/atmospherics/binary/passive_gate/Destroy()
- if(SSradio)
- SSradio.remove_object(src, frequency)
- radio_connection = null
- return ..()
-
-/obj/machinery/atmospherics/binary/passive_gate/update_icon()
- ..()
- icon_state = "[on ? "on" : "off"]"
-
-/obj/machinery/atmospherics/binary/passive_gate/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- add_underlay(T, node1, turn(dir, 180))
- add_underlay(T, node2, dir)
-
-/obj/machinery/atmospherics/binary/passive_gate/process_atmos()
- ..()
- if(!on)
- return 0
-
- var/output_starting_pressure = air2.return_pressure()
- var/input_starting_pressure = air1.return_pressure()
-
- if(output_starting_pressure >= min(target_pressure,input_starting_pressure-10))
- //No need to pump gas if target is already reached or input pressure is too low
- //Need at least 10 KPa difference to overcome friction in the mechanism
- return 1
-
- //Calculate necessary moles to transfer using PV = nRT
- if((air1.total_moles() > 0) && (air1.temperature>0))
- var/pressure_delta = min(target_pressure - output_starting_pressure, (input_starting_pressure - output_starting_pressure)/2)
- //Can not have a pressure delta that would cause output_pressure > input_pressure
-
- var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
-
- //Actually transfer the gas
- var/datum/gas_mixture/removed = air1.remove(transfer_moles)
- air2.merge(removed)
-
- parent1.update = 1
-
- parent2.update = 1
- return 1
-
-//Radio remote control
-/obj/machinery/atmospherics/binary/passive_gate/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
-
-/obj/machinery/atmospherics/binary/passive_gate/proc/broadcast_status()
- if(!radio_connection)
- return 0
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
- "tag" = id,
- "device" = "AGP",
- "power" = on,
- "target_output" = target_pressure,
- "sigtype" = "status"
- )
-
- radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
-
- return 1
-
-/obj/machinery/atmospherics/binary/passive_gate/receive_signal(datum/signal/signal)
- if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
- return 0
-
- var/old_on = on //for logging
-
- if("power" in signal.data)
- on = text2num(signal.data["power"])
-
- if("power_toggle" in signal.data)
- on = !on
-
- if("set_output_pressure" in signal.data)
- target_pressure = between(
- 0,
- text2num(signal.data["set_output_pressure"]),
- ONE_ATMOSPHERE*50
- )
-
- if(on != old_on)
- investigate_log("was turned [on ? "on" : "off"] by a remote signal", "atmos")
-
- if("status" in signal.data)
- spawn(2)
- broadcast_status()
- return //do not update_icon
-
- spawn(2)
- broadcast_status()
- update_icon()
- return
-
-/obj/machinery/atmospherics/binary/passive_gate/attack_hand(mob/user)
- if(..())
- return
-
- if(!allowed(user))
- to_chat(user, "Access denied.")
- return
-
- add_fingerprint(user)
- ui_interact(user)
-
-/obj/machinery/atmospherics/binary/passive_gate/attack_ghost(mob/user)
- ui_interact(user)
-
-/obj/machinery/atmospherics/binary/passive_gate/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
- user.set_machine(src)
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
- if(!ui)
- ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 385, 115, state = state)
- ui.open()
-
-/obj/machinery/atmospherics/binary/passive_gate/ui_data(mob/user)
- var/list/data = list()
- data["on"] = on
- data["pressure"] = round(target_pressure)
- data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
- return data
-
-/obj/machinery/atmospherics/binary/passive_gate/Topic(href,href_list)
- if(..())
- return 1
-
- if(href_list["power"])
- on = !on
- investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
- . = TRUE
- if(href_list["pressure"])
- var/pressure = href_list["pressure"]
- if(pressure == "max")
- pressure = MAX_OUTPUT_PRESSURE
- . = TRUE
- else if(pressure == "input")
- pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
- if(!isnull(pressure))
- . = TRUE
- else if(text2num(pressure) != null)
- pressure = text2num(pressure)
- . = TRUE
- if(.)
- target_pressure = Clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
- investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
-
- update_icon()
- SSnanoui.update_uis(src)
-
-/obj/machinery/atmospherics/binary/passive_gate/attackby(obj/item/W, mob/user, params)
- if(!istype(W, /obj/item/wrench))
- return ..()
- if(on)
- to_chat(user, "You cannot unwrench this [src], turn it off first.")
- return 1
- return ..()
+/obj/machinery/atmospherics/binary/passive_gate
+ //Tries to achieve target pressure at output (like a normal pump) except
+ // Uses no power but can not transfer gases from a low pressure area to a high pressure area
+ icon = 'icons/atmos/passive_gate.dmi'
+ icon_state = "map"
+
+ name = "passive gate"
+ desc = "A one-way air valve that does not require power"
+
+ can_unwrench = 1
+
+ var/on = 0
+ var/target_pressure = ONE_ATMOSPHERE
+
+ var/frequency = 0
+ var/id = null
+ var/datum/radio_frequency/radio_connection
+
+/obj/machinery/atmospherics/binary/passive_gate/atmos_init()
+ ..()
+ if(frequency)
+ set_frequency(frequency)
+
+/obj/machinery/atmospherics/binary/passive_gate/Destroy()
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
+ radio_connection = null
+ return ..()
+
+/obj/machinery/atmospherics/binary/passive_gate/update_icon()
+ ..()
+ icon_state = "[on ? "on" : "off"]"
+
+/obj/machinery/atmospherics/binary/passive_gate/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ add_underlay(T, node1, turn(dir, 180))
+ add_underlay(T, node2, dir)
+
+/obj/machinery/atmospherics/binary/passive_gate/process_atmos()
+ ..()
+ if(!on)
+ return 0
+
+ var/output_starting_pressure = air2.return_pressure()
+ var/input_starting_pressure = air1.return_pressure()
+
+ if(output_starting_pressure >= min(target_pressure,input_starting_pressure-10))
+ //No need to pump gas if target is already reached or input pressure is too low
+ //Need at least 10 KPa difference to overcome friction in the mechanism
+ return 1
+
+ //Calculate necessary moles to transfer using PV = nRT
+ if((air1.total_moles() > 0) && (air1.temperature>0))
+ var/pressure_delta = min(target_pressure - output_starting_pressure, (input_starting_pressure - output_starting_pressure)/2)
+ //Can not have a pressure delta that would cause output_pressure > input_pressure
+
+ var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
+
+ //Actually transfer the gas
+ var/datum/gas_mixture/removed = air1.remove(transfer_moles)
+ air2.merge(removed)
+
+ parent1.update = 1
+
+ parent2.update = 1
+ return 1
+
+//Radio remote control
+/obj/machinery/atmospherics/binary/passive_gate/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ if(frequency)
+ radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
+
+/obj/machinery/atmospherics/binary/passive_gate/proc/broadcast_status()
+ if(!radio_connection)
+ return 0
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ signal.data = list(
+ "tag" = id,
+ "device" = "AGP",
+ "power" = on,
+ "target_output" = target_pressure,
+ "sigtype" = "status"
+ )
+
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+
+ return 1
+
+/obj/machinery/atmospherics/binary/passive_gate/receive_signal(datum/signal/signal)
+ if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
+ return 0
+
+ var/old_on = on //for logging
+
+ if("power" in signal.data)
+ on = text2num(signal.data["power"])
+
+ if("power_toggle" in signal.data)
+ on = !on
+
+ if("set_output_pressure" in signal.data)
+ target_pressure = between(
+ 0,
+ text2num(signal.data["set_output_pressure"]),
+ ONE_ATMOSPHERE*50
+ )
+
+ if(on != old_on)
+ investigate_log("was turned [on ? "on" : "off"] by a remote signal", "atmos")
+
+ if("status" in signal.data)
+ spawn(2)
+ broadcast_status()
+ return //do not update_icon
+
+ spawn(2)
+ broadcast_status()
+ update_icon()
+ return
+
+/obj/machinery/atmospherics/binary/passive_gate/attack_hand(mob/user)
+ if(..())
+ return
+
+ if(!allowed(user))
+ to_chat(user, "Access denied.")
+ return
+
+ add_fingerprint(user)
+ ui_interact(user)
+
+/obj/machinery/atmospherics/binary/passive_gate/attack_ghost(mob/user)
+ ui_interact(user)
+
+/obj/machinery/atmospherics/binary/passive_gate/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
+ user.set_machine(src)
+ ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 385, 115, state = state)
+ ui.open()
+
+/obj/machinery/atmospherics/binary/passive_gate/ui_data(mob/user)
+ var/list/data = list()
+ data["on"] = on
+ data["pressure"] = round(target_pressure)
+ data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
+ return data
+
+/obj/machinery/atmospherics/binary/passive_gate/Topic(href,href_list)
+ if(..())
+ return 1
+
+ if(href_list["power"])
+ on = !on
+ investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
+ . = TRUE
+ if(href_list["pressure"])
+ var/pressure = href_list["pressure"]
+ if(pressure == "max")
+ pressure = MAX_OUTPUT_PRESSURE
+ . = TRUE
+ else if(pressure == "input")
+ pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
+ if(!isnull(pressure))
+ . = TRUE
+ else if(text2num(pressure) != null)
+ pressure = text2num(pressure)
+ . = TRUE
+ if(.)
+ target_pressure = Clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
+ investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
+
+ update_icon()
+ SSnanoui.update_uis(src)
+
+/obj/machinery/atmospherics/binary/passive_gate/attackby(obj/item/W, mob/user, params)
+ if(!istype(W, /obj/item/wrench))
+ return ..()
+ if(on)
+ to_chat(user, "You cannot unwrench this [src], turn it off first.")
+ return 1
+ return ..()
diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm
index b2a7d0948be..a579663a3cc 100644
--- a/code/ATMOSPHERICS/components/binary_devices/pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm
@@ -1,261 +1,261 @@
-/*
-Every cycle, the pump uses the air in air_in to try and make air_out the perfect pressure.
-
-node1, air1, network1 correspond to input
-node2, air2, network2 correspond to output
-
-Thus, the two variables affect pump operation are set in New():
- air1.volume
- This is the volume of gas available to the pump that may be transfered to the output
- air2.volume
- Higher quantities of this cause more air to be perfected later
- but overall network volume is also increased as this increases...
-*/
-
-/obj/machinery/atmospherics/binary/pump
- icon = 'icons/atmos/pump.dmi'
- icon_state = "map_off"
-
- name = "gas pump"
- desc = "A pump"
-
- can_unwrench = 1
-
- var/on = 0
- var/target_pressure = ONE_ATMOSPHERE
-
- var/frequency = 0
- var/id = null
- var/datum/radio_frequency/radio_connection
-
-/obj/machinery/atmospherics/binary/pump/CtrlClick(mob/living/user)
- if(!istype(user) || user.incapacitated())
- to_chat(user, "You can't do that right now!")
- return
- if(!in_range(src, user) && !issilicon(usr))
- return
- if(!ishuman(usr) && !issilicon(usr))
- return
- toggle()
- return ..()
-
-/obj/machinery/atmospherics/binary/pump/AICtrlClick()
- toggle()
- return ..()
-
-/obj/machinery/atmospherics/binary/pump/AltClick(mob/living/user)
- if(!istype(user) || user.incapacitated())
- to_chat(user, "You can't do that right now!")
- return
- if(!in_range(src, user) && !issilicon(usr))
- return
- if(!ishuman(usr) && !issilicon(usr))
- return
- set_max()
- return
-
-/obj/machinery/atmospherics/binary/pump/AIAltClick()
- set_max()
- return ..()
-
-/obj/machinery/atmospherics/binary/pump/proc/toggle()
- if(powered())
- on = !on
- update_icon()
-
-/obj/machinery/atmospherics/binary/pump/proc/set_max()
- if(powered())
- target_pressure = MAX_OUTPUT_PRESSURE
- update_icon()
-
-/obj/machinery/atmospherics/binary/pump/Destroy()
- if(SSradio)
- SSradio.remove_object(src, frequency)
- radio_connection = null
- return ..()
-
-/obj/machinery/atmospherics/binary/pump/on
- icon_state = "map_on"
- on = 1
-
-/obj/machinery/atmospherics/binary/pump/update_icon()
- ..()
-
- if(!powered())
- icon_state = "off"
- else
- icon_state = "[on ? "on" : "off"]"
-
-/obj/machinery/atmospherics/binary/pump/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- add_underlay(T, node1, turn(dir, -180))
- add_underlay(T, node2, dir)
-
-/obj/machinery/atmospherics/binary/pump/process_atmos()
- ..()
- if((stat & (NOPOWER|BROKEN)) || !on)
- return 0
-
- var/output_starting_pressure = air2.return_pressure()
-
- if( (target_pressure - output_starting_pressure) < 0.01)
- //No need to pump gas if target is already reached!
- return 1
-
- //Calculate necessary moles to transfer using PV=nRT
- if((air1.total_moles() > 0) && (air1.temperature>0))
- var/pressure_delta = target_pressure - output_starting_pressure
- var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
-
- //Actually transfer the gas
- var/datum/gas_mixture/removed = air1.remove(transfer_moles)
- air2.merge(removed)
-
- parent1.update = 1
-
- parent2.update = 1
- return 1
-
-//Radio remote control
-/obj/machinery/atmospherics/binary/pump/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
-
-/obj/machinery/atmospherics/binary/pump/proc/broadcast_status()
- if(!radio_connection)
- return 0
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
- "tag" = id,
- "device" = "AGP",
- "power" = on,
- "target_output" = target_pressure,
- "sigtype" = "status"
- )
-
- radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
- return 1
-
-/obj/machinery/atmospherics/binary/pump/atmos_init()
- ..()
- if(frequency)
- set_frequency(frequency)
-
-/obj/machinery/atmospherics/binary/pump/receive_signal(datum/signal/signal)
- if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
- return 0
-
- var/old_on = on //for logging
-
- if(signal.data["power"])
- on = text2num(signal.data["power"])
-
- if(signal.data["power_toggle"])
- on = !on
-
- if(signal.data["set_output_pressure"])
- target_pressure = between(
- 0,
- text2num(signal.data["set_output_pressure"]),
- ONE_ATMOSPHERE*50
- )
-
- if(on != old_on)
- investigate_log("was turned [on ? "on" : "off"] by a remote signal", "atmos")
-
- if(signal.data["status"])
- spawn(2)
- broadcast_status()
- return //do not update_icon
-
- spawn(2)
- broadcast_status()
- update_icon()
- return
-
-/obj/machinery/atmospherics/binary/pump/attack_hand(mob/user)
- if(..())
- return
-
- if(!allowed(user))
- to_chat(user, "Access denied.")
- return
-
- add_fingerprint(user)
- ui_interact(user)
-
-/obj/machinery/atmospherics/binary/pump/attack_ghost(mob/user)
- ui_interact(user)
-
-/obj/machinery/atmospherics/binary/pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
- user.set_machine(src)
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
- if(!ui)
- ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 385, 115, state = state)
- ui.open()
-
-/obj/machinery/atmospherics/binary/pump/ui_data(mob/user)
- var/list/data = list()
- data["on"] = on
- data["pressure"] = round(target_pressure)
- data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
- return data
-
-/obj/machinery/atmospherics/binary/pump/Topic(href,href_list)
- if(..())
- return 1
-
- if(href_list["power"])
- on = !on
- investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
- . = TRUE
- if(href_list["pressure"])
- var/pressure = href_list["pressure"]
- if(pressure == "max")
- pressure = MAX_OUTPUT_PRESSURE
- . = TRUE
- else if(pressure == "input")
- pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
- if(!isnull(pressure))
- . = TRUE
- else if(text2num(pressure) != null)
- pressure = text2num(pressure)
- . = TRUE
- if(.)
- target_pressure = Clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
- investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
-
- update_icon()
- SSnanoui.update_uis(src)
-
-/obj/machinery/atmospherics/binary/pump/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- update_icon()
-
-/obj/machinery/atmospherics/binary/pump/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/pen))
- var/t = copytext(stripped_input(user, "Enter the name for the pump.", "Rename", name), 1, MAX_NAME_LEN)
- if(!t)
- return
- if(!in_range(src, usr) && loc != usr)
- return
- name = t
- return
- else if(!istype(W, /obj/item/wrench))
- return ..()
- if(!(stat & NOPOWER) && on)
- to_chat(user, "You cannot unwrench this [src], turn it off first.")
- return 1
- return ..()
\ No newline at end of file
+/*
+Every cycle, the pump uses the air in air_in to try and make air_out the perfect pressure.
+
+node1, air1, network1 correspond to input
+node2, air2, network2 correspond to output
+
+Thus, the two variables affect pump operation are set in New():
+ air1.volume
+ This is the volume of gas available to the pump that may be transfered to the output
+ air2.volume
+ Higher quantities of this cause more air to be perfected later
+ but overall network volume is also increased as this increases...
+*/
+
+/obj/machinery/atmospherics/binary/pump
+ icon = 'icons/atmos/pump.dmi'
+ icon_state = "map_off"
+
+ name = "gas pump"
+ desc = "A pump"
+
+ can_unwrench = 1
+
+ var/on = 0
+ var/target_pressure = ONE_ATMOSPHERE
+
+ var/frequency = 0
+ var/id = null
+ var/datum/radio_frequency/radio_connection
+
+/obj/machinery/atmospherics/binary/pump/CtrlClick(mob/living/user)
+ if(!istype(user) || user.incapacitated())
+ to_chat(user, "You can't do that right now!")
+ return
+ if(!in_range(src, user) && !issilicon(usr))
+ return
+ if(!ishuman(usr) && !issilicon(usr))
+ return
+ toggle()
+ return ..()
+
+/obj/machinery/atmospherics/binary/pump/AICtrlClick()
+ toggle()
+ return ..()
+
+/obj/machinery/atmospherics/binary/pump/AltClick(mob/living/user)
+ if(!istype(user) || user.incapacitated())
+ to_chat(user, "You can't do that right now!")
+ return
+ if(!in_range(src, user) && !issilicon(usr))
+ return
+ if(!ishuman(usr) && !issilicon(usr))
+ return
+ set_max()
+ return
+
+/obj/machinery/atmospherics/binary/pump/AIAltClick()
+ set_max()
+ return ..()
+
+/obj/machinery/atmospherics/binary/pump/proc/toggle()
+ if(powered())
+ on = !on
+ update_icon()
+
+/obj/machinery/atmospherics/binary/pump/proc/set_max()
+ if(powered())
+ target_pressure = MAX_OUTPUT_PRESSURE
+ update_icon()
+
+/obj/machinery/atmospherics/binary/pump/Destroy()
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
+ radio_connection = null
+ return ..()
+
+/obj/machinery/atmospherics/binary/pump/on
+ icon_state = "map_on"
+ on = 1
+
+/obj/machinery/atmospherics/binary/pump/update_icon()
+ ..()
+
+ if(!powered())
+ icon_state = "off"
+ else
+ icon_state = "[on ? "on" : "off"]"
+
+/obj/machinery/atmospherics/binary/pump/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ add_underlay(T, node1, turn(dir, -180))
+ add_underlay(T, node2, dir)
+
+/obj/machinery/atmospherics/binary/pump/process_atmos()
+ ..()
+ if((stat & (NOPOWER|BROKEN)) || !on)
+ return 0
+
+ var/output_starting_pressure = air2.return_pressure()
+
+ if( (target_pressure - output_starting_pressure) < 0.01)
+ //No need to pump gas if target is already reached!
+ return 1
+
+ //Calculate necessary moles to transfer using PV=nRT
+ if((air1.total_moles() > 0) && (air1.temperature>0))
+ var/pressure_delta = target_pressure - output_starting_pressure
+ var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
+
+ //Actually transfer the gas
+ var/datum/gas_mixture/removed = air1.remove(transfer_moles)
+ air2.merge(removed)
+
+ parent1.update = 1
+
+ parent2.update = 1
+ return 1
+
+//Radio remote control
+/obj/machinery/atmospherics/binary/pump/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ if(frequency)
+ radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
+
+/obj/machinery/atmospherics/binary/pump/proc/broadcast_status()
+ if(!radio_connection)
+ return 0
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ signal.data = list(
+ "tag" = id,
+ "device" = "AGP",
+ "power" = on,
+ "target_output" = target_pressure,
+ "sigtype" = "status"
+ )
+
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+ return 1
+
+/obj/machinery/atmospherics/binary/pump/atmos_init()
+ ..()
+ if(frequency)
+ set_frequency(frequency)
+
+/obj/machinery/atmospherics/binary/pump/receive_signal(datum/signal/signal)
+ if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
+ return 0
+
+ var/old_on = on //for logging
+
+ if(signal.data["power"])
+ on = text2num(signal.data["power"])
+
+ if(signal.data["power_toggle"])
+ on = !on
+
+ if(signal.data["set_output_pressure"])
+ target_pressure = between(
+ 0,
+ text2num(signal.data["set_output_pressure"]),
+ ONE_ATMOSPHERE*50
+ )
+
+ if(on != old_on)
+ investigate_log("was turned [on ? "on" : "off"] by a remote signal", "atmos")
+
+ if(signal.data["status"])
+ spawn(2)
+ broadcast_status()
+ return //do not update_icon
+
+ spawn(2)
+ broadcast_status()
+ update_icon()
+ return
+
+/obj/machinery/atmospherics/binary/pump/attack_hand(mob/user)
+ if(..())
+ return
+
+ if(!allowed(user))
+ to_chat(user, "Access denied.")
+ return
+
+ add_fingerprint(user)
+ ui_interact(user)
+
+/obj/machinery/atmospherics/binary/pump/attack_ghost(mob/user)
+ ui_interact(user)
+
+/obj/machinery/atmospherics/binary/pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
+ user.set_machine(src)
+ ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 385, 115, state = state)
+ ui.open()
+
+/obj/machinery/atmospherics/binary/pump/ui_data(mob/user)
+ var/list/data = list()
+ data["on"] = on
+ data["pressure"] = round(target_pressure)
+ data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
+ return data
+
+/obj/machinery/atmospherics/binary/pump/Topic(href,href_list)
+ if(..())
+ return 1
+
+ if(href_list["power"])
+ on = !on
+ investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
+ . = TRUE
+ if(href_list["pressure"])
+ var/pressure = href_list["pressure"]
+ if(pressure == "max")
+ pressure = MAX_OUTPUT_PRESSURE
+ . = TRUE
+ else if(pressure == "input")
+ pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
+ if(!isnull(pressure))
+ . = TRUE
+ else if(text2num(pressure) != null)
+ pressure = text2num(pressure)
+ . = TRUE
+ if(.)
+ target_pressure = Clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
+ investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
+
+ update_icon()
+ SSnanoui.update_uis(src)
+
+/obj/machinery/atmospherics/binary/pump/power_change()
+ var/old_stat = stat
+ ..()
+ if(old_stat != stat)
+ update_icon()
+
+/obj/machinery/atmospherics/binary/pump/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/pen))
+ var/t = copytext(stripped_input(user, "Enter the name for the pump.", "Rename", name), 1, MAX_NAME_LEN)
+ if(!t)
+ return
+ if(!in_range(src, usr) && loc != usr)
+ return
+ name = t
+ return
+ else if(!istype(W, /obj/item/wrench))
+ return ..()
+ if(!(stat & NOPOWER) && on)
+ to_chat(user, "You cannot unwrench this [src], turn it off first.")
+ return 1
+ return ..()
diff --git a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
index 6dab5ddd441..b664b09b320 100644
--- a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
@@ -1,257 +1,257 @@
-/*
-Every cycle, the pump uses the air in air_in to try and make air_out the perfect pressure.
-
-node1, air1, network1 correspond to input
-node2, air2, network2 correspond to output
-
-Thus, the two variables affect pump operation are set in New():
- air1.volume
- This is the volume of gas available to the pump that may be transfered to the output
- air2.volume
- Higher quantities of this cause more air to be perfected later
- but overall network volume is also increased as this increases...
-*/
-
-/obj/machinery/atmospherics/binary/volume_pump
- icon = 'icons/atmos/volume_pump.dmi'
- icon_state = "map_off"
-
- name = "volumetric gas pump"
- desc = "A volumetric pump"
-
- can_unwrench = 1
-
- var/on = 0
- var/transfer_rate = 200
-
- var/frequency = 0
- var/id = null
- var/datum/radio_frequency/radio_connection
-
-/obj/machinery/atmospherics/binary/volume_pump/CtrlClick(mob/living/user)
- if(!istype(user) || user.incapacitated())
- to_chat(user, "You can't do that right now!")
- return
- if(!in_range(src, user) && !issilicon(usr))
- return
- if(!ishuman(usr) && !issilicon(usr))
- return
- toggle()
- return ..()
-
-/obj/machinery/atmospherics/binary/volume_pump/AICtrlClick()
- toggle()
- return ..()
-
-/obj/machinery/atmospherics/binary/volume_pump/AltClick(mob/living/user)
- if(!istype(user) || user.incapacitated())
- to_chat(user, "You can't do that right now!")
- return
- if(!in_range(src, user) && !issilicon(usr))
- return
- if(!ishuman(usr) && !issilicon(usr))
- return
- set_max()
- return
-
-/obj/machinery/atmospherics/binary/volume_pump/AIAltClick()
- set_max()
- return ..()
-
-/obj/machinery/atmospherics/binary/volume_pump/proc/toggle()
- if(powered())
- on = !on
- update_icon()
-
-/obj/machinery/atmospherics/binary/volume_pump/proc/set_max()
- if(powered())
- transfer_rate = MAX_TRANSFER_RATE
- update_icon()
-
-/obj/machinery/atmospherics/binary/volume_pump/Destroy()
- if(SSradio)
- SSradio.remove_object(src, frequency)
- radio_connection = null
- return ..()
-
-/obj/machinery/atmospherics/binary/volume_pump/on
- on = 1
- icon_state = "map_on"
-
-/obj/machinery/atmospherics/binary/volume_pump/atmos_init()
- ..()
- set_frequency(frequency)
-
-/obj/machinery/atmospherics/binary/volume_pump/update_icon()
- ..()
-
- if(!powered())
- icon_state = "off"
- else
- icon_state = "[on ? "on" : "off"]"
-
-/obj/machinery/atmospherics/binary/volume_pump/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- add_underlay(T, node1, turn(dir, -180))
- add_underlay(T, node2, dir)
-
-/obj/machinery/atmospherics/binary/volume_pump/process_atmos()
- ..()
- if((stat & (NOPOWER|BROKEN)) || !on)
- return 0
-
- // Pump mechanism just won't do anything if the pressure is too high/too low
- var/input_starting_pressure = air1.return_pressure()
- var/output_starting_pressure = air2.return_pressure()
-
- if((input_starting_pressure < 0.01) || (output_starting_pressure > 9000))
- return 1
-
- var/transfer_ratio = max(1, transfer_rate/air1.volume)
-
- var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio)
-
- air2.merge(removed)
-
-
- parent1.update = 1
- parent2.update = 1
-
- return 1
-
-/obj/machinery/atmospherics/binary/volume_pump/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = SSradio.add_object(src, frequency)
-
-/obj/machinery/atmospherics/binary/volume_pump/proc/broadcast_status()
- if(!radio_connection)
- return 0
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
- "tag" = id,
- "device" = "APV",
- "power" = on,
- "transfer_rate" = transfer_rate,
- "sigtype" = "status"
- )
- radio_connection.post_signal(src, signal)
-
- return 1
-
-/obj/machinery/atmospherics/binary/volume_pump/receive_signal(datum/signal/signal)
- if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
- return 0
-
- var/old_on = on //for logging
-
- if(signal.data["power"])
- on = text2num(signal.data["power"])
-
- if(signal.data["power_toggle"])
- on = !on
-
- if(signal.data["set_transfer_rate"])
- transfer_rate = between(
- 0,
- text2num(signal.data["set_transfer_rate"]),
- air1.volume
- )
-
- if(on != old_on)
- investigate_log("was turned [on ? "on" : "off"] by a remote signal", "atmos")
-
- if(signal.data["status"])
- spawn(2)
- broadcast_status()
- return //do not update_icon
-
- spawn(2)
- broadcast_status()
- update_icon()
-
-/obj/machinery/atmospherics/binary/volume_pump/attack_hand(mob/user)
- if(..())
- return
-
- if(!allowed(user))
- to_chat(user, "Access denied.")
- return
-
- add_fingerprint(user)
- ui_interact(user)
-
-/obj/machinery/atmospherics/binary/volume_pump/attack_ghost(mob/user)
- ui_interact(user)
-
-/obj/machinery/atmospherics/binary/volume_pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
- user.set_machine(src)
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
- if(!ui)
- ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 310, 115, state = state)
- ui.open()
-
-/obj/machinery/atmospherics/binary/volume_pump/ui_data(mob/user)
- var/list/data = list()
- data["on"] = on
- data["rate"] = round(transfer_rate)
- data["max_rate"] = round(MAX_TRANSFER_RATE)
- return data
-
-/obj/machinery/atmospherics/binary/volume_pump/Topic(href,href_list)
- if(..())
- return 1
-
- if(href_list["power"])
- on = !on
- investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
- . = TRUE
- if(href_list["rate"])
- var/rate = href_list["rate"]
- if(rate == "max")
- rate = MAX_TRANSFER_RATE
- . = TRUE
- else if(rate == "input")
- rate = input("New transfer rate (0-[MAX_TRANSFER_RATE] L/s):", name, transfer_rate) as num|null
- if(!isnull(rate))
- . = TRUE
- else if(text2num(rate) != null)
- rate = text2num(rate)
- . = TRUE
- if(.)
- transfer_rate = Clamp(rate, 0, MAX_TRANSFER_RATE)
- investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", "atmos")
-
- update_icon()
- SSnanoui.update_uis(src)
-
-/obj/machinery/atmospherics/binary/volume_pump/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- update_icon()
-
-/obj/machinery/atmospherics/binary/volume_pump/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/pen))
- var/t = copytext(stripped_input(user, "Enter the name for the volume pump.", "Rename", name), 1, MAX_NAME_LEN)
- if(!t)
- return
- if(!in_range(src, usr) && loc != usr)
- return
- name = t
- return
- else if(!istype(W, /obj/item/wrench))
- return ..()
- if(!(stat & NOPOWER) && on)
- to_chat(user, "You cannot unwrench this [src], turn it off first.")
- return 1
- return ..()
\ No newline at end of file
+/*
+Every cycle, the pump uses the air in air_in to try and make air_out the perfect pressure.
+
+node1, air1, network1 correspond to input
+node2, air2, network2 correspond to output
+
+Thus, the two variables affect pump operation are set in New():
+ air1.volume
+ This is the volume of gas available to the pump that may be transfered to the output
+ air2.volume
+ Higher quantities of this cause more air to be perfected later
+ but overall network volume is also increased as this increases...
+*/
+
+/obj/machinery/atmospherics/binary/volume_pump
+ icon = 'icons/atmos/volume_pump.dmi'
+ icon_state = "map_off"
+
+ name = "volumetric gas pump"
+ desc = "A volumetric pump"
+
+ can_unwrench = 1
+
+ var/on = 0
+ var/transfer_rate = 200
+
+ var/frequency = 0
+ var/id = null
+ var/datum/radio_frequency/radio_connection
+
+/obj/machinery/atmospherics/binary/volume_pump/CtrlClick(mob/living/user)
+ if(!istype(user) || user.incapacitated())
+ to_chat(user, "You can't do that right now!")
+ return
+ if(!in_range(src, user) && !issilicon(usr))
+ return
+ if(!ishuman(usr) && !issilicon(usr))
+ return
+ toggle()
+ return ..()
+
+/obj/machinery/atmospherics/binary/volume_pump/AICtrlClick()
+ toggle()
+ return ..()
+
+/obj/machinery/atmospherics/binary/volume_pump/AltClick(mob/living/user)
+ if(!istype(user) || user.incapacitated())
+ to_chat(user, "You can't do that right now!")
+ return
+ if(!in_range(src, user) && !issilicon(usr))
+ return
+ if(!ishuman(usr) && !issilicon(usr))
+ return
+ set_max()
+ return
+
+/obj/machinery/atmospherics/binary/volume_pump/AIAltClick()
+ set_max()
+ return ..()
+
+/obj/machinery/atmospherics/binary/volume_pump/proc/toggle()
+ if(powered())
+ on = !on
+ update_icon()
+
+/obj/machinery/atmospherics/binary/volume_pump/proc/set_max()
+ if(powered())
+ transfer_rate = MAX_TRANSFER_RATE
+ update_icon()
+
+/obj/machinery/atmospherics/binary/volume_pump/Destroy()
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
+ radio_connection = null
+ return ..()
+
+/obj/machinery/atmospherics/binary/volume_pump/on
+ on = 1
+ icon_state = "map_on"
+
+/obj/machinery/atmospherics/binary/volume_pump/atmos_init()
+ ..()
+ set_frequency(frequency)
+
+/obj/machinery/atmospherics/binary/volume_pump/update_icon()
+ ..()
+
+ if(!powered())
+ icon_state = "off"
+ else
+ icon_state = "[on ? "on" : "off"]"
+
+/obj/machinery/atmospherics/binary/volume_pump/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ add_underlay(T, node1, turn(dir, -180))
+ add_underlay(T, node2, dir)
+
+/obj/machinery/atmospherics/binary/volume_pump/process_atmos()
+ ..()
+ if((stat & (NOPOWER|BROKEN)) || !on)
+ return 0
+
+ // Pump mechanism just won't do anything if the pressure is too high/too low
+ var/input_starting_pressure = air1.return_pressure()
+ var/output_starting_pressure = air2.return_pressure()
+
+ if((input_starting_pressure < 0.01) || (output_starting_pressure > 9000))
+ return 1
+
+ var/transfer_ratio = max(1, transfer_rate/air1.volume)
+
+ var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio)
+
+ air2.merge(removed)
+
+
+ parent1.update = 1
+ parent2.update = 1
+
+ return 1
+
+/obj/machinery/atmospherics/binary/volume_pump/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ if(frequency)
+ radio_connection = SSradio.add_object(src, frequency)
+
+/obj/machinery/atmospherics/binary/volume_pump/proc/broadcast_status()
+ if(!radio_connection)
+ return 0
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ signal.data = list(
+ "tag" = id,
+ "device" = "APV",
+ "power" = on,
+ "transfer_rate" = transfer_rate,
+ "sigtype" = "status"
+ )
+ radio_connection.post_signal(src, signal)
+
+ return 1
+
+/obj/machinery/atmospherics/binary/volume_pump/receive_signal(datum/signal/signal)
+ if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
+ return 0
+
+ var/old_on = on //for logging
+
+ if(signal.data["power"])
+ on = text2num(signal.data["power"])
+
+ if(signal.data["power_toggle"])
+ on = !on
+
+ if(signal.data["set_transfer_rate"])
+ transfer_rate = between(
+ 0,
+ text2num(signal.data["set_transfer_rate"]),
+ air1.volume
+ )
+
+ if(on != old_on)
+ investigate_log("was turned [on ? "on" : "off"] by a remote signal", "atmos")
+
+ if(signal.data["status"])
+ spawn(2)
+ broadcast_status()
+ return //do not update_icon
+
+ spawn(2)
+ broadcast_status()
+ update_icon()
+
+/obj/machinery/atmospherics/binary/volume_pump/attack_hand(mob/user)
+ if(..())
+ return
+
+ if(!allowed(user))
+ to_chat(user, "Access denied.")
+ return
+
+ add_fingerprint(user)
+ ui_interact(user)
+
+/obj/machinery/atmospherics/binary/volume_pump/attack_ghost(mob/user)
+ ui_interact(user)
+
+/obj/machinery/atmospherics/binary/volume_pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
+ user.set_machine(src)
+ ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "atmos_pump.tmpl", name, 310, 115, state = state)
+ ui.open()
+
+/obj/machinery/atmospherics/binary/volume_pump/ui_data(mob/user)
+ var/list/data = list()
+ data["on"] = on
+ data["rate"] = round(transfer_rate)
+ data["max_rate"] = round(MAX_TRANSFER_RATE)
+ return data
+
+/obj/machinery/atmospherics/binary/volume_pump/Topic(href,href_list)
+ if(..())
+ return 1
+
+ if(href_list["power"])
+ on = !on
+ investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
+ . = TRUE
+ if(href_list["rate"])
+ var/rate = href_list["rate"]
+ if(rate == "max")
+ rate = MAX_TRANSFER_RATE
+ . = TRUE
+ else if(rate == "input")
+ rate = input("New transfer rate (0-[MAX_TRANSFER_RATE] L/s):", name, transfer_rate) as num|null
+ if(!isnull(rate))
+ . = TRUE
+ else if(text2num(rate) != null)
+ rate = text2num(rate)
+ . = TRUE
+ if(.)
+ transfer_rate = Clamp(rate, 0, MAX_TRANSFER_RATE)
+ investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", "atmos")
+
+ update_icon()
+ SSnanoui.update_uis(src)
+
+/obj/machinery/atmospherics/binary/volume_pump/power_change()
+ var/old_stat = stat
+ ..()
+ if(old_stat != stat)
+ update_icon()
+
+/obj/machinery/atmospherics/binary/volume_pump/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/pen))
+ var/t = copytext(stripped_input(user, "Enter the name for the volume pump.", "Rename", name), 1, MAX_NAME_LEN)
+ if(!t)
+ return
+ if(!in_range(src, usr) && loc != usr)
+ return
+ name = t
+ return
+ else if(!istype(W, /obj/item/wrench))
+ return ..()
+ if(!(stat & NOPOWER) && on)
+ to_chat(user, "You cannot unwrench this [src], turn it off first.")
+ return 1
+ return ..()
diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
index 174c77f6753..16897c59b9a 100755
--- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
@@ -1,267 +1,267 @@
-/obj/machinery/atmospherics/trinary/filter
- icon = 'icons/atmos/filter.dmi'
- icon_state = "map"
-
- can_unwrench = 1
-
- name = "gas filter"
-
- var/target_pressure = ONE_ATMOSPHERE
-
- var/filter_type = 0
-/*
-Filter types:
--1: Nothing
- 0: Toxins: Toxins, Oxygen Agent B
- 1: Oxygen: Oxygen ONLY
- 2: Nitrogen: Nitrogen ONLY
- 3: Carbon Dioxide: Carbon Dioxide ONLY
- 4: Sleeping Agent (N2O)
-*/
-
- var/frequency = 0
- var/datum/radio_frequency/radio_connection
-
-/obj/machinery/atmospherics/trinary/filter/CtrlClick(mob/living/user)
- if(!istype(user) || user.incapacitated())
- to_chat(user, "You can't do that right now!")
- return
- if(!in_range(src, user) && !issilicon(usr))
- return
- if(!ishuman(usr) && !issilicon(usr))
- return
- toggle()
- return ..()
-
-/obj/machinery/atmospherics/trinary/filter/AICtrlClick()
- toggle()
- return ..()
-
-/obj/machinery/atmospherics/trinary/filter/AltClick(mob/living/user)
- if(!istype(user) || user.incapacitated())
- to_chat(user, "You can't do that right now!")
- return
- if(!in_range(src, user) && !issilicon(usr))
- return
- if(!ishuman(usr) && !issilicon(usr))
- return
- set_max()
- return
-
-/obj/machinery/atmospherics/trinary/filter/AIAltClick()
- set_max()
- return ..()
-
-/obj/machinery/atmospherics/trinary/filter/proc/toggle()
- if(powered())
- on = !on
- update_icon()
-
-/obj/machinery/atmospherics/trinary/filter/proc/set_max()
- if(powered())
- target_pressure = MAX_OUTPUT_PRESSURE
- update_icon()
-
-/obj/machinery/atmospherics/trinary/filter/Destroy()
- if(SSradio)
- SSradio.remove_object(src, frequency)
- radio_connection = null
- return ..()
-
-/obj/machinery/atmospherics/trinary/filter/flipped
- icon_state = "mmap"
- flipped = 1
-
-/obj/machinery/atmospherics/trinary/filter/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
-
-/obj/machinery/atmospherics/trinary/filter/update_icon()
- ..()
-
- if(flipped)
- icon_state = "m"
- else
- icon_state = ""
-
- if(!powered())
- icon_state += "off"
- else if(node2 && node3 && node1)
- icon_state += on ? "on" : "off"
- else
- icon_state += "off"
- on = 0
-
-/obj/machinery/atmospherics/trinary/filter/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
-
- add_underlay(T, node1, turn(dir, -180))
-
- if(flipped)
- add_underlay(T, node2, turn(dir, 90))
- else
- add_underlay(T, node2, turn(dir, -90))
-
- add_underlay(T, node3, dir)
-
-/obj/machinery/atmospherics/trinary/filter/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- update_icon()
-
-/obj/machinery/atmospherics/trinary/filter/process_atmos()
- ..()
- if(!on)
- return 0
-
- var/output_starting_pressure = air3.return_pressure()
-
- if(output_starting_pressure >= target_pressure || air2.return_pressure() >= target_pressure )
- //No need to mix if target is already full!
- return 1
-
- //Calculate necessary moles to transfer using PV=nRT
-
- var/pressure_delta = target_pressure - output_starting_pressure
- var/transfer_moles
-
- if(air1.temperature > 0)
- transfer_moles = pressure_delta*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
-
- //Actually transfer the gas
-
- if(transfer_moles > 0)
- var/datum/gas_mixture/removed = air1.remove(transfer_moles)
-
- if(!removed)
- return
- var/datum/gas_mixture/filtered_out = new
- filtered_out.temperature = removed.temperature
-
- switch(filter_type)
- if(0) //removing hydrocarbons
- filtered_out.toxins = removed.toxins
- removed.toxins = 0
-
- if(removed.trace_gases.len>0)
- for(var/datum/gas/trace_gas in removed.trace_gases)
- if(istype(trace_gas, /datum/gas/oxygen_agent_b))
- removed.trace_gases -= trace_gas
- filtered_out.trace_gases += trace_gas
-
- if(1) //removing O2
- filtered_out.oxygen = removed.oxygen
- removed.oxygen = 0
-
- if(2) //removing N2
- filtered_out.nitrogen = removed.nitrogen
- removed.nitrogen = 0
-
- if(3) //removing CO2
- filtered_out.carbon_dioxide = removed.carbon_dioxide
- removed.carbon_dioxide = 0
-
- if(4)//removing N2O
- if(removed.trace_gases.len>0)
- for(var/datum/gas/trace_gas in removed.trace_gases)
- if(istype(trace_gas, /datum/gas/sleeping_agent))
- removed.trace_gases -= trace_gas
- filtered_out.trace_gases += trace_gas
-
- else
- filtered_out = null
-
-
- air2.merge(filtered_out)
- air3.merge(removed)
-
- parent2.update = 1
-
- parent3.update = 1
-
- parent1.update = 1
-
- return 1
-
-/obj/machinery/atmospherics/trinary/filter/atmos_init()
- set_frequency(frequency)
- ..()
-
-/obj/machinery/atmospherics/trinary/filter/attack_ghost(mob/user)
- ui_interact(user)
-
-/obj/machinery/atmospherics/trinary/filter/attack_hand(mob/user)
- if(..())
- return
-
- if(!allowed(user))
- to_chat(user, "Access denied.")
- return
-
- add_fingerprint(user)
- ui_interact(user)
-
-/obj/machinery/atmospherics/trinary/filter/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
- user.set_machine(src)
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
- if(!ui)
- ui = new(user, src, ui_key, "atmos_filter.tmpl", name, 475, 155, state = state)
- ui.open()
-
-/obj/machinery/atmospherics/trinary/filter/ui_data(mob/user)
- var/list/data = list()
- data["on"] = on
- data["pressure"] = round(target_pressure)
- data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
- data["filter_type"] = filter_type
- return data
-
-/obj/machinery/atmospherics/trinary/filter/Topic(href, href_list) // -- TLE
- if(..())
- return 1
-
- if(href_list["power"])
- on = !on
- investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
- . = TRUE
- if(href_list["pressure"])
- var/pressure = href_list["pressure"]
- if(pressure == "max")
- pressure = MAX_OUTPUT_PRESSURE
- . = TRUE
- else if(pressure == "input")
- pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
- if(!isnull(pressure) && !..())
- . = TRUE
- else if(text2num(pressure) != null)
- pressure = text2num(pressure)
- . = TRUE
- if(.)
- target_pressure = Clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
- investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
- if(href_list["filter"])
- filter_type = text2num(href_list["filter"])
- investigate_log("was set to filter [filter_type] by [key_name(usr)]", "atmos")
- . = TRUE
-
- update_icon()
- SSnanoui.update_uis(src)
-
-/obj/machinery/atmospherics/trinary/filter/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/pen))
- var/t = copytext(stripped_input(user, "Enter the name for the filter.", "Rename", name), 1, MAX_NAME_LEN)
- if(!t)
- return
- if(!in_range(src, usr) && loc != usr)
- return
- name = t
- return
- else
- return ..()
\ No newline at end of file
+/obj/machinery/atmospherics/trinary/filter
+ icon = 'icons/atmos/filter.dmi'
+ icon_state = "map"
+
+ can_unwrench = 1
+
+ name = "gas filter"
+
+ var/target_pressure = ONE_ATMOSPHERE
+
+ var/filter_type = 0
+/*
+Filter types:
+-1: Nothing
+ 0: Toxins: Toxins, Oxygen Agent B
+ 1: Oxygen: Oxygen ONLY
+ 2: Nitrogen: Nitrogen ONLY
+ 3: Carbon Dioxide: Carbon Dioxide ONLY
+ 4: Sleeping Agent (N2O)
+*/
+
+ var/frequency = 0
+ var/datum/radio_frequency/radio_connection
+
+/obj/machinery/atmospherics/trinary/filter/CtrlClick(mob/living/user)
+ if(!istype(user) || user.incapacitated())
+ to_chat(user, "You can't do that right now!")
+ return
+ if(!in_range(src, user) && !issilicon(usr))
+ return
+ if(!ishuman(usr) && !issilicon(usr))
+ return
+ toggle()
+ return ..()
+
+/obj/machinery/atmospherics/trinary/filter/AICtrlClick()
+ toggle()
+ return ..()
+
+/obj/machinery/atmospherics/trinary/filter/AltClick(mob/living/user)
+ if(!istype(user) || user.incapacitated())
+ to_chat(user, "You can't do that right now!")
+ return
+ if(!in_range(src, user) && !issilicon(usr))
+ return
+ if(!ishuman(usr) && !issilicon(usr))
+ return
+ set_max()
+ return
+
+/obj/machinery/atmospherics/trinary/filter/AIAltClick()
+ set_max()
+ return ..()
+
+/obj/machinery/atmospherics/trinary/filter/proc/toggle()
+ if(powered())
+ on = !on
+ update_icon()
+
+/obj/machinery/atmospherics/trinary/filter/proc/set_max()
+ if(powered())
+ target_pressure = MAX_OUTPUT_PRESSURE
+ update_icon()
+
+/obj/machinery/atmospherics/trinary/filter/Destroy()
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
+ radio_connection = null
+ return ..()
+
+/obj/machinery/atmospherics/trinary/filter/flipped
+ icon_state = "mmap"
+ flipped = 1
+
+/obj/machinery/atmospherics/trinary/filter/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ if(frequency)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
+
+/obj/machinery/atmospherics/trinary/filter/update_icon()
+ ..()
+
+ if(flipped)
+ icon_state = "m"
+ else
+ icon_state = ""
+
+ if(!powered())
+ icon_state += "off"
+ else if(node2 && node3 && node1)
+ icon_state += on ? "on" : "off"
+ else
+ icon_state += "off"
+ on = 0
+
+/obj/machinery/atmospherics/trinary/filter/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+
+ add_underlay(T, node1, turn(dir, -180))
+
+ if(flipped)
+ add_underlay(T, node2, turn(dir, 90))
+ else
+ add_underlay(T, node2, turn(dir, -90))
+
+ add_underlay(T, node3, dir)
+
+/obj/machinery/atmospherics/trinary/filter/power_change()
+ var/old_stat = stat
+ ..()
+ if(old_stat != stat)
+ update_icon()
+
+/obj/machinery/atmospherics/trinary/filter/process_atmos()
+ ..()
+ if(!on)
+ return 0
+
+ var/output_starting_pressure = air3.return_pressure()
+
+ if(output_starting_pressure >= target_pressure || air2.return_pressure() >= target_pressure )
+ //No need to mix if target is already full!
+ return 1
+
+ //Calculate necessary moles to transfer using PV=nRT
+
+ var/pressure_delta = target_pressure - output_starting_pressure
+ var/transfer_moles
+
+ if(air1.temperature > 0)
+ transfer_moles = pressure_delta*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
+
+ //Actually transfer the gas
+
+ if(transfer_moles > 0)
+ var/datum/gas_mixture/removed = air1.remove(transfer_moles)
+
+ if(!removed)
+ return
+ var/datum/gas_mixture/filtered_out = new
+ filtered_out.temperature = removed.temperature
+
+ switch(filter_type)
+ if(0) //removing hydrocarbons
+ filtered_out.toxins = removed.toxins
+ removed.toxins = 0
+
+ if(removed.trace_gases.len>0)
+ for(var/datum/gas/trace_gas in removed.trace_gases)
+ if(istype(trace_gas, /datum/gas/oxygen_agent_b))
+ removed.trace_gases -= trace_gas
+ filtered_out.trace_gases += trace_gas
+
+ if(1) //removing O2
+ filtered_out.oxygen = removed.oxygen
+ removed.oxygen = 0
+
+ if(2) //removing N2
+ filtered_out.nitrogen = removed.nitrogen
+ removed.nitrogen = 0
+
+ if(3) //removing CO2
+ filtered_out.carbon_dioxide = removed.carbon_dioxide
+ removed.carbon_dioxide = 0
+
+ if(4)//removing N2O
+ if(removed.trace_gases.len>0)
+ for(var/datum/gas/trace_gas in removed.trace_gases)
+ if(istype(trace_gas, /datum/gas/sleeping_agent))
+ removed.trace_gases -= trace_gas
+ filtered_out.trace_gases += trace_gas
+
+ else
+ filtered_out = null
+
+
+ air2.merge(filtered_out)
+ air3.merge(removed)
+
+ parent2.update = 1
+
+ parent3.update = 1
+
+ parent1.update = 1
+
+ return 1
+
+/obj/machinery/atmospherics/trinary/filter/atmos_init()
+ set_frequency(frequency)
+ ..()
+
+/obj/machinery/atmospherics/trinary/filter/attack_ghost(mob/user)
+ ui_interact(user)
+
+/obj/machinery/atmospherics/trinary/filter/attack_hand(mob/user)
+ if(..())
+ return
+
+ if(!allowed(user))
+ to_chat(user, "Access denied.")
+ return
+
+ add_fingerprint(user)
+ ui_interact(user)
+
+/obj/machinery/atmospherics/trinary/filter/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
+ user.set_machine(src)
+ ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "atmos_filter.tmpl", name, 475, 155, state = state)
+ ui.open()
+
+/obj/machinery/atmospherics/trinary/filter/ui_data(mob/user)
+ var/list/data = list()
+ data["on"] = on
+ data["pressure"] = round(target_pressure)
+ data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
+ data["filter_type"] = filter_type
+ return data
+
+/obj/machinery/atmospherics/trinary/filter/Topic(href, href_list) // -- TLE
+ if(..())
+ return 1
+
+ if(href_list["power"])
+ on = !on
+ investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
+ . = TRUE
+ if(href_list["pressure"])
+ var/pressure = href_list["pressure"]
+ if(pressure == "max")
+ pressure = MAX_OUTPUT_PRESSURE
+ . = TRUE
+ else if(pressure == "input")
+ pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
+ if(!isnull(pressure) && !..())
+ . = TRUE
+ else if(text2num(pressure) != null)
+ pressure = text2num(pressure)
+ . = TRUE
+ if(.)
+ target_pressure = Clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
+ investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
+ if(href_list["filter"])
+ filter_type = text2num(href_list["filter"])
+ investigate_log("was set to filter [filter_type] by [key_name(usr)]", "atmos")
+ . = TRUE
+
+ update_icon()
+ SSnanoui.update_uis(src)
+
+/obj/machinery/atmospherics/trinary/filter/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/pen))
+ var/t = copytext(stripped_input(user, "Enter the name for the filter.", "Rename", name), 1, MAX_NAME_LEN)
+ if(!t)
+ return
+ if(!in_range(src, usr) && loc != usr)
+ return
+ name = t
+ return
+ else
+ return ..()
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index a923afb563f..24b8bb27735 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -1,997 +1,997 @@
-// A datum for dealing with threshold limit values
-// used in /obj/machinery/alarm
-/datum/tlv
- var/min2
- var/min1
- var/max1
- var/max2
-
-/datum/tlv/New(_min2 as num, _min1 as num, _max1 as num, _max2 as num)
- min2 = _min2
- min1 = _min1
- max1 = _max1
- max2 = _max2
-
-/datum/tlv/proc/get_danger_level(curval as num)
- if(max2 >=0 && curval>max2)
- return ATMOS_ALARM_DANGER
- if(min2 >=0 && curval=0 && curval>max1)
- return ATMOS_ALARM_WARNING
- if(min1 >=0 && curval=0 && curval>max2)
+ return ATMOS_ALARM_DANGER
+ if(min2 >=0 && curval=0 && curval>max1)
+ return ATMOS_ALARM_WARNING
+ if(min1 >=0 && curval target_temperature + 2 || regulating_temperature)
- //If it goes too far, we should adjust ourselves back before stopping.
- if(!cur_tlv.get_danger_level(target_temperature))
- if(!regulating_temperature)
- regulating_temperature = 1
- visible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
- "You hear a click and a faint electronic hum.")
-
- if(target_temperature > MAX_TEMPERATURE)
- target_temperature = MAX_TEMPERATURE
-
- if(target_temperature < MIN_TEMPERATURE)
- target_temperature = MIN_TEMPERATURE
-
- var/datum/gas_mixture/gas = location.remove_air(0.25*environment.total_moles())
- var/heat_capacity = gas.heat_capacity()
- var/energy_used = max( abs( heat_capacity*(gas.temperature - target_temperature) ), MAX_ENERGY_CHANGE)
-
- //Use power. Assuming that each power unit represents 1000 watts....
- use_power(energy_used/1000, ENVIRON)
-
- //We need to cool ourselves.
- if(heat_capacity)
- if(environment.temperature > target_temperature)
- gas.temperature -= energy_used/heat_capacity
- else
- gas.temperature += energy_used/heat_capacity
-
- environment.merge(gas)
-
- if(abs(environment.temperature - target_temperature) <= 0.5)
- regulating_temperature = 0
- visible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
- "You hear a click as a faint electronic humming stops.")
-
-/obj/machinery/alarm/update_icon()
- if(wiresexposed)
- icon_state = "alarmx"
- return
- if((stat & (NOPOWER|BROKEN)) || shorted)
- icon_state = "alarmp"
- return
-
- switch(max(danger_level, alarm_area.atmosalm-1))
- if(ATMOS_ALARM_NONE)
- icon_state = "alarm0"
- if(ATMOS_ALARM_WARNING)
- icon_state = "alarm2" //yes, alarm2 is yellow alarm
- if(ATMOS_ALARM_DANGER)
- icon_state = "alarm1"
-
-/obj/machinery/alarm/proc/register_env_machine(var/m_id, var/device_type)
- var/new_name
- if(device_type=="AVP")
- new_name = "[alarm_area.name] Vent Pump #[alarm_area.air_vent_names.len+1]"
- alarm_area.air_vent_names[m_id] = new_name
- else if(device_type=="AScr")
- new_name = "[alarm_area.name] Air Scrubber #[alarm_area.air_scrub_names.len+1]"
- alarm_area.air_scrub_names[m_id] = new_name
- else
- return
- spawn (10)
- send_signal(m_id, list("init" = new_name) )
-
-/obj/machinery/alarm/proc/refresh_all()
- for(var/id_tag in alarm_area.air_vent_names)
- var/list/I = alarm_area.air_vent_info[id_tag]
- if(I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time)
- continue
- send_signal(id_tag, list("status") )
- for(var/id_tag in alarm_area.air_scrub_names)
- var/list/I = alarm_area.air_scrub_info[id_tag]
- if(I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time)
- continue
- send_signal(id_tag, list("status") )
-
-/obj/machinery/alarm/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- radio_connection = SSradio.add_object(src, frequency, RADIO_TO_AIRALARM)
-
-/obj/machinery/alarm/proc/send_signal(var/target, var/list/command)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise
- if(!radio_connection)
- return 0
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = command
- signal.data["tag"] = target
- signal.data["sigtype"] = "command"
-
- radio_connection.post_signal(src, signal, RADIO_FROM_AIRALARM)
-// to_chat(world, text("Signal [] Broadcasted to []", command, target))
-
- return 1
-
-/obj/machinery/alarm/proc/apply_mode()
- switch(mode)
- if(AALARM_MODE_SCRUBBING)
- for(var/device_id in alarm_area.air_scrub_names)
- send_signal(device_id, list(
- "power"= 1,
- "o2_scrub" = (preset==AALARM_PRESET_VOX),
- "n2_scrub" = 0,
- "co2_scrub"= 1,
- "scrubbing"= 1,
- "widenet"= 0,
- ))
- for(var/device_id in alarm_area.air_vent_names)
- send_signal(device_id, list(
- "power"= 1,
- "checks"= 1,
- "set_external_pressure"= ONE_ATMOSPHERE
- ))
- if(AALARM_MODE_CONTAMINATED)
- for(var/device_id in alarm_area.air_scrub_names)
- send_signal(device_id, list(
- "power"= 1,
- "co2_scrub"= 1,
- "tox_scrub"= 1,
- "n2o_scrub"= 1,
- "scrubbing"= 1,
- "widenet"= 1,
- ))
- for(var/device_id in alarm_area.air_vent_names)
- send_signal(device_id, list(
- "power"= 1,
- "checks"= 1,
- "set_external_pressure"= ONE_ATMOSPHERE
- ))
- if(AALARM_MODE_VENTING)
- for(var/device_id in alarm_area.air_scrub_names)
- send_signal(device_id, list(
- "power"= 1,
- "widenet"= 0,
- "scrubbing"= 0
- ))
- for(var/device_id in alarm_area.air_vent_names)
- send_signal(device_id, list(
- "power"= 1,
- "checks"= 1,
- "set_external_pressure" = ONE_ATMOSPHERE*2
- ))
- if(AALARM_MODE_REFILL)
- for(var/device_id in alarm_area.air_scrub_names)
- send_signal(device_id, list(
- "power"= 1,
- "co2_scrub"= 1,
- "tox_scrub"= 0,
- "n2o_scrub"= 0,
- "scrubbing"= 1,
- "widenet"= 0,
- ))
- for(var/device_id in alarm_area.air_vent_names)
- send_signal(device_id, list(
- "power"= 1,
- "checks"= 1,
- "set_external_pressure" = ONE_ATMOSPHERE*3
- ))
- if(
- AALARM_MODE_PANIC,
- AALARM_MODE_REPLACEMENT
- )
- for(var/device_id in alarm_area.air_scrub_names)
- send_signal(device_id, list(
- "power"= 1,
- "widenet"= 1,
- "scrubbing"= 0
- ))
- for(var/device_id in alarm_area.air_vent_names)
- send_signal(device_id, list(
- "power"= 0
- ))
- if(
- AALARM_MODE_SIPHON
- )
- for(var/device_id in alarm_area.air_scrub_names)
- send_signal(device_id, list(
- "power"= 1,
- "widenet"= 0,
- "scrubbing"= 0
- ))
- for(var/device_id in alarm_area.air_vent_names)
- send_signal(device_id, list(
- "power"= 0
- ))
-
- if(AALARM_MODE_OFF)
- for(var/device_id in alarm_area.air_scrub_names)
- send_signal(device_id, list(
- "power"= 0
- ))
- for(var/device_id in alarm_area.air_vent_names)
- send_signal(device_id, list(
- "power"= 0
- ))
- if(AALARM_MODE_FLOOD)
- for(var/device_id in alarm_area.air_scrub_names)
- send_signal(device_id, list(
- "power"=0
- ))
- for(var/device_id in alarm_area.air_vent_names)
- send_signal(device_id, list(
- "power"= 1,
- "checks"= 0,
- ))
-
-/obj/machinery/alarm/proc/apply_danger_level(var/new_danger_level)
- if(report_danger_level && alarm_area.atmosalert(new_danger_level, src))
- post_alert(new_danger_level)
-
- update_icon()
-
-/obj/machinery/alarm/proc/post_alert(alert_level)
- var/datum/radio_frequency/frequency = SSradio.return_frequency(alarm_frequency)
- if(!frequency)
- return
-
- var/datum/signal/alert_signal = new
- alert_signal.source = src
- alert_signal.transmission_method = 1
- alert_signal.data["zone"] = alarm_area.name
- alert_signal.data["type"] = "Atmospheric"
-
- if(alert_level==2)
- alert_signal.data["alert"] = "severe"
- else if(alert_level==1)
- alert_signal.data["alert"] = "minor"
- else if(alert_level==0)
- alert_signal.data["alert"] = "clear"
-
- frequency.post_signal(src, alert_signal)
-
-///////////////
-//END HACKING//
-///////////////
-
-/obj/machinery/alarm/attack_ai(mob/user)
- src.add_hiddenprint(user)
- return ui_interact(user)
-
-/obj/machinery/alarm/attack_ghost(user as mob)
- return interact(user)
-
-/obj/machinery/alarm/attack_hand(mob/user)
- . = ..()
- if(.)
- return
- return interact(user)
-
-/obj/machinery/alarm/interact(mob/user)
- if(buildstage != 2)
- return
-
- if(wiresexposed)
- wires.Interact(user)
-
- if(!shorted)
- ui_interact(user)
-
-/obj/machinery/alarm/proc/ui_air_status()
- var/turf/location = get_turf(src)
- if(!istype(location))
- return
-
- var/datum/gas_mixture/environment = location.return_air()
- var/total = environment.oxygen + environment.nitrogen + environment.carbon_dioxide + environment.toxins
- if(total==0)
- return null
-
- var/datum/tlv/cur_tlv
- var/GET_PP = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume
-
- cur_tlv = TLV["pressure"]
- var/environment_pressure = environment.return_pressure()
- var/pressure_dangerlevel = cur_tlv.get_danger_level(environment_pressure)
-
- cur_tlv = TLV["oxygen"]
- var/oxygen_dangerlevel = cur_tlv.get_danger_level(environment.oxygen*GET_PP)
- var/oxygen_percent = round(environment.oxygen / total * 100, 2)
-
- cur_tlv = TLV["nitrogen"]
- var/nitrogen_dangerlevel = cur_tlv.get_danger_level(environment.nitrogen*GET_PP)
- var/nitrogen_percent = round(environment.nitrogen / total * 100, 2)
-
- cur_tlv = TLV["carbon dioxide"]
- var/co2_dangerlevel = cur_tlv.get_danger_level(environment.carbon_dioxide*GET_PP)
- var/co2_percent = round(environment.carbon_dioxide / total * 100, 2)
-
- cur_tlv = TLV["plasma"]
- var/plasma_dangerlevel = cur_tlv.get_danger_level(environment.toxins*GET_PP)
- var/plasma_percent = round(environment.toxins / total * 100, 2)
-
- cur_tlv = TLV["other"]
- var/other_moles = 0.0
- for(var/datum/gas/G in environment.trace_gases)
- other_moles+=G.moles
- var/other_dangerlevel = cur_tlv.get_danger_level(other_moles*GET_PP)
-
- cur_tlv = TLV["temperature"]
- var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature)
-
- var/data[0]
- data["pressure"] = environment_pressure
- data["temperature"] = environment.temperature
- data["temperature_c"] = round(environment.temperature - T0C, 0.1)
-
- var/percentages[0]
- percentages["oxygen"] = oxygen_percent
- percentages["nitrogen"] = nitrogen_percent
- percentages["co2"] = co2_percent
- percentages["plasma"] = plasma_percent
- percentages["other"] = other_moles
- data["contents"] = percentages
-
- var/danger[0]
- danger["pressure"] = pressure_dangerlevel
- danger["temperature"] = temperature_dangerlevel
- danger["oxygen"] = oxygen_dangerlevel
- danger["nitrogen"] = nitrogen_dangerlevel
- danger["co2"] = co2_dangerlevel
- danger["plasma"] = plasma_dangerlevel
- danger["other"] = other_dangerlevel
- danger["overall"] = max(pressure_dangerlevel,oxygen_dangerlevel,nitrogen_dangerlevel,co2_dangerlevel,plasma_dangerlevel,other_dangerlevel,temperature_dangerlevel)
- data["danger"] = danger
- return data
-
-/obj/machinery/alarm/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state)
- var/data[0]
-
- var/list/href_list = state.href_list(user)
- if(href_list)
- data["remote_connection"] = href_list["remote_connection"]
- data["remote_access"] = href_list["remote_access"]
-
- data["name"] = sanitize(name)
- data["air"] = ui_air_status()
- data["alarmActivated"] = alarmActivated || danger_level == ATMOS_ALARM_DANGER
- data["thresholds"] = generate_thresholds_menu()
-
- // Locked when:
- // Not sent from atmos console AND
- // Not silicon AND locked.
- data["locked"] = !is_authenticated(user, href_list)
- data["rcon"] = rcon_setting
- data["target_temp"] = target_temperature - T0C
- data["atmos_alarm"] = alarm_area.atmosalm
- data["emagged"] = emagged
- data["modes"] = list(
- AALARM_MODE_SCRUBBING = list("name"="Filtering", "desc"="Scrubs out contaminants"),\
- AALARM_MODE_VENTING = list("name"="Draught", "desc"="Siphons out air while replacing"),\
- AALARM_MODE_PANIC = list("name"="Panic Siphon","desc"="Siphons air out of the room quickly"),\
- AALARM_MODE_REPLACEMENT = list("name"="Cycle", "desc"="Siphons air before replacing"),\
- AALARM_MODE_SIPHON = list("name"="Siphon", "desc"="Siphons air out of the room"),\
- AALARM_MODE_CONTAMINATED= list("name"="Contaminated","desc"="Scrubs out all contaminants quickly"),\
- AALARM_MODE_REFILL = list("name"="Refill", "desc"="Triples vent output"),\
- AALARM_MODE_OFF = list("name"="Off", "desc"="Shuts off vents and scrubbers"),\
- AALARM_MODE_FLOOD = list("name"="Flood", "desc"="Shuts off scrubbers and opens vents", "emagonly" = 1)
- )
- data["mode"] = mode
- data["presets"] = list(
- AALARM_PRESET_HUMAN = list("name"="Human", "desc"="Checks for oxygen and nitrogen"),\
- AALARM_PRESET_VOX = list("name"="Vox", "desc"="Checks for nitrogen only"),\
- AALARM_PRESET_COLDROOM = list("name"="Coldroom", "desc"="For freezers"),\
- AALARM_PRESET_SERVER = list("name"="Server Room", "desc"="For server rooms")
- )
- data["preset"] = preset
- data["screen"] = screen
-
- var/list/vents=list()
- if(alarm_area.air_vent_names.len)
- for(var/id_tag in alarm_area.air_vent_names)
- var/vent_info[0]
- var/long_name = alarm_area.air_vent_names[id_tag]
- var/list/vent_data = alarm_area.air_vent_info[id_tag]
- if(!vent_data)
- continue
- vent_info["id_tag"]=id_tag
- vent_info["name"]=sanitize(long_name)
- vent_info += vent_data
- vents+=list(vent_info)
- data["vents"]=vents
-
- var/list/scrubbers=list()
- if(alarm_area.air_scrub_names.len)
- for(var/id_tag in alarm_area.air_scrub_names)
- var/long_name = alarm_area.air_scrub_names[id_tag]
- var/list/scrubber_data = alarm_area.air_scrub_info[id_tag]
- if(!scrubber_data)
- continue
- scrubber_data["id_tag"]=id_tag
- scrubber_data["name"]=sanitize(long_name)
- scrubbers+=list(scrubber_data)
- data["scrubbers"]=scrubbers
- return data
-
-/obj/machinery/alarm/proc/get_nano_data_console(mob/user)
- var/data[0]
- data["name"] = sanitize(name)
- data["ref"] = "\ref[src]"
- data["danger"] = max(danger_level, alarm_area.atmosalm)
- var/area/Area = get_area(src)
- data["area"] = sanitize(Area.name)
- var/turf/pos = get_turf(src)
- data["x"] = pos.x
- data["y"] = pos.y
- data["z"] = pos.z
- return data
-
-/obj/machinery/alarm/proc/generate_thresholds_menu()
- var/datum/tlv/selected
- var/list/thresholds = list()
-
- var/list/gas_names = list(
- "oxygen" = "O2",
- "nitrogen" = "N2",
- "carbon dioxide" = "CO2",
- "plasma" = "Toxin",
- "other" = "Other")
- for(var/g in gas_names)
- thresholds += list(list("name" = gas_names[g], "settings" = list()))
- selected = TLV[g]
- thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = "min2", "selected" = selected.min2))
- thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = "min1", "selected" = selected.min1))
- thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = "max1", "selected" = selected.max1))
- thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = "max2", "selected" = selected.max2))
-
- selected = TLV["pressure"]
- thresholds += list(list("name" = "Pressure", "settings" = list()))
- thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min2", "selected" = selected.min2))
- thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min1", "selected" = selected.min1))
- thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max1", "selected" = selected.max1))
- thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max2", "selected" = selected.max2))
-
- selected = TLV["temperature"]
- thresholds += list(list("name" = "Temperature", "settings" = list()))
- thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min2", "selected" = selected.min2))
- thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min1", "selected" = selected.min1))
- thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max1", "selected" = selected.max1))
- thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max2", "selected" = selected.max2))
-
- return thresholds
-
-/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
- if(!ui)
- ui = new(user, src, ui_key, "air_alarm.tmpl", name, 570, 410, state = state)
- ui.open()
- ui.set_auto_update(1)
-
-/obj/machinery/alarm/proc/is_authenticated(var/mob/user, href_list)
- if(user.can_admin_interact())
- return 1
- else if(isAI(user) || isrobot(user) || emagged || is_auth_rcon(href_list))
- return 1
- else
- return !locked
-
-/obj/machinery/alarm/proc/is_auth_rcon(href_list)
- if(href_list && href_list["remote_connection"] && href_list["remote_access"])
- return 1
- else
- return 0
-
-/obj/machinery/alarm/CanUseTopic(var/mob/user, var/datum/topic_state/state, var/href_list = list())
- if(buildstage != 2)
- return STATUS_CLOSE
-
- if(aidisabled && (isAI(user) || isrobot(user)))
- to_chat(user, "AI control for \the [src] interface has been disabled.")
- return STATUS_CLOSE
-
- . = shorted ? STATUS_DISABLED : STATUS_INTERACTIVE
-
- if(. == STATUS_INTERACTIVE)
- var/extra_href = state.href_list(usr)
- // Prevent remote users from altering RCON settings or activating atmos alarms unless they already have access
- if((href_list["atmos_alarm"] || href_list["rcon"]) && extra_href["remote_connection"] && !extra_href["remote_access"])
- . = STATUS_UPDATE
- return min(..(), .)
-
-/obj/machinery/alarm/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state)
- if(..(href, href_list, nowindow, state))
- return 1
-
- var/state_href = state.href_list(usr)
-
- if(href_list["rcon"])
- var/attempted_rcon_setting = text2num(href_list["rcon"])
- switch(attempted_rcon_setting)
- if(RCON_NO)
- rcon_setting = RCON_NO
- if(RCON_AUTO)
- rcon_setting = RCON_AUTO
- if(RCON_YES)
- rcon_setting = RCON_YES
- return 1
-
- add_fingerprint(usr)
-
- if(href_list["command"])
- if(!is_authenticated(usr, state_href))
- return
-
- var/device_id = href_list["id_tag"]
- switch(href_list["command"])
- if( "power",
- "adjust_external_pressure",
- "set_external_pressure",
- "checks",
- "co2_scrub",
- "tox_scrub",
- "n2o_scrub",
- "n2_scrub",
- "o2_scrub",
- "widenet",
- "scrubbing",
- "direction")
- var/val
- if(href_list["val"])
- val=text2num(href_list["val"])
- else
- var/newval = input("Enter new value") as num|null
- if(isnull(newval))
- return
- if(href_list["command"]=="set_external_pressure")
- if(newval>1000+ONE_ATMOSPHERE)
- newval = 1000+ONE_ATMOSPHERE
- if(newval<0)
- newval = 0
- val = newval
-
- send_signal(device_id, list(href_list["command"] = val ) )
- waiting_on_device=device_id
-
- if("set_threshold")
- var/env = href_list["env"]
- var/varname = href_list["var"]
- var/datum/tlv/tlv = TLV[env]
- var/newval = input("Enter [varname] for [env]", "Alarm triggers", tlv.vars[varname]) as num|null
-
- if(isnull(newval) || ..(href, href_list, nowindow, state))
- return
- if(newval<0)
- tlv.vars[varname] = -1.0
- else if(env=="temperature" && newval>5000)
- tlv.vars[varname] = 5000
- else if(env=="pressure" && newval>50*ONE_ATMOSPHERE)
- tlv.vars[varname] = 50*ONE_ATMOSPHERE
- else if(env!="temperature" && env!="pressure" && newval>200)
- tlv.vars[varname] = 200
- else
- newval = round(newval,0.01)
- tlv.vars[varname] = newval
-
- if(href_list["screen"])
- if(!is_authenticated(usr, state_href))
- return
-
- screen = text2num(href_list["screen"])
- return 1
-
- if(href_list["atmos_alarm"])
- if(alarm_area.atmosalert(ATMOS_ALARM_DANGER, src))
- apply_danger_level(ATMOS_ALARM_DANGER)
- alarmActivated = 1
- update_icon()
- return 1
-
- if(href_list["atmos_reset"])
- if(alarm_area.atmosalert(ATMOS_ALARM_NONE, src, TRUE))
- apply_danger_level(ATMOS_ALARM_NONE)
- alarmActivated = 0
- update_icon()
- return 1
-
- if(href_list["mode"])
- if(!is_authenticated(usr, state_href))
- return
-
- mode = text2num(href_list["mode"])
- apply_mode()
- return 1
-
- if(href_list["preset"])
- if(!is_authenticated(usr, state_href))
- return
-
- preset = text2num(href_list["preset"])
- apply_preset()
- return 1
-
- if(href_list["temperature"])
- var/datum/tlv/selected = TLV["temperature"]
- var/max_temperature = selected.max1 >= 0 ? min(selected.max1, MAX_TEMPERATURE) : max(selected.max1, MAX_TEMPERATURE)
- var/min_temperature = max(selected.min1, MIN_TEMPERATURE)
- var/max_temperature_c = max_temperature - T0C
- var/min_temperature_c = min_temperature - T0C
- var/input_temperature = input("What temperature would you like the system to maintain? (Capped between [min_temperature_c]C and [max_temperature_c]C)", "Thermostat Controls") as num|null
- if(isnull(input_temperature) || ..(href, href_list, nowindow, state))
- return
- input_temperature = input_temperature + T0C
- if(input_temperature > max_temperature || input_temperature < min_temperature)
- to_chat(usr, "Temperature must be between [min_temperature_c]C and [max_temperature_c]C")
- else
- target_temperature = input_temperature
- return 1
-
-/obj/machinery/alarm/emag_act(mob/user)
- if(!emagged)
- src.emagged = 1
- if(user)
- user.visible_message("Sparks fly out of the [src]!", "You emag the [src], disabling its safeties.")
- playsound(src.loc, 'sound/effects/sparks4.ogg', 50, 1)
- return
-
-/obj/machinery/alarm/attackby(obj/item/I, mob/user, params)
- add_fingerprint(user)
-
- switch(buildstage)
- if(2)
- if(istype(I, /obj/item/card/id) || istype(I, /obj/item/pda))// trying to unlock the interface with an ID card
- if(stat & (NOPOWER|BROKEN))
- to_chat(user, "It does nothing")
- return
- else
- if(allowed(usr) && !wires.IsIndexCut(AALARM_WIRE_IDSCAN))
- locked = !locked
- to_chat(user, "You [ locked ? "lock" : "unlock"] the Air Alarm interface.")
- updateUsrDialog()
- else
- to_chat(user, "Access denied.")
- return
-
- if(1)
- if(iscoil(I))
- var/obj/item/stack/cable_coil/coil = I
- if(coil.amount < 5)
- to_chat(user, "You need more cable for this!")
- return
-
- to_chat(user, "You wire \the [src]!")
- playsound(get_turf(src), coil.usesound, 50, 1)
- coil.amount -= 5
- if(!coil.amount)
- qdel(coil)
-
- buildstage = 2
- update_icon()
- first_run()
- return
- if(0)
- if(istype(I, /obj/item/airalarm_electronics))
- to_chat(user, "You insert the circuit!")
- playsound(get_turf(src), I.usesound, 50, 1)
- qdel(I)
- buildstage = 1
- update_icon()
- return
+ req_one_access = list()
+
+/obj/machinery/alarm/monitor/server
+ preset = AALARM_PRESET_SERVER
+
+/obj/machinery/alarm/server
+ preset = AALARM_PRESET_SERVER
+
+/obj/machinery/alarm/vox
+ preset = AALARM_PRESET_VOX
+
+/obj/machinery/alarm/kitchen_cold_room
+ preset = AALARM_PRESET_COLDROOM
+
+/obj/machinery/alarm/proc/apply_preset(var/no_cycle_after=0)
+ // Propogate settings.
+ for(var/obj/machinery/alarm/AA in alarm_area)
+ if(!(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted && AA.preset != src.preset)
+ AA.preset=preset
+ apply_preset(1) // Only this air alarm should send a cycle.
+
+ TLV = list (
+ "oxygen" = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
+ "nitrogen" = new/datum/tlv(-1.0, -1.0, -1.0, -1.0), // Partial pressure, kpa
+ "carbon dioxide" = new/datum/tlv(-1.0, -1.0, 5, 10), // Partial pressure, kpa
+ "plasma" = new/datum/tlv(-1.0, -1.0, 0.2, 0.5), // Partial pressure, kpa
+ "other" = new/datum/tlv(-1.0, -1.0, 0.5, 1.0), // Partial pressure, kpa
+ "pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.10,ONE_ATMOSPHERE*1.20), /* kpa */
+ "temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66), // K
+ )
+ switch(preset)
+ if(AALARM_PRESET_VOX)
+ TLV = list(
+ "oxygen" = new/datum/tlv(-1.0, -1.0, 1, 2), // Partial pressure, kpa
+ "nitrogen" = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
+ "carbon dioxide" = new/datum/tlv(-1.0, -1.0, 5, 10), // Partial pressure, kpa
+ "plasma" = new/datum/tlv(-1.0, -1.0, 0.2, 0.5), // Partial pressure, kpa
+ "other" = new/datum/tlv(-1.0, -1.0, 0.5, 1.0), // Partial pressure, kpa
+ "pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.10,ONE_ATMOSPHERE*1.20), /* kpa */
+ "temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66), // K
+ )
+ if(AALARM_PRESET_COLDROOM)
+ TLV = list(
+ "oxygen" = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
+ "nitrogen" = new/datum/tlv(-1.0, -1.0, -1.0, -1.0), // Partial pressure, kpa
+ "carbon dioxide" = new/datum/tlv(-1.0, -1.0, 5, 10), // Partial pressure, kpa
+ "plasma" = new/datum/tlv(-1.0, -1.0, 0.2, 0.5), // Partial pressure, kpa
+ "other" = new/datum/tlv(-1.0, -1.0, 0.5, 1.0), // Partial pressure, kpa
+ "pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.50,ONE_ATMOSPHERE*1.60), /* kpa */
+ "temperature" = new/datum/tlv(T0C-50, T0C-20, T0C, T20C), // K
+ )
+ if(AALARM_PRESET_SERVER)
+ TLV = list(
+ "oxygen" = new/datum/tlv(-1.0, -1.0, -1.0, -1.0), // Partial pressure, kpa
+ "nitrogen" = new/datum/tlv(-1.0, -1.0, -1.0, -1.0), // Partial pressure, kpa
+ "carbon dioxide" = new/datum/tlv(-1.0, -1.0, -1.0, -1.0), // Partial pressure, kpa
+ "plasma" = new/datum/tlv(-1.0, -1.0, -1.0, -1.0), // Partial pressure, kpa
+ "other" = new/datum/tlv(-1.0, -1.0, -1.0, -1.0), // Partial pressure, kpa
+ "pressure" = new/datum/tlv(-1.0, -1.0, -1.0, -1.0), /* kpa */
+ "temperature" = new/datum/tlv(0, 0, T20C + 5, T20C + 15), // K
+ )
+
+ if(!no_cycle_after)
+ mode = AALARM_MODE_REPLACEMENT
+ apply_mode()
+
+/obj/machinery/alarm/New(var/loc, var/dir, var/building = 0)
+ ..()
+ GLOB.air_alarms += src
+ GLOB.air_alarms = sortAtom(GLOB.air_alarms)
+
+ wires = new(src)
+
+ if(building)
+ if(loc)
+ src.loc = loc
+
+ if(dir)
+ src.dir = dir
+
+ buildstage = 0
+ wiresexposed = 1
+ pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
+ pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0
+ update_icon()
+ return
+
+ first_run()
+
+/obj/machinery/alarm/Destroy()
+ GLOB.air_alarms -= src
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
+ radio_connection = null
+ air_alarm_repository.update_cache(src)
+ QDEL_NULL(wires)
+ if(alarm_area && alarm_area.master_air_alarm == src)
+ alarm_area.master_air_alarm = null
+ elect_master(exclude_self = 1)
+ alarm_area = null
return ..()
-
+
+/obj/machinery/alarm/proc/first_run()
+ alarm_area = get_area(src)
+ area_uid = alarm_area.uid
+ if(name == "alarm")
+ name = "[alarm_area.name] Air Alarm"
+ apply_preset(1) // Don't cycle.
+ air_alarm_repository.update_cache(src)
+
+/obj/machinery/alarm/Initialize()
+ ..()
+ set_frequency(frequency)
+ if(!master_is_operating())
+ elect_master()
+
+/obj/machinery/alarm/proc/master_is_operating()
+ if(!alarm_area)
+ alarm_area = areaMaster
+ if(!alarm_area)
+ log_runtime(EXCEPTION("Air alarm /obj/machinery/alarm lacks alarm_area and areaMaster vars during proc/master_is_operating()"), src)
+ return FALSE
+ return alarm_area.master_air_alarm && !(alarm_area.master_air_alarm.stat & (NOPOWER|BROKEN))
+
+
+/obj/machinery/alarm/proc/elect_master(exclude_self = 0) //Why is this an alarm and not area proc?
+ for(var/obj/machinery/alarm/AA in alarm_area)
+ if(exclude_self && AA == src)
+ continue
+ if(!(AA.stat & (NOPOWER|BROKEN)))
+ alarm_area.master_air_alarm = AA
+ return 1
+ return 0
+
+/obj/machinery/alarm/process()
+ if((stat & (NOPOWER|BROKEN)) || shorted || buildstage != 2)
+ return
+
+ var/turf/simulated/location = loc
+ if(!istype(location))
+ return 0
+
+ var/datum/gas_mixture/environment = location.return_air()
+ var/datum/tlv/cur_tlv
+
+ handle_heating_cooling(environment, cur_tlv, location)
+
+ var/GET_PP = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume
+
+ cur_tlv = TLV["pressure"]
+ var/environment_pressure = environment.return_pressure()
+ var/pressure_dangerlevel = cur_tlv.get_danger_level(environment_pressure)
+
+ cur_tlv = TLV["oxygen"]
+ var/oxygen_dangerlevel = cur_tlv.get_danger_level(environment.oxygen*GET_PP)
+
+ cur_tlv = TLV["nitrogen"]
+ var/nitrogen_dangerlevel = cur_tlv.get_danger_level(environment.nitrogen*GET_PP)
+
+ cur_tlv = TLV["carbon dioxide"]
+ var/co2_dangerlevel = cur_tlv.get_danger_level(environment.carbon_dioxide*GET_PP)
+
+ cur_tlv = TLV["plasma"]
+ var/plasma_dangerlevel = cur_tlv.get_danger_level(environment.toxins*GET_PP)
+
+ cur_tlv = TLV["other"]
+ var/other_moles = 0.0
+ for(var/datum/gas/G in environment.trace_gases)
+ other_moles+=G.moles
+ var/other_dangerlevel = cur_tlv.get_danger_level(other_moles*GET_PP)
+
+ cur_tlv = TLV["temperature"]
+ var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature)
+
+ var/old_danger_level = danger_level
+ danger_level = max(
+ pressure_dangerlevel,
+ oxygen_dangerlevel,
+ nitrogen_dangerlevel,
+ co2_dangerlevel,
+ plasma_dangerlevel,
+ other_dangerlevel,
+ temperature_dangerlevel
+ )
+
+ if(old_danger_level!=danger_level)
+ apply_danger_level()
+
+ if(mode == AALARM_MODE_REPLACEMENT && environment_pressure < ONE_ATMOSPHERE * 0.05)
+ mode = AALARM_MODE_SCRUBBING
+ apply_mode()
+
+
+/obj/machinery/alarm/proc/handle_heating_cooling(var/datum/gas_mixture/environment, var/datum/tlv/cur_tlv, var/turf/simulated/location)
+ cur_tlv = TLV["temperature"]
+ //Handle temperature adjustment here.
+ if(environment.temperature < target_temperature - 2 || environment.temperature > target_temperature + 2 || regulating_temperature)
+ //If it goes too far, we should adjust ourselves back before stopping.
+ if(!cur_tlv.get_danger_level(target_temperature))
+ if(!regulating_temperature)
+ regulating_temperature = 1
+ visible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
+ "You hear a click and a faint electronic hum.")
+
+ if(target_temperature > MAX_TEMPERATURE)
+ target_temperature = MAX_TEMPERATURE
+
+ if(target_temperature < MIN_TEMPERATURE)
+ target_temperature = MIN_TEMPERATURE
+
+ var/datum/gas_mixture/gas = location.remove_air(0.25*environment.total_moles())
+ var/heat_capacity = gas.heat_capacity()
+ var/energy_used = max( abs( heat_capacity*(gas.temperature - target_temperature) ), MAX_ENERGY_CHANGE)
+
+ //Use power. Assuming that each power unit represents 1000 watts....
+ use_power(energy_used/1000, ENVIRON)
+
+ //We need to cool ourselves.
+ if(heat_capacity)
+ if(environment.temperature > target_temperature)
+ gas.temperature -= energy_used/heat_capacity
+ else
+ gas.temperature += energy_used/heat_capacity
+
+ environment.merge(gas)
+
+ if(abs(environment.temperature - target_temperature) <= 0.5)
+ regulating_temperature = 0
+ visible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
+ "You hear a click as a faint electronic humming stops.")
+
+/obj/machinery/alarm/update_icon()
+ if(wiresexposed)
+ icon_state = "alarmx"
+ return
+ if((stat & (NOPOWER|BROKEN)) || shorted)
+ icon_state = "alarmp"
+ return
+
+ switch(max(danger_level, alarm_area.atmosalm-1))
+ if(ATMOS_ALARM_NONE)
+ icon_state = "alarm0"
+ if(ATMOS_ALARM_WARNING)
+ icon_state = "alarm2" //yes, alarm2 is yellow alarm
+ if(ATMOS_ALARM_DANGER)
+ icon_state = "alarm1"
+
+/obj/machinery/alarm/proc/register_env_machine(var/m_id, var/device_type)
+ var/new_name
+ if(device_type=="AVP")
+ new_name = "[alarm_area.name] Vent Pump #[alarm_area.air_vent_names.len+1]"
+ alarm_area.air_vent_names[m_id] = new_name
+ else if(device_type=="AScr")
+ new_name = "[alarm_area.name] Air Scrubber #[alarm_area.air_scrub_names.len+1]"
+ alarm_area.air_scrub_names[m_id] = new_name
+ else
+ return
+ spawn (10)
+ send_signal(m_id, list("init" = new_name) )
+
+/obj/machinery/alarm/proc/refresh_all()
+ for(var/id_tag in alarm_area.air_vent_names)
+ var/list/I = alarm_area.air_vent_info[id_tag]
+ if(I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time)
+ continue
+ send_signal(id_tag, list("status") )
+ for(var/id_tag in alarm_area.air_scrub_names)
+ var/list/I = alarm_area.air_scrub_info[id_tag]
+ if(I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time)
+ continue
+ send_signal(id_tag, list("status") )
+
+/obj/machinery/alarm/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ radio_connection = SSradio.add_object(src, frequency, RADIO_TO_AIRALARM)
+
+/obj/machinery/alarm/proc/send_signal(var/target, var/list/command)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise
+ if(!radio_connection)
+ return 0
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ signal.data = command
+ signal.data["tag"] = target
+ signal.data["sigtype"] = "command"
+
+ radio_connection.post_signal(src, signal, RADIO_FROM_AIRALARM)
+// to_chat(world, text("Signal [] Broadcasted to []", command, target))
+
+ return 1
+
+/obj/machinery/alarm/proc/apply_mode()
+ switch(mode)
+ if(AALARM_MODE_SCRUBBING)
+ for(var/device_id in alarm_area.air_scrub_names)
+ send_signal(device_id, list(
+ "power"= 1,
+ "o2_scrub" = (preset==AALARM_PRESET_VOX),
+ "n2_scrub" = 0,
+ "co2_scrub"= 1,
+ "scrubbing"= 1,
+ "widenet"= 0,
+ ))
+ for(var/device_id in alarm_area.air_vent_names)
+ send_signal(device_id, list(
+ "power"= 1,
+ "checks"= 1,
+ "set_external_pressure"= ONE_ATMOSPHERE
+ ))
+ if(AALARM_MODE_CONTAMINATED)
+ for(var/device_id in alarm_area.air_scrub_names)
+ send_signal(device_id, list(
+ "power"= 1,
+ "co2_scrub"= 1,
+ "tox_scrub"= 1,
+ "n2o_scrub"= 1,
+ "scrubbing"= 1,
+ "widenet"= 1,
+ ))
+ for(var/device_id in alarm_area.air_vent_names)
+ send_signal(device_id, list(
+ "power"= 1,
+ "checks"= 1,
+ "set_external_pressure"= ONE_ATMOSPHERE
+ ))
+ if(AALARM_MODE_VENTING)
+ for(var/device_id in alarm_area.air_scrub_names)
+ send_signal(device_id, list(
+ "power"= 1,
+ "widenet"= 0,
+ "scrubbing"= 0
+ ))
+ for(var/device_id in alarm_area.air_vent_names)
+ send_signal(device_id, list(
+ "power"= 1,
+ "checks"= 1,
+ "set_external_pressure" = ONE_ATMOSPHERE*2
+ ))
+ if(AALARM_MODE_REFILL)
+ for(var/device_id in alarm_area.air_scrub_names)
+ send_signal(device_id, list(
+ "power"= 1,
+ "co2_scrub"= 1,
+ "tox_scrub"= 0,
+ "n2o_scrub"= 0,
+ "scrubbing"= 1,
+ "widenet"= 0,
+ ))
+ for(var/device_id in alarm_area.air_vent_names)
+ send_signal(device_id, list(
+ "power"= 1,
+ "checks"= 1,
+ "set_external_pressure" = ONE_ATMOSPHERE*3
+ ))
+ if(
+ AALARM_MODE_PANIC,
+ AALARM_MODE_REPLACEMENT
+ )
+ for(var/device_id in alarm_area.air_scrub_names)
+ send_signal(device_id, list(
+ "power"= 1,
+ "widenet"= 1,
+ "scrubbing"= 0
+ ))
+ for(var/device_id in alarm_area.air_vent_names)
+ send_signal(device_id, list(
+ "power"= 0
+ ))
+ if(
+ AALARM_MODE_SIPHON
+ )
+ for(var/device_id in alarm_area.air_scrub_names)
+ send_signal(device_id, list(
+ "power"= 1,
+ "widenet"= 0,
+ "scrubbing"= 0
+ ))
+ for(var/device_id in alarm_area.air_vent_names)
+ send_signal(device_id, list(
+ "power"= 0
+ ))
+
+ if(AALARM_MODE_OFF)
+ for(var/device_id in alarm_area.air_scrub_names)
+ send_signal(device_id, list(
+ "power"= 0
+ ))
+ for(var/device_id in alarm_area.air_vent_names)
+ send_signal(device_id, list(
+ "power"= 0
+ ))
+ if(AALARM_MODE_FLOOD)
+ for(var/device_id in alarm_area.air_scrub_names)
+ send_signal(device_id, list(
+ "power"=0
+ ))
+ for(var/device_id in alarm_area.air_vent_names)
+ send_signal(device_id, list(
+ "power"= 1,
+ "checks"= 0,
+ ))
+
+/obj/machinery/alarm/proc/apply_danger_level(var/new_danger_level)
+ if(report_danger_level && alarm_area.atmosalert(new_danger_level, src))
+ post_alert(new_danger_level)
+
+ update_icon()
+
+/obj/machinery/alarm/proc/post_alert(alert_level)
+ var/datum/radio_frequency/frequency = SSradio.return_frequency(alarm_frequency)
+ if(!frequency)
+ return
+
+ var/datum/signal/alert_signal = new
+ alert_signal.source = src
+ alert_signal.transmission_method = 1
+ alert_signal.data["zone"] = alarm_area.name
+ alert_signal.data["type"] = "Atmospheric"
+
+ if(alert_level==2)
+ alert_signal.data["alert"] = "severe"
+ else if(alert_level==1)
+ alert_signal.data["alert"] = "minor"
+ else if(alert_level==0)
+ alert_signal.data["alert"] = "clear"
+
+ frequency.post_signal(src, alert_signal)
+
+///////////////
+//END HACKING//
+///////////////
+
+/obj/machinery/alarm/attack_ai(mob/user)
+ src.add_hiddenprint(user)
+ return ui_interact(user)
+
+/obj/machinery/alarm/attack_ghost(user as mob)
+ return interact(user)
+
+/obj/machinery/alarm/attack_hand(mob/user)
+ . = ..()
+ if(.)
+ return
+ return interact(user)
+
+/obj/machinery/alarm/interact(mob/user)
+ if(buildstage != 2)
+ return
+
+ if(wiresexposed)
+ wires.Interact(user)
+
+ if(!shorted)
+ ui_interact(user)
+
+/obj/machinery/alarm/proc/ui_air_status()
+ var/turf/location = get_turf(src)
+ if(!istype(location))
+ return
+
+ var/datum/gas_mixture/environment = location.return_air()
+ var/total = environment.oxygen + environment.nitrogen + environment.carbon_dioxide + environment.toxins
+ if(total==0)
+ return null
+
+ var/datum/tlv/cur_tlv
+ var/GET_PP = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume
+
+ cur_tlv = TLV["pressure"]
+ var/environment_pressure = environment.return_pressure()
+ var/pressure_dangerlevel = cur_tlv.get_danger_level(environment_pressure)
+
+ cur_tlv = TLV["oxygen"]
+ var/oxygen_dangerlevel = cur_tlv.get_danger_level(environment.oxygen*GET_PP)
+ var/oxygen_percent = round(environment.oxygen / total * 100, 2)
+
+ cur_tlv = TLV["nitrogen"]
+ var/nitrogen_dangerlevel = cur_tlv.get_danger_level(environment.nitrogen*GET_PP)
+ var/nitrogen_percent = round(environment.nitrogen / total * 100, 2)
+
+ cur_tlv = TLV["carbon dioxide"]
+ var/co2_dangerlevel = cur_tlv.get_danger_level(environment.carbon_dioxide*GET_PP)
+ var/co2_percent = round(environment.carbon_dioxide / total * 100, 2)
+
+ cur_tlv = TLV["plasma"]
+ var/plasma_dangerlevel = cur_tlv.get_danger_level(environment.toxins*GET_PP)
+ var/plasma_percent = round(environment.toxins / total * 100, 2)
+
+ cur_tlv = TLV["other"]
+ var/other_moles = 0.0
+ for(var/datum/gas/G in environment.trace_gases)
+ other_moles+=G.moles
+ var/other_dangerlevel = cur_tlv.get_danger_level(other_moles*GET_PP)
+
+ cur_tlv = TLV["temperature"]
+ var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature)
+
+ var/data[0]
+ data["pressure"] = environment_pressure
+ data["temperature"] = environment.temperature
+ data["temperature_c"] = round(environment.temperature - T0C, 0.1)
+
+ var/percentages[0]
+ percentages["oxygen"] = oxygen_percent
+ percentages["nitrogen"] = nitrogen_percent
+ percentages["co2"] = co2_percent
+ percentages["plasma"] = plasma_percent
+ percentages["other"] = other_moles
+ data["contents"] = percentages
+
+ var/danger[0]
+ danger["pressure"] = pressure_dangerlevel
+ danger["temperature"] = temperature_dangerlevel
+ danger["oxygen"] = oxygen_dangerlevel
+ danger["nitrogen"] = nitrogen_dangerlevel
+ danger["co2"] = co2_dangerlevel
+ danger["plasma"] = plasma_dangerlevel
+ danger["other"] = other_dangerlevel
+ danger["overall"] = max(pressure_dangerlevel,oxygen_dangerlevel,nitrogen_dangerlevel,co2_dangerlevel,plasma_dangerlevel,other_dangerlevel,temperature_dangerlevel)
+ data["danger"] = danger
+ return data
+
+/obj/machinery/alarm/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state)
+ var/data[0]
+
+ var/list/href_list = state.href_list(user)
+ if(href_list)
+ data["remote_connection"] = href_list["remote_connection"]
+ data["remote_access"] = href_list["remote_access"]
+
+ data["name"] = sanitize(name)
+ data["air"] = ui_air_status()
+ data["alarmActivated"] = alarmActivated || danger_level == ATMOS_ALARM_DANGER
+ data["thresholds"] = generate_thresholds_menu()
+
+ // Locked when:
+ // Not sent from atmos console AND
+ // Not silicon AND locked.
+ data["locked"] = !is_authenticated(user, href_list)
+ data["rcon"] = rcon_setting
+ data["target_temp"] = target_temperature - T0C
+ data["atmos_alarm"] = alarm_area.atmosalm
+ data["emagged"] = emagged
+ data["modes"] = list(
+ AALARM_MODE_SCRUBBING = list("name"="Filtering", "desc"="Scrubs out contaminants"),\
+ AALARM_MODE_VENTING = list("name"="Draught", "desc"="Siphons out air while replacing"),\
+ AALARM_MODE_PANIC = list("name"="Panic Siphon","desc"="Siphons air out of the room quickly"),\
+ AALARM_MODE_REPLACEMENT = list("name"="Cycle", "desc"="Siphons air before replacing"),\
+ AALARM_MODE_SIPHON = list("name"="Siphon", "desc"="Siphons air out of the room"),\
+ AALARM_MODE_CONTAMINATED= list("name"="Contaminated","desc"="Scrubs out all contaminants quickly"),\
+ AALARM_MODE_REFILL = list("name"="Refill", "desc"="Triples vent output"),\
+ AALARM_MODE_OFF = list("name"="Off", "desc"="Shuts off vents and scrubbers"),\
+ AALARM_MODE_FLOOD = list("name"="Flood", "desc"="Shuts off scrubbers and opens vents", "emagonly" = 1)
+ )
+ data["mode"] = mode
+ data["presets"] = list(
+ AALARM_PRESET_HUMAN = list("name"="Human", "desc"="Checks for oxygen and nitrogen"),\
+ AALARM_PRESET_VOX = list("name"="Vox", "desc"="Checks for nitrogen only"),\
+ AALARM_PRESET_COLDROOM = list("name"="Coldroom", "desc"="For freezers"),\
+ AALARM_PRESET_SERVER = list("name"="Server Room", "desc"="For server rooms")
+ )
+ data["preset"] = preset
+ data["screen"] = screen
+
+ var/list/vents=list()
+ if(alarm_area.air_vent_names.len)
+ for(var/id_tag in alarm_area.air_vent_names)
+ var/vent_info[0]
+ var/long_name = alarm_area.air_vent_names[id_tag]
+ var/list/vent_data = alarm_area.air_vent_info[id_tag]
+ if(!vent_data)
+ continue
+ vent_info["id_tag"]=id_tag
+ vent_info["name"]=sanitize(long_name)
+ vent_info += vent_data
+ vents+=list(vent_info)
+ data["vents"]=vents
+
+ var/list/scrubbers=list()
+ if(alarm_area.air_scrub_names.len)
+ for(var/id_tag in alarm_area.air_scrub_names)
+ var/long_name = alarm_area.air_scrub_names[id_tag]
+ var/list/scrubber_data = alarm_area.air_scrub_info[id_tag]
+ if(!scrubber_data)
+ continue
+ scrubber_data["id_tag"]=id_tag
+ scrubber_data["name"]=sanitize(long_name)
+ scrubbers+=list(scrubber_data)
+ data["scrubbers"]=scrubbers
+ return data
+
+/obj/machinery/alarm/proc/get_nano_data_console(mob/user)
+ var/data[0]
+ data["name"] = sanitize(name)
+ data["ref"] = "\ref[src]"
+ data["danger"] = max(danger_level, alarm_area.atmosalm)
+ var/area/Area = get_area(src)
+ data["area"] = sanitize(Area.name)
+ var/turf/pos = get_turf(src)
+ data["x"] = pos.x
+ data["y"] = pos.y
+ data["z"] = pos.z
+ return data
+
+/obj/machinery/alarm/proc/generate_thresholds_menu()
+ var/datum/tlv/selected
+ var/list/thresholds = list()
+
+ var/list/gas_names = list(
+ "oxygen" = "O2",
+ "nitrogen" = "N2",
+ "carbon dioxide" = "CO2",
+ "plasma" = "Toxin",
+ "other" = "Other")
+ for(var/g in gas_names)
+ thresholds += list(list("name" = gas_names[g], "settings" = list()))
+ selected = TLV[g]
+ thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = "min2", "selected" = selected.min2))
+ thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = "min1", "selected" = selected.min1))
+ thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = "max1", "selected" = selected.max1))
+ thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = "max2", "selected" = selected.max2))
+
+ selected = TLV["pressure"]
+ thresholds += list(list("name" = "Pressure", "settings" = list()))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min2", "selected" = selected.min2))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min1", "selected" = selected.min1))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max1", "selected" = selected.max1))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max2", "selected" = selected.max2))
+
+ selected = TLV["temperature"]
+ thresholds += list(list("name" = "Temperature", "settings" = list()))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min2", "selected" = selected.min2))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min1", "selected" = selected.min1))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max1", "selected" = selected.max1))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max2", "selected" = selected.max2))
+
+ return thresholds
+
+/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
+ ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "air_alarm.tmpl", name, 570, 410, state = state)
+ ui.open()
+ ui.set_auto_update(1)
+
+/obj/machinery/alarm/proc/is_authenticated(var/mob/user, href_list)
+ if(user.can_admin_interact())
+ return 1
+ else if(isAI(user) || isrobot(user) || emagged || is_auth_rcon(href_list))
+ return 1
+ else
+ return !locked
+
+/obj/machinery/alarm/proc/is_auth_rcon(href_list)
+ if(href_list && href_list["remote_connection"] && href_list["remote_access"])
+ return 1
+ else
+ return 0
+
+/obj/machinery/alarm/CanUseTopic(var/mob/user, var/datum/topic_state/state, var/href_list = list())
+ if(buildstage != 2)
+ return STATUS_CLOSE
+
+ if(aidisabled && (isAI(user) || isrobot(user)))
+ to_chat(user, "AI control for \the [src] interface has been disabled.")
+ return STATUS_CLOSE
+
+ . = shorted ? STATUS_DISABLED : STATUS_INTERACTIVE
+
+ if(. == STATUS_INTERACTIVE)
+ var/extra_href = state.href_list(usr)
+ // Prevent remote users from altering RCON settings or activating atmos alarms unless they already have access
+ if((href_list["atmos_alarm"] || href_list["rcon"]) && extra_href["remote_connection"] && !extra_href["remote_access"])
+ . = STATUS_UPDATE
+ return min(..(), .)
+
+/obj/machinery/alarm/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state)
+ if(..(href, href_list, nowindow, state))
+ return 1
+
+ var/state_href = state.href_list(usr)
+
+ if(href_list["rcon"])
+ var/attempted_rcon_setting = text2num(href_list["rcon"])
+ switch(attempted_rcon_setting)
+ if(RCON_NO)
+ rcon_setting = RCON_NO
+ if(RCON_AUTO)
+ rcon_setting = RCON_AUTO
+ if(RCON_YES)
+ rcon_setting = RCON_YES
+ return 1
+
+ add_fingerprint(usr)
+
+ if(href_list["command"])
+ if(!is_authenticated(usr, state_href))
+ return
+
+ var/device_id = href_list["id_tag"]
+ switch(href_list["command"])
+ if( "power",
+ "adjust_external_pressure",
+ "set_external_pressure",
+ "checks",
+ "co2_scrub",
+ "tox_scrub",
+ "n2o_scrub",
+ "n2_scrub",
+ "o2_scrub",
+ "widenet",
+ "scrubbing",
+ "direction")
+ var/val
+ if(href_list["val"])
+ val=text2num(href_list["val"])
+ else
+ var/newval = input("Enter new value") as num|null
+ if(isnull(newval))
+ return
+ if(href_list["command"]=="set_external_pressure")
+ if(newval>1000+ONE_ATMOSPHERE)
+ newval = 1000+ONE_ATMOSPHERE
+ if(newval<0)
+ newval = 0
+ val = newval
+
+ send_signal(device_id, list(href_list["command"] = val ) )
+ waiting_on_device=device_id
+
+ if("set_threshold")
+ var/env = href_list["env"]
+ var/varname = href_list["var"]
+ var/datum/tlv/tlv = TLV[env]
+ var/newval = input("Enter [varname] for [env]", "Alarm triggers", tlv.vars[varname]) as num|null
+
+ if(isnull(newval) || ..(href, href_list, nowindow, state))
+ return
+ if(newval<0)
+ tlv.vars[varname] = -1.0
+ else if(env=="temperature" && newval>5000)
+ tlv.vars[varname] = 5000
+ else if(env=="pressure" && newval>50*ONE_ATMOSPHERE)
+ tlv.vars[varname] = 50*ONE_ATMOSPHERE
+ else if(env!="temperature" && env!="pressure" && newval>200)
+ tlv.vars[varname] = 200
+ else
+ newval = round(newval,0.01)
+ tlv.vars[varname] = newval
+
+ if(href_list["screen"])
+ if(!is_authenticated(usr, state_href))
+ return
+
+ screen = text2num(href_list["screen"])
+ return 1
+
+ if(href_list["atmos_alarm"])
+ if(alarm_area.atmosalert(ATMOS_ALARM_DANGER, src))
+ apply_danger_level(ATMOS_ALARM_DANGER)
+ alarmActivated = 1
+ update_icon()
+ return 1
+
+ if(href_list["atmos_reset"])
+ if(alarm_area.atmosalert(ATMOS_ALARM_NONE, src, TRUE))
+ apply_danger_level(ATMOS_ALARM_NONE)
+ alarmActivated = 0
+ update_icon()
+ return 1
+
+ if(href_list["mode"])
+ if(!is_authenticated(usr, state_href))
+ return
+
+ mode = text2num(href_list["mode"])
+ apply_mode()
+ return 1
+
+ if(href_list["preset"])
+ if(!is_authenticated(usr, state_href))
+ return
+
+ preset = text2num(href_list["preset"])
+ apply_preset()
+ return 1
+
+ if(href_list["temperature"])
+ var/datum/tlv/selected = TLV["temperature"]
+ var/max_temperature = selected.max1 >= 0 ? min(selected.max1, MAX_TEMPERATURE) : max(selected.max1, MAX_TEMPERATURE)
+ var/min_temperature = max(selected.min1, MIN_TEMPERATURE)
+ var/max_temperature_c = max_temperature - T0C
+ var/min_temperature_c = min_temperature - T0C
+ var/input_temperature = input("What temperature would you like the system to maintain? (Capped between [min_temperature_c]C and [max_temperature_c]C)", "Thermostat Controls") as num|null
+ if(isnull(input_temperature) || ..(href, href_list, nowindow, state))
+ return
+ input_temperature = input_temperature + T0C
+ if(input_temperature > max_temperature || input_temperature < min_temperature)
+ to_chat(usr, "Temperature must be between [min_temperature_c]C and [max_temperature_c]C")
+ else
+ target_temperature = input_temperature
+ return 1
+
+/obj/machinery/alarm/emag_act(mob/user)
+ if(!emagged)
+ src.emagged = 1
+ if(user)
+ user.visible_message("Sparks fly out of the [src]!", "You emag the [src], disabling its safeties.")
+ playsound(src.loc, 'sound/effects/sparks4.ogg', 50, 1)
+ return
+
+/obj/machinery/alarm/attackby(obj/item/I, mob/user, params)
+ add_fingerprint(user)
+
+ switch(buildstage)
+ if(2)
+ if(istype(I, /obj/item/card/id) || istype(I, /obj/item/pda))// trying to unlock the interface with an ID card
+ if(stat & (NOPOWER|BROKEN))
+ to_chat(user, "It does nothing")
+ return
+ else
+ if(allowed(usr) && !wires.IsIndexCut(AALARM_WIRE_IDSCAN))
+ locked = !locked
+ to_chat(user, "You [ locked ? "lock" : "unlock"] the Air Alarm interface.")
+ updateUsrDialog()
+ else
+ to_chat(user, "Access denied.")
+ return
+
+ if(1)
+ if(iscoil(I))
+ var/obj/item/stack/cable_coil/coil = I
+ if(coil.amount < 5)
+ to_chat(user, "You need more cable for this!")
+ return
+
+ to_chat(user, "You wire \the [src]!")
+ playsound(get_turf(src), coil.usesound, 50, 1)
+ coil.amount -= 5
+ if(!coil.amount)
+ qdel(coil)
+
+ buildstage = 2
+ update_icon()
+ first_run()
+ return
+ if(0)
+ if(istype(I, /obj/item/airalarm_electronics))
+ to_chat(user, "You insert the circuit!")
+ playsound(get_turf(src), I.usesound, 50, 1)
+ qdel(I)
+ buildstage = 1
+ update_icon()
+ return
+ return ..()
+
/obj/machinery/alarm/crowbar_act(mob/user, obj/item/I)
if(buildstage != AIR_ALARM_BUILDING)
return
@@ -1007,7 +1007,7 @@
new /obj/item/airalarm_electronics(user.drop_location())
buildstage = AIR_ALARM_FRAME
update_icon()
-
+
/obj/machinery/alarm/multitool_act(mob/user, obj/item/I)
if(buildstage != AIR_ALARM_READY)
return
@@ -1053,56 +1053,56 @@
new /obj/item/mounted/frame/alarm_frame(get_turf(user))
WRENCH_UNANCHOR_WALL_MESSAGE
qdel(src)
-
-/obj/machinery/alarm/power_change()
- if(powered(power_channel))
- stat &= ~NOPOWER
- else
- stat |= NOPOWER
- spawn(rand(0,15))
- update_icon()
-
-/obj/machinery/alarm/obj_break(damage_flag)
- ..()
- update_icon()
-
-/obj/machinery/alarm/deconstruct(disassembled = TRUE)
- if(!(flags & NODECONSTRUCT))
- new /obj/item/stack/sheet/metal(loc, 2)
- var/obj/item/I = new /obj/item/airalarm_electronics(loc)
- if(!disassembled)
- I.obj_integrity = I.max_integrity * 0.5
- new /obj/item/stack/cable_coil(loc, 3)
- qdel(src)
-
-/obj/machinery/alarm/examine(mob/user)
- . = ..()
- if(buildstage < 2)
- . += "It is not wired."
- if(buildstage < 1)
- . += "The circuit is missing."
-
-/obj/machinery/alarm/all_access
- name = "all-access air alarm"
- desc = "This particular atmos control unit appears to have no access restrictions."
- locked = FALSE
- req_access = null
- req_one_access = null
-
-/*
-AIR ALARM CIRCUIT
-Just an object used in constructing air alarms
-*/
-/obj/item/airalarm_electronics
- name = "air alarm electronics"
- icon = 'icons/obj/doors/door_assembly.dmi'
- icon_state = "door_electronics"
- desc = "Looks like a circuit. Probably is."
- w_class = WEIGHT_CLASS_SMALL
- materials = list(MAT_METAL=50, MAT_GLASS=50)
- origin_tech = "engineering=2;programming=1"
- toolspeed = 1
- usesound = 'sound/items/deconstruct.ogg'
+
+/obj/machinery/alarm/power_change()
+ if(powered(power_channel))
+ stat &= ~NOPOWER
+ else
+ stat |= NOPOWER
+ spawn(rand(0,15))
+ update_icon()
+
+/obj/machinery/alarm/obj_break(damage_flag)
+ ..()
+ update_icon()
+
+/obj/machinery/alarm/deconstruct(disassembled = TRUE)
+ if(!(flags & NODECONSTRUCT))
+ new /obj/item/stack/sheet/metal(loc, 2)
+ var/obj/item/I = new /obj/item/airalarm_electronics(loc)
+ if(!disassembled)
+ I.obj_integrity = I.max_integrity * 0.5
+ new /obj/item/stack/cable_coil(loc, 3)
+ qdel(src)
+
+/obj/machinery/alarm/examine(mob/user)
+ . = ..()
+ if(buildstage < 2)
+ . += "It is not wired."
+ if(buildstage < 1)
+ . += "The circuit is missing."
+
+/obj/machinery/alarm/all_access
+ name = "all-access air alarm"
+ desc = "This particular atmos control unit appears to have no access restrictions."
+ locked = FALSE
+ req_access = null
+ req_one_access = null
+
+/*
+AIR ALARM CIRCUIT
+Just an object used in constructing air alarms
+*/
+/obj/item/airalarm_electronics
+ name = "air alarm electronics"
+ icon = 'icons/obj/doors/door_assembly.dmi'
+ icon_state = "door_electronics"
+ desc = "Looks like a circuit. Probably is."
+ w_class = WEIGHT_CLASS_SMALL
+ materials = list(MAT_METAL=50, MAT_GLASS=50)
+ origin_tech = "engineering=2;programming=1"
+ toolspeed = 1
+ usesound = 'sound/items/deconstruct.ogg'
#undef AIR_ALARM_FRAME
diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm
index 92b7cf8ca54..91d9103e994 100644
--- a/code/game/machinery/buttons.dm
+++ b/code/game/machinery/buttons.dm
@@ -1,206 +1,206 @@
-
-//////////////////////////////////////
-// Driver Button //
-//////////////////////////////////////
-
-/obj/machinery/driver_button
- name = "mass driver button"
- icon = 'icons/obj/objects.dmi'
- icon_state = "launcherbtt"
- desc = "A remote control switch for a mass driver."
- var/id_tag = "default"
- var/active = 0
- settagwhitelist = list("id_tag", "logic_id_tag")
- anchored = 1.0
- armor = list(melee = 50, bullet = 50, laser = 50, energy = 50, bomb = 10, bio = 100, rad = 100, fire = 90, acid = 70)
- use_power = IDLE_POWER_USE
- idle_power_usage = 2
- active_power_usage = 4
- resistance_flags = LAVA_PROOF | FIRE_PROOF
- var/range = 7
-
- var/datum/radio_frequency/radio_connection
- var/frequency = 0
- var/logic_id_tag = "default" //Defines the ID tag to send logic signals to, so you don't have to unlink from doors and stuff
- var/logic_connect = 0 //Set this to allow the button to send out logic signals when pressed in addition to normal stuff
-
-/obj/machinery/button/indestructible
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
-
-/obj/machinery/driver_button/New(turf/loc, var/w_dir=null)
- ..()
- switch(w_dir)
- if(NORTH)
- pixel_y = 25
- if(SOUTH)
- pixel_y = -25
- if(EAST)
- pixel_x = 25
- if(WEST)
- pixel_x = -25
- if(SSradio)
- set_frequency(frequency)
-
-/obj/machinery/driver_button/Initialize()
- ..()
- set_frequency(frequency)
-
-/obj/machinery/driver_button/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- radio_connection = SSradio.add_object(src, frequency, RADIO_LOGIC)
- return
-
-/obj/machinery/driver_button/Destroy()
- if(SSradio)
- SSradio.remove_object(src, frequency)
- radio_connection = null
- return ..()
-
-
-/obj/machinery/driver_button/attack_ai(mob/user as mob)
- return attack_hand(user)
-
-/obj/machinery/driver_button/attack_ghost(mob/user)
- if(user.can_advanced_admin_interact())
- return attack_hand(user)
-
-/obj/machinery/driver_button/attackby(obj/item/W, mob/user as mob, params)
-
- if(istype(W, /obj/item/detective_scanner))
- return
-
- if(istype(W, /obj/item/multitool))
- update_multitool_menu(user)
- return 1
-
- if(istype(W, /obj/item/wrench))
- playsound(get_turf(src), W.usesound, 50, 1)
- if(do_after(user, 30 * W.toolspeed, target = src))
- to_chat(user, "You detach \the [src] from the wall.")
- new/obj/item/mounted/frame/driver_button(get_turf(src))
- qdel(src)
- return 1
-
- return ..()
-
-/obj/machinery/driver_button/multitool_menu(var/mob/user, var/obj/item/multitool/P)
- return {"
-
- - ID Tag: [format_tag("ID Tag","id_tag")]
- - Logic Connection: [logic_connect ? "On" : "Off"]
- - Logic ID Tag: [format_tag("Logic ID Tag", "logic_id_tag")]
-
"}
-
-/obj/machinery/driver_button/attack_hand(mob/user as mob)
-
- add_fingerprint(usr)
- if(stat & (NOPOWER|BROKEN))
- return
- if(active)
- return
- add_fingerprint(user)
-
- use_power(5)
-
- launch_sequence()
-
-/obj/machinery/driver_button/proc/launch_sequence()
- active = 1
- icon_state = "launcheract"
-
- if(logic_connect)
- if(!radio_connection) //can't output without this
- return
-
- if(logic_id_tag == null) //Don't output to an undefined id_tag
- return
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
- "tag" = logic_id_tag,
- "sigtype" = "logic",
- "state" = LOGIC_FLICKER, //Buttons are a FLICKER source, since they only register as ON when you press it, then turn OFF after you release
- )
-
- radio_connection.post_signal(src, signal, filter = RADIO_LOGIC)
-
- for(var/obj/machinery/door/poddoor/M in range(src,range))
- if(M.id_tag == id_tag && !M.protected)
- spawn()
- M.open()
-
- sleep(20)
-
- for(var/obj/machinery/mass_driver/M in range(src,range))
- if(M.id_tag == id_tag)
- M.drive()
-
- sleep(50)
-
- for(var/obj/machinery/door/poddoor/M in range(src,range))
- if(M.id_tag == id_tag && !M.protected)
- spawn()
- M.close()
- return
-
- icon_state = "launcherbtt"
- active = 0
-
-/obj/machinery/driver_button/multitool_topic(var/mob/user,var/list/href_list,var/obj/O)
- ..()
- if("toggle_logic" in href_list)
- logic_connect = !logic_connect
-
-//////////////////////////////////////
-// Ignition Switch //
-//////////////////////////////////////
-
-/obj/machinery/ignition_switch
- name = "ignition switch"
- icon = 'icons/obj/objects.dmi'
- icon_state = "launcherbtt"
- desc = "A remote control switch for a mounted igniter."
- var/id = null
- var/active = 0
- anchored = 1.0
- use_power = IDLE_POWER_USE
- idle_power_usage = 2
- active_power_usage = 4
-
-/obj/machinery/ignition_switch/attack_ai(mob/user)
- return attack_hand(user)
-
-/obj/machinery/ignition_switch/attack_ghost(mob/user)
- if(user.can_advanced_admin_interact())
- return attack_hand(user)
-
-/obj/machinery/ignition_switch/attack_hand(mob/user)
- if(stat & (NOPOWER|BROKEN))
- return
- if(active)
- return
-
- use_power(5)
-
- active = 1
- icon_state = "launcheract"
-
- for(var/obj/machinery/sparker/M in world)
- if(M.id == id)
- spawn( 0 )
- M.spark()
-
- for(var/obj/machinery/igniter/M in world)
- if(M.id == id)
- use_power(50)
- M.on = !( M.on )
- M.icon_state = text("igniter[]", M.on)
-
- sleep(50)
-
- icon_state = "launcherbtt"
- active = 0
+
+//////////////////////////////////////
+// Driver Button //
+//////////////////////////////////////
+
+/obj/machinery/driver_button
+ name = "mass driver button"
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "launcherbtt"
+ desc = "A remote control switch for a mass driver."
+ var/id_tag = "default"
+ var/active = 0
+ settagwhitelist = list("id_tag", "logic_id_tag")
+ anchored = 1.0
+ armor = list(melee = 50, bullet = 50, laser = 50, energy = 50, bomb = 10, bio = 100, rad = 100, fire = 90, acid = 70)
+ use_power = IDLE_POWER_USE
+ idle_power_usage = 2
+ active_power_usage = 4
+ resistance_flags = LAVA_PROOF | FIRE_PROOF
+ var/range = 7
+
+ var/datum/radio_frequency/radio_connection
+ var/frequency = 0
+ var/logic_id_tag = "default" //Defines the ID tag to send logic signals to, so you don't have to unlink from doors and stuff
+ var/logic_connect = 0 //Set this to allow the button to send out logic signals when pressed in addition to normal stuff
+
+/obj/machinery/button/indestructible
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+
+/obj/machinery/driver_button/New(turf/loc, var/w_dir=null)
+ ..()
+ switch(w_dir)
+ if(NORTH)
+ pixel_y = 25
+ if(SOUTH)
+ pixel_y = -25
+ if(EAST)
+ pixel_x = 25
+ if(WEST)
+ pixel_x = -25
+ if(SSradio)
+ set_frequency(frequency)
+
+/obj/machinery/driver_button/Initialize()
+ ..()
+ set_frequency(frequency)
+
+/obj/machinery/driver_button/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ radio_connection = SSradio.add_object(src, frequency, RADIO_LOGIC)
+ return
+
+/obj/machinery/driver_button/Destroy()
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
+ radio_connection = null
+ return ..()
+
+
+/obj/machinery/driver_button/attack_ai(mob/user as mob)
+ return attack_hand(user)
+
+/obj/machinery/driver_button/attack_ghost(mob/user)
+ if(user.can_advanced_admin_interact())
+ return attack_hand(user)
+
+/obj/machinery/driver_button/attackby(obj/item/W, mob/user as mob, params)
+
+ if(istype(W, /obj/item/detective_scanner))
+ return
+
+ if(istype(W, /obj/item/multitool))
+ update_multitool_menu(user)
+ return 1
+
+ if(istype(W, /obj/item/wrench))
+ playsound(get_turf(src), W.usesound, 50, 1)
+ if(do_after(user, 30 * W.toolspeed, target = src))
+ to_chat(user, "You detach \the [src] from the wall.")
+ new/obj/item/mounted/frame/driver_button(get_turf(src))
+ qdel(src)
+ return 1
+
+ return ..()
+
+/obj/machinery/driver_button/multitool_menu(var/mob/user, var/obj/item/multitool/P)
+ return {"
+
+ - ID Tag: [format_tag("ID Tag","id_tag")]
+ - Logic Connection: [logic_connect ? "On" : "Off"]
+ - Logic ID Tag: [format_tag("Logic ID Tag", "logic_id_tag")]
+
"}
+
+/obj/machinery/driver_button/attack_hand(mob/user as mob)
+
+ add_fingerprint(usr)
+ if(stat & (NOPOWER|BROKEN))
+ return
+ if(active)
+ return
+ add_fingerprint(user)
+
+ use_power(5)
+
+ launch_sequence()
+
+/obj/machinery/driver_button/proc/launch_sequence()
+ active = 1
+ icon_state = "launcheract"
+
+ if(logic_connect)
+ if(!radio_connection) //can't output without this
+ return
+
+ if(logic_id_tag == null) //Don't output to an undefined id_tag
+ return
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ signal.data = list(
+ "tag" = logic_id_tag,
+ "sigtype" = "logic",
+ "state" = LOGIC_FLICKER, //Buttons are a FLICKER source, since they only register as ON when you press it, then turn OFF after you release
+ )
+
+ radio_connection.post_signal(src, signal, filter = RADIO_LOGIC)
+
+ for(var/obj/machinery/door/poddoor/M in range(src,range))
+ if(M.id_tag == id_tag && !M.protected)
+ spawn()
+ M.open()
+
+ sleep(20)
+
+ for(var/obj/machinery/mass_driver/M in range(src,range))
+ if(M.id_tag == id_tag)
+ M.drive()
+
+ sleep(50)
+
+ for(var/obj/machinery/door/poddoor/M in range(src,range))
+ if(M.id_tag == id_tag && !M.protected)
+ spawn()
+ M.close()
+ return
+
+ icon_state = "launcherbtt"
+ active = 0
+
+/obj/machinery/driver_button/multitool_topic(var/mob/user,var/list/href_list,var/obj/O)
+ ..()
+ if("toggle_logic" in href_list)
+ logic_connect = !logic_connect
+
+//////////////////////////////////////
+// Ignition Switch //
+//////////////////////////////////////
+
+/obj/machinery/ignition_switch
+ name = "ignition switch"
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "launcherbtt"
+ desc = "A remote control switch for a mounted igniter."
+ var/id = null
+ var/active = 0
+ anchored = 1.0
+ use_power = IDLE_POWER_USE
+ idle_power_usage = 2
+ active_power_usage = 4
+
+/obj/machinery/ignition_switch/attack_ai(mob/user)
+ return attack_hand(user)
+
+/obj/machinery/ignition_switch/attack_ghost(mob/user)
+ if(user.can_advanced_admin_interact())
+ return attack_hand(user)
+
+/obj/machinery/ignition_switch/attack_hand(mob/user)
+ if(stat & (NOPOWER|BROKEN))
+ return
+ if(active)
+ return
+
+ use_power(5)
+
+ active = 1
+ icon_state = "launcheract"
+
+ for(var/obj/machinery/sparker/M in world)
+ if(M.id == id)
+ spawn( 0 )
+ M.spark()
+
+ for(var/obj/machinery/igniter/M in world)
+ if(M.id == id)
+ use_power(50)
+ M.on = !( M.on )
+ M.icon_state = text("igniter[]", M.on)
+
+ sleep(50)
+
+ icon_state = "launcherbtt"
+ active = 0
diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm
index ef5adee8971..f1675dd65f8 100644
--- a/code/game/machinery/embedded_controller/embedded_controller_base.dm
+++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm
@@ -1,87 +1,87 @@
-/obj/machinery/embedded_controller
- var/datum/computer/file/embedded_program/program //the currently executing program
-
- name = "Embedded Controller"
- anchored = 1
-
- use_power = IDLE_POWER_USE
- idle_power_usage = 10
-
- var/on = 1
-
-/obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line)
- return 0
-
-/obj/machinery/embedded_controller/receive_signal(datum/signal/signal, receive_method, receive_param)
- if(!signal || signal.encryption) return
-
- if(program)
- program.receive_signal(signal, receive_method, receive_param)
- //spawn(5) program.process() //no, program.process sends some signals and machines respond and we here again and we lag -rastaf0
-
-/obj/machinery/embedded_controller/process()
- if(program)
- program.process()
-
- update_icon()
- src.updateDialog()
-
-/obj/machinery/embedded_controller/attack_ghost(mob/user as mob)
- src.ui_interact(user)
-
-/obj/machinery/embedded_controller/attack_ai(mob/user as mob)
- src.ui_interact(user)
-
-/obj/machinery/embedded_controller/attack_hand(mob/user as mob)
- if(!user.IsAdvancedToolUser())
- return 0
- src.ui_interact(user)
-
-/obj/machinery/embedded_controller/ui_interact()
- return
-
-/obj/machinery/embedded_controller/radio
- icon = 'icons/obj/airlock_machines.dmi'
- icon_state = "airlock_control_standby"
- power_channel = ENVIRON
- density = 0
-
- var/id_tag
- //var/radio_power_use = 50 //power used to xmit signals
-
- var/frequency = 1379
- var/radio_filter = null
- var/datum/radio_frequency/radio_connection
- resistance_flags = FIRE_PROOF | ACID_PROOF
-
-/obj/machinery/embedded_controller/radio/Initialize()
- ..()
- set_frequency(frequency)
-
-/obj/machinery/embedded_controller/radio/Destroy()
- if(SSradio)
- SSradio.remove_object(src, frequency)
- radio_connection = null
- return ..()
-
-/obj/machinery/embedded_controller/radio/update_icon()
- if(on && program)
- if(program.memory["processing"])
- icon_state = "airlock_control_process"
- else
- icon_state = "airlock_control_standby"
- else
- icon_state = "airlock_control_off"
-
-/obj/machinery/embedded_controller/radio/post_signal(datum/signal/signal, var/filter = null)
- signal.transmission_method = TRANSMISSION_RADIO
- if(radio_connection)
- //use_power(radio_power_use) //neat idea, but causes way too much lag.
- return radio_connection.post_signal(src, signal, filter)
- else
- qdel(signal)
-
-/obj/machinery/embedded_controller/radio/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- radio_connection = SSradio.add_object(src, frequency, radio_filter)
+/obj/machinery/embedded_controller
+ var/datum/computer/file/embedded_program/program //the currently executing program
+
+ name = "Embedded Controller"
+ anchored = 1
+
+ use_power = IDLE_POWER_USE
+ idle_power_usage = 10
+
+ var/on = 1
+
+/obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line)
+ return 0
+
+/obj/machinery/embedded_controller/receive_signal(datum/signal/signal, receive_method, receive_param)
+ if(!signal || signal.encryption) return
+
+ if(program)
+ program.receive_signal(signal, receive_method, receive_param)
+ //spawn(5) program.process() //no, program.process sends some signals and machines respond and we here again and we lag -rastaf0
+
+/obj/machinery/embedded_controller/process()
+ if(program)
+ program.process()
+
+ update_icon()
+ src.updateDialog()
+
+/obj/machinery/embedded_controller/attack_ghost(mob/user as mob)
+ src.ui_interact(user)
+
+/obj/machinery/embedded_controller/attack_ai(mob/user as mob)
+ src.ui_interact(user)
+
+/obj/machinery/embedded_controller/attack_hand(mob/user as mob)
+ if(!user.IsAdvancedToolUser())
+ return 0
+ src.ui_interact(user)
+
+/obj/machinery/embedded_controller/ui_interact()
+ return
+
+/obj/machinery/embedded_controller/radio
+ icon = 'icons/obj/airlock_machines.dmi'
+ icon_state = "airlock_control_standby"
+ power_channel = ENVIRON
+ density = 0
+
+ var/id_tag
+ //var/radio_power_use = 50 //power used to xmit signals
+
+ var/frequency = 1379
+ var/radio_filter = null
+ var/datum/radio_frequency/radio_connection
+ resistance_flags = FIRE_PROOF | ACID_PROOF
+
+/obj/machinery/embedded_controller/radio/Initialize()
+ ..()
+ set_frequency(frequency)
+
+/obj/machinery/embedded_controller/radio/Destroy()
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
+ radio_connection = null
+ return ..()
+
+/obj/machinery/embedded_controller/radio/update_icon()
+ if(on && program)
+ if(program.memory["processing"])
+ icon_state = "airlock_control_process"
+ else
+ icon_state = "airlock_control_standby"
+ else
+ icon_state = "airlock_control_off"
+
+/obj/machinery/embedded_controller/radio/post_signal(datum/signal/signal, var/filter = null)
+ signal.transmission_method = TRANSMISSION_RADIO
+ if(radio_connection)
+ //use_power(radio_power_use) //neat idea, but causes way too much lag.
+ return radio_connection.post_signal(src, signal, filter)
+ else
+ qdel(signal)
+
+/obj/machinery/embedded_controller/radio/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ radio_connection = SSradio.add_object(src, frequency, radio_filter)
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index 612a38626e3..d98856e16a3 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -1,160 +1,160 @@
-// the light switch
-// can have multiple per area
-// can also operate on non-loc area through "otherarea" var
-/obj/machinery/light_switch
- name = "light switch"
- desc = "It turns lights on and off. What are you, simple?"
- icon = 'icons/obj/power.dmi'
- icon_state = "light1"
- anchored = 1.0
- var/on = 1
- var/area/area = null
- var/otherarea = null
- // luminosity = 1
- settagwhitelist = list("logic_id_tag")
- var/light_connect = 1 //Allows the switch to control lights in its associated areas. When set to 0, using the switch won't affect the lights.
- var/datum/radio_frequency/radio_connection
- var/frequency = 0
- var/logic_id_tag = "default" //Defines the ID tag to send logic signals to.
- var/logic_connect = 0 //Set this to allow the switch to send out logic signals.
-
-
-/obj/machinery/light_switch/New(turf/loc, var/w_dir=null)
- ..()
- switch(w_dir)
- if(NORTH)
- pixel_y = 25
- if(SOUTH)
- pixel_y = -25
- if(EAST)
- pixel_x = 25
- if(WEST)
- pixel_x = -25
- if(SSradio)
- set_frequency(frequency)
- spawn(5)
- src.area = get_area(src)
-
- if(otherarea)
- src.area = locate(text2path("/area/[otherarea]"))
-
- if(!name)
- name = "light switch([area.name])"
-
- src.on = src.area.lightswitch
- updateicon()
-
-/obj/machinery/light_switch/Initialize()
- ..()
- set_frequency(frequency)
-
-/obj/machinery/light_switch/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- radio_connection = SSradio.add_object(src, frequency, RADIO_LOGIC)
- return
-
-/obj/machinery/light_switch/Destroy()
- if(SSradio)
- SSradio.remove_object(src, frequency)
- radio_connection = null
- return ..()
-
-/obj/machinery/light_switch/proc/updateicon()
- if(stat & NOPOWER)
- icon_state = "light-p"
- else
- if(on)
- icon_state = "light1"
- else
- icon_state = "light0"
-
-/obj/machinery/light_switch/examine(mob/user)
- . = ..()
- . += "A light switch. It is [on? "on" : "off"]."
-
-/obj/machinery/light_switch/attack_ghost(mob/user)
- if(user.can_advanced_admin_interact())
- return attack_hand(user)
-
-/obj/machinery/light_switch/attack_hand(mob/user)
- on = !on
- updateicon()
-
- if(light_connect)
- area.lightswitch = on
- area.updateicon()
-
- if(logic_connect && powered(LIGHT)) //Don't bother sending a signal if we aren't set to send them or we have no power to send with.
- handle_output()
-
- if(light_connect)
- for(var/obj/machinery/light_switch/L in area)
- L.on = on
- L.updateicon()
-
- area.power_change()
-
-/obj/machinery/light_switch/proc/handle_output()
- if(!radio_connection) //can't output without this
- return
-
- if(logic_id_tag == null) //Don't output to an undefined id_tag
- return
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- //Light switches are continuous signal sources, since they register as ON or OFF and stay that way until adjusted again
- if(on)
- signal.data = list(
- "tag" = logic_id_tag,
- "sigtype" = "logic",
- "state" = LOGIC_ON,
- )
- else
- signal.data = list(
- "tag" = logic_id_tag,
- "sigtype" = "logic",
- "state" = LOGIC_OFF,
- )
-
- radio_connection.post_signal(src, signal, filter = RADIO_LOGIC)
- if(on)
- use_power(5, LIGHT) //Use a tiny bit of power every time we send an ON signal. Draws from the local APC's lighting circuit, since this is a LIGHT switch.
-
-/obj/machinery/light_switch/power_change()
- if(!otherarea)
- if(powered(LIGHT))
- stat &= ~NOPOWER
- else
- stat |= NOPOWER
-
- updateicon()
-
-/obj/machinery/light_switch/emp_act(severity)
- if(stat & (BROKEN|NOPOWER))
- ..(severity)
- return
- power_change()
- ..(severity)
-
-/obj/machinery/light_switch/process()
- if(logic_connect && powered(LIGHT)) //We won't send signals while unpowered, but the last signal will remain valid for anything that received it before we went dark
- handle_output()
-
-/obj/machinery/light_switch/attackby(obj/item/W as obj, mob/user as mob, params)
- if(istype(W, /obj/item/detective_scanner))
- return
+// the light switch
+// can have multiple per area
+// can also operate on non-loc area through "otherarea" var
+/obj/machinery/light_switch
+ name = "light switch"
+ desc = "It turns lights on and off. What are you, simple?"
+ icon = 'icons/obj/power.dmi'
+ icon_state = "light1"
+ anchored = 1.0
+ var/on = 1
+ var/area/area = null
+ var/otherarea = null
+ // luminosity = 1
+ settagwhitelist = list("logic_id_tag")
+ var/light_connect = 1 //Allows the switch to control lights in its associated areas. When set to 0, using the switch won't affect the lights.
+ var/datum/radio_frequency/radio_connection
+ var/frequency = 0
+ var/logic_id_tag = "default" //Defines the ID tag to send logic signals to.
+ var/logic_connect = 0 //Set this to allow the switch to send out logic signals.
+
+
+/obj/machinery/light_switch/New(turf/loc, var/w_dir=null)
+ ..()
+ switch(w_dir)
+ if(NORTH)
+ pixel_y = 25
+ if(SOUTH)
+ pixel_y = -25
+ if(EAST)
+ pixel_x = 25
+ if(WEST)
+ pixel_x = -25
+ if(SSradio)
+ set_frequency(frequency)
+ spawn(5)
+ src.area = get_area(src)
+
+ if(otherarea)
+ src.area = locate(text2path("/area/[otherarea]"))
+
+ if(!name)
+ name = "light switch([area.name])"
+
+ src.on = src.area.lightswitch
+ updateicon()
+
+/obj/machinery/light_switch/Initialize()
+ ..()
+ set_frequency(frequency)
+
+/obj/machinery/light_switch/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ radio_connection = SSradio.add_object(src, frequency, RADIO_LOGIC)
+ return
+
+/obj/machinery/light_switch/Destroy()
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
+ radio_connection = null
return ..()
-
+
+/obj/machinery/light_switch/proc/updateicon()
+ if(stat & NOPOWER)
+ icon_state = "light-p"
+ else
+ if(on)
+ icon_state = "light1"
+ else
+ icon_state = "light0"
+
+/obj/machinery/light_switch/examine(mob/user)
+ . = ..()
+ . += "A light switch. It is [on? "on" : "off"]."
+
+/obj/machinery/light_switch/attack_ghost(mob/user)
+ if(user.can_advanced_admin_interact())
+ return attack_hand(user)
+
+/obj/machinery/light_switch/attack_hand(mob/user)
+ on = !on
+ updateicon()
+
+ if(light_connect)
+ area.lightswitch = on
+ area.updateicon()
+
+ if(logic_connect && powered(LIGHT)) //Don't bother sending a signal if we aren't set to send them or we have no power to send with.
+ handle_output()
+
+ if(light_connect)
+ for(var/obj/machinery/light_switch/L in area)
+ L.on = on
+ L.updateicon()
+
+ area.power_change()
+
+/obj/machinery/light_switch/proc/handle_output()
+ if(!radio_connection) //can't output without this
+ return
+
+ if(logic_id_tag == null) //Don't output to an undefined id_tag
+ return
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ //Light switches are continuous signal sources, since they register as ON or OFF and stay that way until adjusted again
+ if(on)
+ signal.data = list(
+ "tag" = logic_id_tag,
+ "sigtype" = "logic",
+ "state" = LOGIC_ON,
+ )
+ else
+ signal.data = list(
+ "tag" = logic_id_tag,
+ "sigtype" = "logic",
+ "state" = LOGIC_OFF,
+ )
+
+ radio_connection.post_signal(src, signal, filter = RADIO_LOGIC)
+ if(on)
+ use_power(5, LIGHT) //Use a tiny bit of power every time we send an ON signal. Draws from the local APC's lighting circuit, since this is a LIGHT switch.
+
+/obj/machinery/light_switch/power_change()
+ if(!otherarea)
+ if(powered(LIGHT))
+ stat &= ~NOPOWER
+ else
+ stat |= NOPOWER
+
+ updateicon()
+
+/obj/machinery/light_switch/emp_act(severity)
+ if(stat & (BROKEN|NOPOWER))
+ ..(severity)
+ return
+ power_change()
+ ..(severity)
+
+/obj/machinery/light_switch/process()
+ if(logic_connect && powered(LIGHT)) //We won't send signals while unpowered, but the last signal will remain valid for anything that received it before we went dark
+ handle_output()
+
+/obj/machinery/light_switch/attackby(obj/item/W as obj, mob/user as mob, params)
+ if(istype(W, /obj/item/detective_scanner))
+ return
+ return ..()
+
/obj/machinery/light_switch/multitool_act(mob/user, obj/item/I)
. = TRUE
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
return
update_multitool_menu(user)
-
+
/obj/machinery/light_switch/wrench_act(mob/user, obj/item/I)
. = TRUE
if(!I.tool_use_check(user, 0))
@@ -166,18 +166,18 @@
WRENCH_UNANCHOR_WALL_MESSAGE
new/obj/item/mounted/frame/light_switch(get_turf(src))
qdel(src)
-
-/obj/machinery/light_switch/multitool_menu(var/mob/user, var/obj/item/multitool/P)
- return {"
- "}
-
-/obj/machinery/light_switch/multitool_topic(var/mob/user,var/list/href_list,var/obj/O)
- ..()
- if("toggle_light_connect" in href_list)
- light_connect = !light_connect
- if("toggle_logic" in href_list)
- logic_connect = !logic_connect
+
+/obj/machinery/light_switch/multitool_menu(var/mob/user, var/obj/item/multitool/P)
+ return {"
+ "}
+
+/obj/machinery/light_switch/multitool_topic(var/mob/user,var/list/href_list,var/obj/O)
+ ..()
+ if("toggle_light_connect" in href_list)
+ light_connect = !light_connect
+ if("toggle_logic" in href_list)
+ logic_connect = !logic_connect
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 546702069ee..6f97856a227 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -1,407 +1,407 @@
-/*
-Overview:
- Used to create objects that need a per step proc call. Default definition of 'New()'
- stores a reference to src machine in global 'machines list'. Default definition
- of 'Del' removes reference to src machine in global 'machines list'.
-
-Class Variables:
- use_power (num)
- current state of auto power use.
- Possible Values:
- 0 -- no auto power use
- 1 -- machine is using power at its idle power level
- 2 -- machine is using power at its active power level
-
- active_power_usage (num)
- Value for the amount of power to use when in active power mode
-
- idle_power_usage (num)
- Value for the amount of power to use when in idle power mode
-
- power_channel (num)
- What channel to draw from when drawing power for power mode
- Possible Values:
- EQUIP:0 -- Equipment Channel
- LIGHT:2 -- Lighting Channel
- ENVIRON:3 -- Environment Channel
-
- component_parts (list)
- A list of component parts of machine used by frame based machines.
-
- uid (num)
- Unique id of machine across all machines.
-
- gl_uid (global num)
- Next uid value in sequence
-
- stat (bitflag)
- Machine status bit flags.
- Possible bit flags:
- BROKEN:1 -- Machine is broken
- NOPOWER:2 -- No power is being supplied to machine.
- POWEROFF:4 -- tbd
- MAINT:8 -- machine is currently under going maintenance.
- EMPED:16 -- temporary broken by EMP pulse
-
- manual (num)
- Currently unused.
-
-Class Procs:
- initialize() 'game/machinery/machine.dm'
-
- Destroy() 'game/machinery/machine.dm'
-
- auto_use_power() 'game/machinery/machine.dm'
- This proc determines how power mode power is deducted by the machine.
- 'auto_use_power()' is called by the 'master_controller' game_controller every
- tick.
-
- Return Value:
- return:1 -- if object is powered
- return:0 -- if object is not powered.
-
- Default definition uses 'use_power', 'power_channel', 'active_power_usage',
- 'idle_power_usage', 'powered()', and 'use_power()' implement behavior.
-
- powered(chan = EQUIP) 'modules/power/power.dm'
- Checks to see if area that contains the object has power available for power
- channel given in 'chan'.
-
- use_power(amount, chan=EQUIP, autocalled) 'modules/power/power.dm'
- Deducts 'amount' from the power channel 'chan' of the area that contains the object.
- If it's autocalled then everything is normal, if something else calls use_power we are going to
- need to recalculate the power two ticks in a row.
-
- power_change() 'modules/power/power.dm'
- Called by the area that contains the object when ever that area under goes a
- power state change (area runs out of power, or area channel is turned off).
-
- RefreshParts() 'game/machinery/machine.dm'
- Called to refresh the variables in the machine that are contributed to by parts
- contained in the component_parts list. (example: glass and material amounts for
- the autolathe)
-
- Default definition does nothing.
-
- assign_uid() 'game/machinery/machine.dm'
- Called by machine to assign a value to the uid variable.
-
- process() 'game/machinery/machine.dm'
- Called by the 'master_controller' once per game tick for each machine that is listed in the 'machines' list.
-
-
- Compiled by Aygar
-*/
-
-/obj/machinery
- name = "machinery"
- icon = 'icons/obj/stationobjs.dmi'
- pressure_resistance = 15
- max_integrity = 200
- layer = BELOW_OBJ_LAYER
- var/stat = 0
- var/emagged = 0
- var/use_power = IDLE_POWER_USE
- //0 = dont run the auto
- //1 = run auto, use idle
- //2 = run auto, use active
- var/idle_power_usage = 0
- var/active_power_usage = 0
- var/power_channel = EQUIP //EQUIP,ENVIRON or LIGHT
- var/list/component_parts = null //list of all the parts used to build it, if made from certain kinds of frames.
- var/uid
- var/manual = 0
- var/global/gl_uid = 1
- var/custom_aghost_alerts=0
- var/panel_open = 0
- var/area/myArea
- var/interact_offline = 0 // Can the machine be interacted with while de-powered.
- var/use_log = list()
- var/list/settagwhitelist = list()//WHITELIST OF VARIABLES THAT THE set_tag HREF CAN MODIFY, DON'T PUT SHIT YOU DON'T NEED ON HERE, AND IF YOU'RE GONNA USE set_tag (format_tag() proc), ADD TO THIS LIST.
- atom_say_verb = "beeps"
- var/siemens_strength = 0.7 // how badly will it shock you?
-
-/obj/machinery/Initialize(mapload)
- if(!armor)
- armor = list(melee = 25, bullet = 10, laser = 10, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 70)
- . = ..()
- GLOB.machines += src
-
- if(use_power)
- myArea = get_area(src)
- if(!speed_process)
- START_PROCESSING(SSmachines, src)
- else
- START_PROCESSING(SSfastprocess, src)
-
- power_change()
-
-// gotta go fast
-/obj/machinery/makeSpeedProcess()
- if(speed_process)
- return
- speed_process = TRUE
- STOP_PROCESSING(SSmachines, src)
- START_PROCESSING(SSfastprocess, src)
-
-// gotta go slow
-/obj/machinery/makeNormalProcess()
- if(!speed_process)
- return
- speed_process = FALSE
- STOP_PROCESSING(SSfastprocess, src)
- START_PROCESSING(SSmachines, src)
-
-/obj/machinery/Destroy()
- if(myArea)
- myArea = null
- GLOB.machines.Remove(src)
- if(!speed_process)
- STOP_PROCESSING(SSmachines, src)
- else
- STOP_PROCESSING(SSfastprocess, src)
- return ..()
-
-/obj/machinery/proc/locate_machinery()
- return
-
-/obj/machinery/proc/set_frequency()
- return
-
-/obj/machinery/process() // If you dont use process or power why are you here
- return PROCESS_KILL
-
-/obj/machinery/proc/process_atmos() //If you dont use process why are you here
- return PROCESS_KILL
-
-/obj/machinery/emp_act(severity)
- if(use_power && !stat)
- use_power(7500/severity)
- new /obj/effect/temp_visual/emp(loc)
- ..()
+/*
+Overview:
+ Used to create objects that need a per step proc call. Default definition of 'New()'
+ stores a reference to src machine in global 'machines list'. Default definition
+ of 'Del' removes reference to src machine in global 'machines list'.
+
+Class Variables:
+ use_power (num)
+ current state of auto power use.
+ Possible Values:
+ 0 -- no auto power use
+ 1 -- machine is using power at its idle power level
+ 2 -- machine is using power at its active power level
+
+ active_power_usage (num)
+ Value for the amount of power to use when in active power mode
+
+ idle_power_usage (num)
+ Value for the amount of power to use when in idle power mode
+
+ power_channel (num)
+ What channel to draw from when drawing power for power mode
+ Possible Values:
+ EQUIP:0 -- Equipment Channel
+ LIGHT:2 -- Lighting Channel
+ ENVIRON:3 -- Environment Channel
+
+ component_parts (list)
+ A list of component parts of machine used by frame based machines.
+
+ uid (num)
+ Unique id of machine across all machines.
+
+ gl_uid (global num)
+ Next uid value in sequence
+
+ stat (bitflag)
+ Machine status bit flags.
+ Possible bit flags:
+ BROKEN:1 -- Machine is broken
+ NOPOWER:2 -- No power is being supplied to machine.
+ POWEROFF:4 -- tbd
+ MAINT:8 -- machine is currently under going maintenance.
+ EMPED:16 -- temporary broken by EMP pulse
+
+ manual (num)
+ Currently unused.
+
+Class Procs:
+ initialize() 'game/machinery/machine.dm'
+
+ Destroy() 'game/machinery/machine.dm'
+
+ auto_use_power() 'game/machinery/machine.dm'
+ This proc determines how power mode power is deducted by the machine.
+ 'auto_use_power()' is called by the 'master_controller' game_controller every
+ tick.
+
+ Return Value:
+ return:1 -- if object is powered
+ return:0 -- if object is not powered.
+
+ Default definition uses 'use_power', 'power_channel', 'active_power_usage',
+ 'idle_power_usage', 'powered()', and 'use_power()' implement behavior.
+
+ powered(chan = EQUIP) 'modules/power/power.dm'
+ Checks to see if area that contains the object has power available for power
+ channel given in 'chan'.
+
+ use_power(amount, chan=EQUIP, autocalled) 'modules/power/power.dm'
+ Deducts 'amount' from the power channel 'chan' of the area that contains the object.
+ If it's autocalled then everything is normal, if something else calls use_power we are going to
+ need to recalculate the power two ticks in a row.
+
+ power_change() 'modules/power/power.dm'
+ Called by the area that contains the object when ever that area under goes a
+ power state change (area runs out of power, or area channel is turned off).
+
+ RefreshParts() 'game/machinery/machine.dm'
+ Called to refresh the variables in the machine that are contributed to by parts
+ contained in the component_parts list. (example: glass and material amounts for
+ the autolathe)
+
+ Default definition does nothing.
+
+ assign_uid() 'game/machinery/machine.dm'
+ Called by machine to assign a value to the uid variable.
+
+ process() 'game/machinery/machine.dm'
+ Called by the 'master_controller' once per game tick for each machine that is listed in the 'machines' list.
+
+
+ Compiled by Aygar
+*/
+
+/obj/machinery
+ name = "machinery"
+ icon = 'icons/obj/stationobjs.dmi'
+ pressure_resistance = 15
+ max_integrity = 200
+ layer = BELOW_OBJ_LAYER
+ var/stat = 0
+ var/emagged = 0
+ var/use_power = IDLE_POWER_USE
+ //0 = dont run the auto
+ //1 = run auto, use idle
+ //2 = run auto, use active
+ var/idle_power_usage = 0
+ var/active_power_usage = 0
+ var/power_channel = EQUIP //EQUIP,ENVIRON or LIGHT
+ var/list/component_parts = null //list of all the parts used to build it, if made from certain kinds of frames.
+ var/uid
+ var/manual = 0
+ var/global/gl_uid = 1
+ var/custom_aghost_alerts=0
+ var/panel_open = 0
+ var/area/myArea
+ var/interact_offline = 0 // Can the machine be interacted with while de-powered.
+ var/use_log = list()
+ var/list/settagwhitelist = list()//WHITELIST OF VARIABLES THAT THE set_tag HREF CAN MODIFY, DON'T PUT SHIT YOU DON'T NEED ON HERE, AND IF YOU'RE GONNA USE set_tag (format_tag() proc), ADD TO THIS LIST.
+ atom_say_verb = "beeps"
+ var/siemens_strength = 0.7 // how badly will it shock you?
+
+/obj/machinery/Initialize(mapload)
+ if(!armor)
+ armor = list(melee = 25, bullet = 10, laser = 10, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 70)
+ . = ..()
+ GLOB.machines += src
+
+ if(use_power)
+ myArea = get_area(src)
+ if(!speed_process)
+ START_PROCESSING(SSmachines, src)
+ else
+ START_PROCESSING(SSfastprocess, src)
+
+ power_change()
+
+// gotta go fast
+/obj/machinery/makeSpeedProcess()
+ if(speed_process)
+ return
+ speed_process = TRUE
+ STOP_PROCESSING(SSmachines, src)
+ START_PROCESSING(SSfastprocess, src)
+
+// gotta go slow
+/obj/machinery/makeNormalProcess()
+ if(!speed_process)
+ return
+ speed_process = FALSE
+ STOP_PROCESSING(SSfastprocess, src)
+ START_PROCESSING(SSmachines, src)
+
+/obj/machinery/Destroy()
+ if(myArea)
+ myArea = null
+ GLOB.machines.Remove(src)
+ if(!speed_process)
+ STOP_PROCESSING(SSmachines, src)
+ else
+ STOP_PROCESSING(SSfastprocess, src)
+ return ..()
+
+/obj/machinery/proc/locate_machinery()
+ return
+
+/obj/machinery/proc/set_frequency()
+ return
+
+/obj/machinery/process() // If you dont use process or power why are you here
+ return PROCESS_KILL
+
+/obj/machinery/proc/process_atmos() //If you dont use process why are you here
+ return PROCESS_KILL
+
+/obj/machinery/emp_act(severity)
+ if(use_power && !stat)
+ use_power(7500/severity)
+ new /obj/effect/temp_visual/emp(loc)
+ ..()
/obj/machinery/default_welder_repair(mob/user, obj/item/I)
. = ..()
if(.)
stat &= ~BROKEN
-
-//sets the use_power var and then forces an area power update
-/obj/machinery/proc/update_use_power(var/new_use_power)
- use_power = new_use_power
-
-/obj/machinery/proc/auto_use_power()
- if(!powered(power_channel))
- return 0
- if(use_power == IDLE_POWER_USE)
- use_power(idle_power_usage,power_channel, 1)
- else if(use_power >= ACTIVE_POWER_USE)
- use_power(active_power_usage,power_channel, 1)
- return 1
-
-/obj/machinery/proc/multitool_topic(mob/user, list/href_list, obj/O)
- if("set_id" in href_list)
- if(!("id_tag" in vars))
- warning("set_id: [type] has no id_tag var.")
- var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, src:id_tag) as null|text),1,MAX_MESSAGE_LEN)
- if(newid)
- src:id_tag = newid
- return TRUE
- if("set_freq" in href_list)
- if(!("frequency" in vars))
- warning("set_freq: [type] has no frequency var.")
- return FALSE
- var/newfreq=src:frequency
- if(href_list["set_freq"]!="-1")
- newfreq=text2num(href_list["set_freq"])
- else
- newfreq = input(usr, "Specify a new frequency (GHz). Decimals assigned automatically.", src, src:frequency) as null|num
- if(newfreq)
- if(findtext(num2text(newfreq), "."))
- newfreq *= 10 // shift the decimal one place
- set_frequency(sanitize_frequency(newfreq, RADIO_LOW_FREQ, RADIO_HIGH_FREQ))
- return TRUE
- return FALSE
-
-/obj/machinery/proc/handle_multitool_topic(var/href, var/list/href_list, var/mob/user)
- if(!allowed(user))//no, not even HREF exploits
- return FALSE
- var/obj/item/multitool/P = get_multitool(usr)
- if(P && istype(P))
- var/update_mt_menu = FALSE
- if("set_tag" in href_list)
- if(!(href_list["set_tag"] in settagwhitelist))//I see you're trying Href exploits, I see you're failing, I SEE ADMIN WARNING. (seriously though, this is a powerfull HREF, I originally found this loophole, I'm not leaving it in on my PR)
- message_admins("set_tag HREF (var attempted to edit: [href_list["set_tag"]]) exploit attempted by [key_name_admin(user)] on [src] (JMP)")
- return FALSE
- if(!(href_list["set_tag"] in vars))
- to_chat(usr, "Something went wrong: Unable to find [href_list["set_tag"]] in vars!")
- return FALSE
- var/current_tag = vars[href_list["set_tag"]]
- var/newid = copytext(reject_bad_text(input(usr, "Specify the new value", src, current_tag) as null|text),1,MAX_MESSAGE_LEN)
- if(newid)
- vars[href_list["set_tag"]] = newid
- update_mt_menu = TRUE
-
- if("unlink" in href_list)
- var/idx = text2num(href_list["unlink"])
- if(!idx)
- return FALSE
-
- var/obj/O = getLink(idx)
- if(!O)
- return FALSE
- if(!canLink(O))
- to_chat(usr, "You can't link with that device.")
- return FALSE
-
- if(unlinkFrom(usr, O))
- to_chat(usr, "A green light flashes on \the [P], confirming the link was removed.")
- else
- to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when unlinking the two devices.")
- update_mt_menu = TRUE
-
- if("link" in href_list)
- var/obj/O = P.buffer
- if(!O)
- return FALSE
- if(!canLink(O,href_list))
- to_chat(usr, "You can't link with that device.")
- return FALSE
- if(isLinkedWith(O))
- to_chat(usr, "A red light flashes on \the [P]. The two devices are already linked.")
- return FALSE
-
- if(linkWith(usr, O, href_list))
- to_chat(usr, "A green light flashes on \the [P], confirming the link was added.")
- else
- to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when linking the two devices.")
- update_mt_menu = TRUE
-
- if("buffer" in href_list)
- P.buffer = src
- to_chat(usr, "A green light flashes, and the device appears in the multitool buffer.")
- update_mt_menu = TRUE
-
- if("flush" in href_list)
- to_chat(usr, "A green light flashes, and the device disappears from the multitool buffer.")
- P.buffer = null
- update_mt_menu = TRUE
-
- var/ret = multitool_topic(usr,href_list,P.buffer)
- if(ret)
- update_mt_menu = TRUE
-
- if(update_mt_menu)
- update_multitool_menu(usr)
- return TRUE
-
-/obj/machinery/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state = default_state)
- if(..(href, href_list, nowindow, state))
- return 1
-
- handle_multitool_topic(href,href_list,usr)
- add_fingerprint(usr)
- return 0
-
-/obj/machinery/proc/operable(var/additional_flags = 0)
- return !inoperable(additional_flags)
-
-/obj/machinery/proc/inoperable(var/additional_flags = 0)
- return (stat & (NOPOWER|BROKEN|additional_flags))
-
-/obj/machinery/CanUseTopic(var/mob/user)
- if(!interact_offline && (stat & (NOPOWER|BROKEN)))
- return STATUS_CLOSE
-
- return ..()
-
-/obj/machinery/CouldUseTopic(var/mob/user)
- ..()
- user.set_machine(src)
-
-/obj/machinery/CouldNotUseTopic(var/mob/user)
- usr.unset_machine()
-
-/obj/machinery/proc/dropContents()//putting for swarmers, occupent code commented out, someone can use later.
- var/turf/T = get_turf(src)
- for(var/atom/movable/AM in contents)
- AM.forceMove(T)
-
-////////////////////////////////////////////////////////////////////////////////////////////
-
-/obj/machinery/attack_ai(mob/user)
- if(isrobot(user))// For some reason attack_robot doesn't work
- var/mob/living/silicon/robot/R = user
- if(R.client && R.client.eye == R && !R.low_power_mode)// This is to stop robots from using cameras to remotely control machines; and from using machines when the borg has no power.
- return attack_hand(user)
- else
- return attack_hand(user)
-
-/obj/machinery/attack_hand(mob/user as mob)
- if(user.incapacitated())
- return TRUE
-
- if(!user.IsAdvancedToolUser())
- to_chat(user, "You don't have the dexterity to do this!")
- return TRUE
-
- if(ishuman(user))
- var/mob/living/carbon/human/H = user
- if(H.getBrainLoss() >= 60)
- visible_message("[H] stares cluelessly at [src] and drools.")
- return TRUE
- else if(prob(H.getBrainLoss()))
- to_chat(user, "You momentarily forget how to use [src].")
- return TRUE
-
- if(panel_open)
- add_fingerprint(user)
- return FALSE
-
- if(!interact_offline && stat & (NOPOWER|BROKEN|MAINT))
- return TRUE
-
- add_fingerprint(user)
-
- return ..()
-
-/obj/machinery/proc/is_operational()
- return !(stat & (NOPOWER|BROKEN|MAINT))
-
-/obj/machinery/CheckParts(list/parts_list)
- ..()
- RefreshParts()
-
-/obj/machinery/proc/RefreshParts() //Placeholder proc for machines that are built using frames.
- return
- return 0
-
-/obj/machinery/proc/assign_uid()
- uid = gl_uid
- gl_uid++
-
-/obj/machinery/deconstruct(disassembled = TRUE)
- if(!(flags & NODECONSTRUCT))
- on_deconstruction()
- if(component_parts && component_parts.len)
- spawn_frame(disassembled)
- for(var/obj/item/I in component_parts)
- I.forceMove(loc)
- component_parts.Cut()
- qdel(src)
-
-/obj/machinery/proc/spawn_frame(disassembled)
- var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(loc)
- . = M
- M.anchored = anchored
- if(!disassembled)
- M.obj_integrity = M.max_integrity * 0.5 //the frame is already half broken
- transfer_fingerprints_to(M)
- M.state = 2
- M.icon_state = "box_1"
-
-/obj/machinery/obj_break(damage_flag)
- if(!(flags & NODECONSTRUCT))
- stat |= BROKEN
-
+
+//sets the use_power var and then forces an area power update
+/obj/machinery/proc/update_use_power(var/new_use_power)
+ use_power = new_use_power
+
+/obj/machinery/proc/auto_use_power()
+ if(!powered(power_channel))
+ return 0
+ if(use_power == IDLE_POWER_USE)
+ use_power(idle_power_usage,power_channel, 1)
+ else if(use_power >= ACTIVE_POWER_USE)
+ use_power(active_power_usage,power_channel, 1)
+ return 1
+
+/obj/machinery/proc/multitool_topic(mob/user, list/href_list, obj/O)
+ if("set_id" in href_list)
+ if(!("id_tag" in vars))
+ warning("set_id: [type] has no id_tag var.")
+ var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, src:id_tag) as null|text),1,MAX_MESSAGE_LEN)
+ if(newid)
+ src:id_tag = newid
+ return TRUE
+ if("set_freq" in href_list)
+ if(!("frequency" in vars))
+ warning("set_freq: [type] has no frequency var.")
+ return FALSE
+ var/newfreq=src:frequency
+ if(href_list["set_freq"]!="-1")
+ newfreq=text2num(href_list["set_freq"])
+ else
+ newfreq = input(usr, "Specify a new frequency (GHz). Decimals assigned automatically.", src, src:frequency) as null|num
+ if(newfreq)
+ if(findtext(num2text(newfreq), "."))
+ newfreq *= 10 // shift the decimal one place
+ set_frequency(sanitize_frequency(newfreq, RADIO_LOW_FREQ, RADIO_HIGH_FREQ))
+ return TRUE
+ return FALSE
+
+/obj/machinery/proc/handle_multitool_topic(var/href, var/list/href_list, var/mob/user)
+ if(!allowed(user))//no, not even HREF exploits
+ return FALSE
+ var/obj/item/multitool/P = get_multitool(usr)
+ if(P && istype(P))
+ var/update_mt_menu = FALSE
+ if("set_tag" in href_list)
+ if(!(href_list["set_tag"] in settagwhitelist))//I see you're trying Href exploits, I see you're failing, I SEE ADMIN WARNING. (seriously though, this is a powerfull HREF, I originally found this loophole, I'm not leaving it in on my PR)
+ message_admins("set_tag HREF (var attempted to edit: [href_list["set_tag"]]) exploit attempted by [key_name_admin(user)] on [src] (JMP)")
+ return FALSE
+ if(!(href_list["set_tag"] in vars))
+ to_chat(usr, "Something went wrong: Unable to find [href_list["set_tag"]] in vars!")
+ return FALSE
+ var/current_tag = vars[href_list["set_tag"]]
+ var/newid = copytext(reject_bad_text(input(usr, "Specify the new value", src, current_tag) as null|text),1,MAX_MESSAGE_LEN)
+ if(newid)
+ vars[href_list["set_tag"]] = newid
+ update_mt_menu = TRUE
+
+ if("unlink" in href_list)
+ var/idx = text2num(href_list["unlink"])
+ if(!idx)
+ return FALSE
+
+ var/obj/O = getLink(idx)
+ if(!O)
+ return FALSE
+ if(!canLink(O))
+ to_chat(usr, "You can't link with that device.")
+ return FALSE
+
+ if(unlinkFrom(usr, O))
+ to_chat(usr, "A green light flashes on \the [P], confirming the link was removed.")
+ else
+ to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when unlinking the two devices.")
+ update_mt_menu = TRUE
+
+ if("link" in href_list)
+ var/obj/O = P.buffer
+ if(!O)
+ return FALSE
+ if(!canLink(O,href_list))
+ to_chat(usr, "You can't link with that device.")
+ return FALSE
+ if(isLinkedWith(O))
+ to_chat(usr, "A red light flashes on \the [P]. The two devices are already linked.")
+ return FALSE
+
+ if(linkWith(usr, O, href_list))
+ to_chat(usr, "A green light flashes on \the [P], confirming the link was added.")
+ else
+ to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when linking the two devices.")
+ update_mt_menu = TRUE
+
+ if("buffer" in href_list)
+ P.buffer = src
+ to_chat(usr, "A green light flashes, and the device appears in the multitool buffer.")
+ update_mt_menu = TRUE
+
+ if("flush" in href_list)
+ to_chat(usr, "A green light flashes, and the device disappears from the multitool buffer.")
+ P.buffer = null
+ update_mt_menu = TRUE
+
+ var/ret = multitool_topic(usr,href_list,P.buffer)
+ if(ret)
+ update_mt_menu = TRUE
+
+ if(update_mt_menu)
+ update_multitool_menu(usr)
+ return TRUE
+
+/obj/machinery/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state = default_state)
+ if(..(href, href_list, nowindow, state))
+ return 1
+
+ handle_multitool_topic(href,href_list,usr)
+ add_fingerprint(usr)
+ return 0
+
+/obj/machinery/proc/operable(var/additional_flags = 0)
+ return !inoperable(additional_flags)
+
+/obj/machinery/proc/inoperable(var/additional_flags = 0)
+ return (stat & (NOPOWER|BROKEN|additional_flags))
+
+/obj/machinery/CanUseTopic(var/mob/user)
+ if(!interact_offline && (stat & (NOPOWER|BROKEN)))
+ return STATUS_CLOSE
+
+ return ..()
+
+/obj/machinery/CouldUseTopic(var/mob/user)
+ ..()
+ user.set_machine(src)
+
+/obj/machinery/CouldNotUseTopic(var/mob/user)
+ usr.unset_machine()
+
+/obj/machinery/proc/dropContents()//putting for swarmers, occupent code commented out, someone can use later.
+ var/turf/T = get_turf(src)
+ for(var/atom/movable/AM in contents)
+ AM.forceMove(T)
+
+////////////////////////////////////////////////////////////////////////////////////////////
+
+/obj/machinery/attack_ai(mob/user)
+ if(isrobot(user))// For some reason attack_robot doesn't work
+ var/mob/living/silicon/robot/R = user
+ if(R.client && R.client.eye == R && !R.low_power_mode)// This is to stop robots from using cameras to remotely control machines; and from using machines when the borg has no power.
+ return attack_hand(user)
+ else
+ return attack_hand(user)
+
+/obj/machinery/attack_hand(mob/user as mob)
+ if(user.incapacitated())
+ return TRUE
+
+ if(!user.IsAdvancedToolUser())
+ to_chat(user, "You don't have the dexterity to do this!")
+ return TRUE
+
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(H.getBrainLoss() >= 60)
+ visible_message("[H] stares cluelessly at [src] and drools.")
+ return TRUE
+ else if(prob(H.getBrainLoss()))
+ to_chat(user, "You momentarily forget how to use [src].")
+ return TRUE
+
+ if(panel_open)
+ add_fingerprint(user)
+ return FALSE
+
+ if(!interact_offline && stat & (NOPOWER|BROKEN|MAINT))
+ return TRUE
+
+ add_fingerprint(user)
+
+ return ..()
+
+/obj/machinery/proc/is_operational()
+ return !(stat & (NOPOWER|BROKEN|MAINT))
+
+/obj/machinery/CheckParts(list/parts_list)
+ ..()
+ RefreshParts()
+
+/obj/machinery/proc/RefreshParts() //Placeholder proc for machines that are built using frames.
+ return
+ return 0
+
+/obj/machinery/proc/assign_uid()
+ uid = gl_uid
+ gl_uid++
+
+/obj/machinery/deconstruct(disassembled = TRUE)
+ if(!(flags & NODECONSTRUCT))
+ on_deconstruction()
+ if(component_parts && component_parts.len)
+ spawn_frame(disassembled)
+ for(var/obj/item/I in component_parts)
+ I.forceMove(loc)
+ component_parts.Cut()
+ qdel(src)
+
+/obj/machinery/proc/spawn_frame(disassembled)
+ var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(loc)
+ . = M
+ M.anchored = anchored
+ if(!disassembled)
+ M.obj_integrity = M.max_integrity * 0.5 //the frame is already half broken
+ transfer_fingerprints_to(M)
+ M.state = 2
+ M.icon_state = "box_1"
+
+/obj/machinery/obj_break(damage_flag)
+ if(!(flags & NODECONSTRUCT))
+ stat |= BROKEN
+
/obj/machinery/proc/default_deconstruction_crowbar(user, obj/item/I, ignore_panel = 0)
if(I.tool_behaviour != TOOL_CROWBAR)
return FALSE
@@ -420,180 +420,180 @@ Class Procs:
if(!I.use_tool(src, user, 0, volume = 0))
return FALSE
if(!(flags & NODECONSTRUCT))
- if(!panel_open)
- panel_open = 1
- icon_state = icon_state_open
- to_chat(user, "You open the maintenance hatch of [src].")
- else
- panel_open = 0
- icon_state = icon_state_closed
- to_chat(user, "You close the maintenance hatch of [src].")
+ if(!panel_open)
+ panel_open = 1
+ icon_state = icon_state_open
+ to_chat(user, "You open the maintenance hatch of [src].")
+ else
+ panel_open = 0
+ icon_state = icon_state_closed
+ to_chat(user, "You close the maintenance hatch of [src].")
I.play_tool_sound(user, I.tool_volume)
- return 1
- return 0
-
+ return 1
+ return 0
+
/obj/machinery/proc/default_change_direction_wrench(mob/user, obj/item/I)
if(I.tool_behaviour != TOOL_WRENCH)
return FALSE
if(!I.use_tool(src, user, 0, volume = 0))
return FALSE
if(panel_open)
- dir = turn(dir,-90)
- to_chat(user, "You rotate [src].")
+ dir = turn(dir,-90)
+ to_chat(user, "You rotate [src].")
I.play_tool_sound(user, I.tool_volume)
return TRUE
return FALSE
-
+
/obj/machinery/default_unfasten_wrench(mob/user, obj/item/I, time)
. = ..()
if(.)
power_change()
-
-/obj/machinery/proc/exchange_parts(mob/user, obj/item/storage/part_replacer/W)
- var/shouldplaysound = 0
- if((flags & NODECONSTRUCT))
- return FALSE
- if(istype(W) && component_parts)
- if(panel_open || W.works_from_distance)
- var/obj/item/circuitboard/CB = locate(/obj/item/circuitboard) in component_parts
- var/P
- if(W.works_from_distance)
- to_chat(user, display_parts(user))
- for(var/obj/item/stock_parts/A in component_parts)
- for(var/D in CB.req_components)
- if(ispath(A.type, D))
- P = D
- break
- for(var/obj/item/stock_parts/B in W.contents)
- if(istype(B, P) && istype(A, P))
- if(B.rating > A.rating)
- W.remove_from_storage(B, src)
- W.handle_item_insertion(A, 1)
- component_parts -= A
- component_parts += B
- B.loc = null
- to_chat(user, "[A.name] replaced with [B.name].")
- shouldplaysound = 1
- break
- RefreshParts()
- else
- to_chat(user, display_parts(user))
- if(shouldplaysound)
- W.play_rped_sound()
- return 1
- else
- return 0
-
-/obj/machinery/proc/display_parts(mob/user)
- . = list("Following parts detected in the machine:")
- for(var/obj/item/C in component_parts)
- . += "[bicon(C)] [C.name]"
- . = jointext(., "\n")
-
-/obj/machinery/examine(mob/user)
- . = ..()
- if(stat & BROKEN)
- . += "It looks broken and non-functional."
- if(!(resistance_flags & INDESTRUCTIBLE))
- if(resistance_flags & ON_FIRE)
- . += "It's on fire!"
- var/healthpercent = (obj_integrity/max_integrity) * 100
- switch(healthpercent)
- if(50 to 99)
- . += "It looks slightly damaged."
- if(25 to 50)
- . += "It appears heavily damaged."
- if(0 to 25)
- . += "It's falling apart!"
- if(user.research_scanner && component_parts)
- . += display_parts(user)
-
-/obj/machinery/proc/on_assess_perp(mob/living/carbon/human/perp)
- return 0
-
-/obj/machinery/proc/is_assess_emagged()
- return emagged
-
-/obj/machinery/proc/assess_perp(mob/living/carbon/human/perp, var/check_access, var/auth_weapons, var/check_records, var/check_arrest)
- var/threatcount = 0 //the integer returned
-
- if(is_assess_emagged())
- return 10 //if emagged, always return 10.
-
- threatcount += on_assess_perp(perp)
- if(threatcount >= 10)
- return threatcount
-
- //Agent cards lower threatlevel.
- var/obj/item/card/id/id = GetIdCard(perp)
- if(id && istype(id, /obj/item/card/id/syndicate))
- threatcount -= 2
- // A proper CentCom id is hard currency.
- else if(id && istype(id, /obj/item/card/id/centcom))
- threatcount -= 2
-
- if(check_access && !allowed(perp))
- threatcount += 4
-
- if(auth_weapons && !allowed(perp))
- if(istype(perp.l_hand, /obj/item/gun) || istype(perp.l_hand, /obj/item/melee))
- threatcount += 4
-
- if(istype(perp.r_hand, /obj/item/gun) || istype(perp.r_hand, /obj/item/melee))
- threatcount += 4
-
- if(istype(perp.belt, /obj/item/gun) || istype(perp.belt, /obj/item/melee))
- threatcount += 2
-
- if(!ishumanbasic(perp)) //beepsky so racist.
- threatcount += 2
-
- if(check_records || check_arrest)
- var/perpname = perp.get_visible_name(TRUE)
-
- var/datum/data/record/R = find_security_record("name", perpname)
- if(check_records && !R)
- threatcount += 4
-
- if(check_arrest && R && (R.fields["criminal"] == "*Arrest*"))
- threatcount += 4
-
- return threatcount
-
-
-/obj/machinery/proc/shock(mob/user, prb)
- if(inoperable())
- return FALSE
- if(!prob(prb))
- return FALSE
- do_sparks(5, 1, src)
- if(electrocute_mob(user, get_area(src), src, siemens_strength, TRUE))
- return TRUE
- return FALSE
-
-//called on machinery construction (i.e from frame to machinery) but not on initialization
-/obj/machinery/proc/on_construction()
- return
-
-/obj/machinery/proc/on_deconstruction()
- return
-
-/obj/machinery/proc/can_be_overridden()
- . = 1
-
-/obj/machinery/tesla_act(power, explosive = FALSE)
- ..()
- if(prob(85) && explosive)
- explosion(loc, 1, 2, 4, flame_range = 2, adminlog = 0, smoke = 0)
- else if(prob(50))
- emp_act(EMP_LIGHT)
- else
- ex_act(EXPLODE_HEAVY)
-
-/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8
- var/md5 = md5(AM.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot.
- for (var/i in 1 to 32)
- . += hex2num(md5[i])
- . = . % 9
- AM.pixel_x = -8 + ((.%3)*8)
- AM.pixel_y = -8 + (round( . / 3)*8)
+
+/obj/machinery/proc/exchange_parts(mob/user, obj/item/storage/part_replacer/W)
+ var/shouldplaysound = 0
+ if((flags & NODECONSTRUCT))
+ return FALSE
+ if(istype(W) && component_parts)
+ if(panel_open || W.works_from_distance)
+ var/obj/item/circuitboard/CB = locate(/obj/item/circuitboard) in component_parts
+ var/P
+ if(W.works_from_distance)
+ to_chat(user, display_parts(user))
+ for(var/obj/item/stock_parts/A in component_parts)
+ for(var/D in CB.req_components)
+ if(ispath(A.type, D))
+ P = D
+ break
+ for(var/obj/item/stock_parts/B in W.contents)
+ if(istype(B, P) && istype(A, P))
+ if(B.rating > A.rating)
+ W.remove_from_storage(B, src)
+ W.handle_item_insertion(A, 1)
+ component_parts -= A
+ component_parts += B
+ B.loc = null
+ to_chat(user, "[A.name] replaced with [B.name].")
+ shouldplaysound = 1
+ break
+ RefreshParts()
+ else
+ to_chat(user, display_parts(user))
+ if(shouldplaysound)
+ W.play_rped_sound()
+ return 1
+ else
+ return 0
+
+/obj/machinery/proc/display_parts(mob/user)
+ . = list("Following parts detected in the machine:")
+ for(var/obj/item/C in component_parts)
+ . += "[bicon(C)] [C.name]"
+ . = jointext(., "\n")
+
+/obj/machinery/examine(mob/user)
+ . = ..()
+ if(stat & BROKEN)
+ . += "It looks broken and non-functional."
+ if(!(resistance_flags & INDESTRUCTIBLE))
+ if(resistance_flags & ON_FIRE)
+ . += "It's on fire!"
+ var/healthpercent = (obj_integrity/max_integrity) * 100
+ switch(healthpercent)
+ if(50 to 99)
+ . += "It looks slightly damaged."
+ if(25 to 50)
+ . += "It appears heavily damaged."
+ if(0 to 25)
+ . += "It's falling apart!"
+ if(user.research_scanner && component_parts)
+ . += display_parts(user)
+
+/obj/machinery/proc/on_assess_perp(mob/living/carbon/human/perp)
+ return 0
+
+/obj/machinery/proc/is_assess_emagged()
+ return emagged
+
+/obj/machinery/proc/assess_perp(mob/living/carbon/human/perp, var/check_access, var/auth_weapons, var/check_records, var/check_arrest)
+ var/threatcount = 0 //the integer returned
+
+ if(is_assess_emagged())
+ return 10 //if emagged, always return 10.
+
+ threatcount += on_assess_perp(perp)
+ if(threatcount >= 10)
+ return threatcount
+
+ //Agent cards lower threatlevel.
+ var/obj/item/card/id/id = GetIdCard(perp)
+ if(id && istype(id, /obj/item/card/id/syndicate))
+ threatcount -= 2
+ // A proper CentCom id is hard currency.
+ else if(id && istype(id, /obj/item/card/id/centcom))
+ threatcount -= 2
+
+ if(check_access && !allowed(perp))
+ threatcount += 4
+
+ if(auth_weapons && !allowed(perp))
+ if(istype(perp.l_hand, /obj/item/gun) || istype(perp.l_hand, /obj/item/melee))
+ threatcount += 4
+
+ if(istype(perp.r_hand, /obj/item/gun) || istype(perp.r_hand, /obj/item/melee))
+ threatcount += 4
+
+ if(istype(perp.belt, /obj/item/gun) || istype(perp.belt, /obj/item/melee))
+ threatcount += 2
+
+ if(!ishumanbasic(perp)) //beepsky so racist.
+ threatcount += 2
+
+ if(check_records || check_arrest)
+ var/perpname = perp.get_visible_name(TRUE)
+
+ var/datum/data/record/R = find_security_record("name", perpname)
+ if(check_records && !R)
+ threatcount += 4
+
+ if(check_arrest && R && (R.fields["criminal"] == "*Arrest*"))
+ threatcount += 4
+
+ return threatcount
+
+
+/obj/machinery/proc/shock(mob/user, prb)
+ if(inoperable())
+ return FALSE
+ if(!prob(prb))
+ return FALSE
+ do_sparks(5, 1, src)
+ if(electrocute_mob(user, get_area(src), src, siemens_strength, TRUE))
+ return TRUE
+ return FALSE
+
+//called on machinery construction (i.e from frame to machinery) but not on initialization
+/obj/machinery/proc/on_construction()
+ return
+
+/obj/machinery/proc/on_deconstruction()
+ return
+
+/obj/machinery/proc/can_be_overridden()
+ . = 1
+
+/obj/machinery/tesla_act(power, explosive = FALSE)
+ ..()
+ if(prob(85) && explosive)
+ explosion(loc, 1, 2, 4, flame_range = 2, adminlog = 0, smoke = 0)
+ else if(prob(50))
+ emp_act(EMP_LIGHT)
+ else
+ ex_act(EXPLODE_HEAVY)
+
+/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8
+ var/md5 = md5(AM.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot.
+ for (var/i in 1 to 32)
+ . += hex2num(md5[i])
+ . = . % 9
+ AM.pixel_x = -8 + ((.%3)*8)
+ AM.pixel_y = -8 + (round( . / 3)*8)
diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm
index f4a8dace06e..2595e328218 100644
--- a/code/modules/power/singularity/emitter.dm
+++ b/code/modules/power/singularity/emitter.dm
@@ -1,323 +1,323 @@
-/obj/machinery/power/emitter
- name = "Emitter"
- desc = "A heavy duty industrial laser"
- icon = 'icons/obj/singularity.dmi'
- icon_state = "emitter"
- anchored = 0
- density = 1
+/obj/machinery/power/emitter
+ name = "Emitter"
+ desc = "A heavy duty industrial laser"
+ icon = 'icons/obj/singularity.dmi'
+ icon_state = "emitter"
+ anchored = 0
+ density = 1
req_access = list(ACCESS_ENGINE_EQUIP)
-
- use_power = NO_POWER_USE
- idle_power_usage = 10
- active_power_usage = 300
-
- var/active = 0
- var/powered = 0
- var/fire_delay = 100
- var/maximum_fire_delay = 100
- var/minimum_fire_delay = 20
- var/last_shot = 0
- var/shot_number = 0
- var/state = 0
- var/locked = 0
-
- var/frequency = 0
- var/id_tag = null
- var/projectile_type = /obj/item/projectile/beam/emitter
- var/projectile_sound = 'sound/weapons/emitter.ogg'
- var/datum/radio_frequency/radio_connection
- var/datum/effect_system/spark_spread/sparks
-
-/obj/machinery/power/emitter/Initialize(mapload)
- . = ..()
- component_parts = list()
- component_parts += new /obj/item/circuitboard/emitter(null)
- component_parts += new /obj/item/stock_parts/micro_laser(null)
- component_parts += new /obj/item/stock_parts/manipulator(null)
- RefreshParts()
- if(state == 2 && anchored)
- connect_to_network()
- sparks = new
- sparks.attach(src)
- sparks.set_up(5, 1, src)
- if(frequency)
- set_frequency(frequency)
-
-/obj/machinery/power/emitter/RefreshParts()
- var/max_firedelay = 120
- var/firedelay = 120
- var/min_firedelay = 24
- var/power_usage = 350
- for(var/obj/item/stock_parts/micro_laser/L in component_parts)
- max_firedelay -= 20 * L.rating
- min_firedelay -= 4 * L.rating
- firedelay -= 20 * L.rating
- maximum_fire_delay = max_firedelay
- minimum_fire_delay = min_firedelay
- fire_delay = firedelay
- for(var/obj/item/stock_parts/manipulator/M in component_parts)
- power_usage -= 50 * M.rating
- active_power_usage = power_usage
-
- //Radio remote control
-/obj/machinery/power/emitter/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
-
-
-/obj/machinery/power/emitter/verb/rotate()
- set name = "Rotate"
- set category = "Object"
- set src in oview(1)
-
- if(src.anchored || usr:stat)
- to_chat(usr, "It is fastened to the floor!")
- return 0
- src.dir = turn(src.dir, 90)
- return 1
-
-/obj/machinery/power/emitter/AltClick(mob/user)
- if(user.incapacitated())
- to_chat(user, "You can't do that right now!")
- return
- if(!Adjacent(user))
- return
- rotate()
-
-/obj/machinery/power/emitter/multitool_menu(var/mob/user,var/obj/item/multitool/P)
- return {"
-
- "}
-
-/obj/machinery/power/emitter/receive_signal(datum/signal/signal)
- if(!signal.data["tag"] || (signal.data["tag"] != id_tag))
- return 0
-
- var/on=0
- switch(signal.data["command"])
- if("on")
- on=1
-
- if("off")
- on=0
-
- if("set")
- on = signal.data["state"] > 0
-
- if("toggle")
- on = !active
-
- if(anchored && state == 2 && on != active)
- active=on
- var/statestr=on?"on":"off"
- // Spammy message_admins("Emitter turned [statestr] by radio signal ([signal.data["command"]] @ [frequency]) in [formatJumpTo(src)]",0,1)
- log_game("Emitter turned [statestr] by radio signal ([signal.data["command"]] @ [frequency]) in ([x], [y], [z]) AAC prints: [jointext(signal.data["hiddenprints"], "")]")
- investigate_log("turned [statestr] by radio signal ([signal.data["command"]] @ [frequency]) AAC prints: [jointext(signal.data["hiddenprints"], "")]","singulo")
- update_icon()
-
-/obj/machinery/power/emitter/Destroy()
- if(SSradio)
- SSradio.remove_object(src, frequency)
- radio_connection = null
- msg_admin_attack("Emitter deleted at ([x],[y],[z] - [ADMIN_JMP(src)])", ATKLOG_FEW)
- log_game("Emitter deleted at ([x],[y],[z])")
- investigate_log("deleted at ([x],[y],[z])","singulo")
- QDEL_NULL(sparks)
- return ..()
-
-/obj/machinery/power/emitter/update_icon()
- if(active && powernet && avail(active_power_usage))
- icon_state = "emitter_+a"
- else
- icon_state = "emitter"
-
-
-/obj/machinery/power/emitter/attack_hand(mob/user as mob)
- src.add_fingerprint(user)
- if(state == 2)
- if(!powernet)
- to_chat(user, "The emitter isn't connected to a wire.")
- return 1
- if(!src.locked)
- if(src.active==1)
- src.active = 0
- to_chat(user, "You turn off the [src].")
- message_admins("Emitter turned off by [key_name_admin(user)] in ([x], [y], [z] - JMP)",0,1)
- log_game("Emitter turned off by [key_name(user)] in [x], [y], [z]")
- investigate_log("turned off by [key_name(usr)]","singulo")
- else
- src.active = 1
- to_chat(user, "You turn on the [src].")
- src.shot_number = 0
- src.fire_delay = maximum_fire_delay
- message_admins("Emitter turned on by [key_name_admin(user)] in ([x], [y], [z] - JMP)",0,1)
- log_game("Emitter turned on by [key_name(user)] in [x], [y], [z]")
- investigate_log("turned on by [key_name(usr)]","singulo")
- update_icon()
- else
- to_chat(user, "The controls are locked!")
- else
- to_chat(user, "The [src] needs to be firmly secured to the floor first.")
- return 1
-
-
-/obj/machinery/power/emitter/emp_act(var/severity)//Emitters are hardened but still might have issues
-// add_load(1000)
-/* if((severity == 1)&&prob(1)&&prob(1))
- if(src.active)
- src.active = 0
- src.use_power = IDLE_POWER_USE */
- return 1
-
-/obj/machinery/power/emitter/attack_animal(mob/living/simple_animal/M)
- if(ismegafauna(M) && anchored)
- state = 0
- anchored = FALSE
- M.visible_message("[M] rips [src] free from its moorings!")
- else
- ..()
- if(!anchored)
- step(src, get_dir(M, src))
-
-/obj/machinery/power/emitter/process()
- if(stat & (BROKEN))
- return
- if(src.state != 2 || (!powernet && active_power_usage))
- src.active = 0
- update_icon()
- return
- if(active == TRUE)
- if(!active_power_usage || surplus() >= active_power_usage)
- add_load(active_power_usage)
- if(!powered)
- powered = 1
- update_icon()
- investigate_log("regained power and turned on","singulo")
- else
- if(powered)
- powered = 0
- update_icon()
- investigate_log("lost power and turned off","singulo")
- return
-
- if(!check_delay())
- return FALSE
- fire_beam()
-
-/obj/machinery/power/emitter/proc/check_delay()
- if((last_shot + fire_delay) <= world.time)
- return TRUE
- return FALSE
-
-/obj/machinery/power/emitter/proc/fire_beam()
- var/obj/item/projectile/P = new projectile_type(get_turf(src))
- playsound(get_turf(src), projectile_sound, 50, TRUE)
- if(prob(35))
- sparks.start()
- switch(dir)
- if(NORTH)
- P.yo = 20
- P.xo = 0
- if(NORTHEAST)
- P.yo = 20
- P.xo = 20
- if(EAST)
- P.yo = 0
- P.xo = 20
- if(SOUTHEAST)
- P.yo = -20
- P.xo = 20
- if(WEST)
- P.yo = 0
- P.xo = -20
- if(SOUTHWEST)
- P.yo = -20
- P.xo = -20
- if(NORTHWEST)
- P.yo = 20
- P.xo = -20
- else // Any other
- P.yo = -20
- P.xo = 0
-
- last_shot = world.time
- if(shot_number < 3)
- fire_delay = 20
- shot_number ++
- else
- fire_delay = rand(minimum_fire_delay, maximum_fire_delay)
- shot_number = 0
- P.setDir(dir)
- P.starting = loc
- P.Angle = null
- P.fire()
- return P
-
-/obj/machinery/power/emitter/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/multitool))
- update_multitool_menu(user)
- return 1
-
- if(istype(W, /obj/item/wrench))
- if(active)
- to_chat(user, "Turn off the [src] first.")
- return
- switch(state)
- if(0)
- state = 1
- playsound(src.loc, W.usesound, 75, 1)
- user.visible_message("[user.name] secures [src.name] to the floor.", \
- "You secure the external reinforcing bolts to the floor.", \
- "You hear a ratchet")
- src.anchored = 1
- if(1)
- state = 0
- playsound(src.loc,W.usesound, 75, 1)
- user.visible_message("[user.name] unsecures [src.name] reinforcing bolts from the floor.", \
- "You undo the external reinforcing bolts.", \
- "You hear a ratchet")
- src.anchored = 0
- if(2)
- to_chat(user, "The [src.name] needs to be unwelded from the floor.")
- return
-
- if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda))
- if(emagged)
- to_chat(user, "The lock seems to be broken")
- return
- if(src.allowed(user))
- if(active)
- src.locked = !src.locked
- to_chat(user, "The controls are now [src.locked ? "locked." : "unlocked."]")
- else
- src.locked = 0 //just in case it somehow gets locked
- to_chat(user, "The controls can only be locked when the [src] is online")
- else
- to_chat(user, "Access denied.")
- return
-
- if(default_deconstruction_screwdriver(user, "emitter_open", "emitter", W))
- return
-
- if(exchange_parts(user, W))
- return
-
+
+ use_power = NO_POWER_USE
+ idle_power_usage = 10
+ active_power_usage = 300
+
+ var/active = 0
+ var/powered = 0
+ var/fire_delay = 100
+ var/maximum_fire_delay = 100
+ var/minimum_fire_delay = 20
+ var/last_shot = 0
+ var/shot_number = 0
+ var/state = 0
+ var/locked = 0
+
+ var/frequency = 0
+ var/id_tag = null
+ var/projectile_type = /obj/item/projectile/beam/emitter
+ var/projectile_sound = 'sound/weapons/emitter.ogg'
+ var/datum/radio_frequency/radio_connection
+ var/datum/effect_system/spark_spread/sparks
+
+/obj/machinery/power/emitter/Initialize(mapload)
+ . = ..()
+ component_parts = list()
+ component_parts += new /obj/item/circuitboard/emitter(null)
+ component_parts += new /obj/item/stock_parts/micro_laser(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ RefreshParts()
+ if(state == 2 && anchored)
+ connect_to_network()
+ sparks = new
+ sparks.attach(src)
+ sparks.set_up(5, 1, src)
+ if(frequency)
+ set_frequency(frequency)
+
+/obj/machinery/power/emitter/RefreshParts()
+ var/max_firedelay = 120
+ var/firedelay = 120
+ var/min_firedelay = 24
+ var/power_usage = 350
+ for(var/obj/item/stock_parts/micro_laser/L in component_parts)
+ max_firedelay -= 20 * L.rating
+ min_firedelay -= 4 * L.rating
+ firedelay -= 20 * L.rating
+ maximum_fire_delay = max_firedelay
+ minimum_fire_delay = min_firedelay
+ fire_delay = firedelay
+ for(var/obj/item/stock_parts/manipulator/M in component_parts)
+ power_usage -= 50 * M.rating
+ active_power_usage = power_usage
+
+ //Radio remote control
+/obj/machinery/power/emitter/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ if(frequency)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
+
+
+/obj/machinery/power/emitter/verb/rotate()
+ set name = "Rotate"
+ set category = "Object"
+ set src in oview(1)
+
+ if(src.anchored || usr:stat)
+ to_chat(usr, "It is fastened to the floor!")
+ return 0
+ src.dir = turn(src.dir, 90)
+ return 1
+
+/obj/machinery/power/emitter/AltClick(mob/user)
+ if(user.incapacitated())
+ to_chat(user, "You can't do that right now!")
+ return
+ if(!Adjacent(user))
+ return
+ rotate()
+
+/obj/machinery/power/emitter/multitool_menu(var/mob/user,var/obj/item/multitool/P)
+ return {"
+
+ "}
+
+/obj/machinery/power/emitter/receive_signal(datum/signal/signal)
+ if(!signal.data["tag"] || (signal.data["tag"] != id_tag))
+ return 0
+
+ var/on=0
+ switch(signal.data["command"])
+ if("on")
+ on=1
+
+ if("off")
+ on=0
+
+ if("set")
+ on = signal.data["state"] > 0
+
+ if("toggle")
+ on = !active
+
+ if(anchored && state == 2 && on != active)
+ active=on
+ var/statestr=on?"on":"off"
+ // Spammy message_admins("Emitter turned [statestr] by radio signal ([signal.data["command"]] @ [frequency]) in [formatJumpTo(src)]",0,1)
+ log_game("Emitter turned [statestr] by radio signal ([signal.data["command"]] @ [frequency]) in ([x], [y], [z]) AAC prints: [jointext(signal.data["hiddenprints"], "")]")
+ investigate_log("turned [statestr] by radio signal ([signal.data["command"]] @ [frequency]) AAC prints: [jointext(signal.data["hiddenprints"], "")]","singulo")
+ update_icon()
+
+/obj/machinery/power/emitter/Destroy()
+ if(SSradio)
+ SSradio.remove_object(src, frequency)
+ radio_connection = null
+ msg_admin_attack("Emitter deleted at ([x],[y],[z] - [ADMIN_JMP(src)])", ATKLOG_FEW)
+ log_game("Emitter deleted at ([x],[y],[z])")
+ investigate_log("deleted at ([x],[y],[z])","singulo")
+ QDEL_NULL(sparks)
+ return ..()
+
+/obj/machinery/power/emitter/update_icon()
+ if(active && powernet && avail(active_power_usage))
+ icon_state = "emitter_+a"
+ else
+ icon_state = "emitter"
+
+
+/obj/machinery/power/emitter/attack_hand(mob/user as mob)
+ src.add_fingerprint(user)
+ if(state == 2)
+ if(!powernet)
+ to_chat(user, "The emitter isn't connected to a wire.")
+ return 1
+ if(!src.locked)
+ if(src.active==1)
+ src.active = 0
+ to_chat(user, "You turn off the [src].")
+ message_admins("Emitter turned off by [key_name_admin(user)] in ([x], [y], [z] - JMP)",0,1)
+ log_game("Emitter turned off by [key_name(user)] in [x], [y], [z]")
+ investigate_log("turned off by [key_name(usr)]","singulo")
+ else
+ src.active = 1
+ to_chat(user, "You turn on the [src].")
+ src.shot_number = 0
+ src.fire_delay = maximum_fire_delay
+ message_admins("Emitter turned on by [key_name_admin(user)] in ([x], [y], [z] - JMP)",0,1)
+ log_game("Emitter turned on by [key_name(user)] in [x], [y], [z]")
+ investigate_log("turned on by [key_name(usr)]","singulo")
+ update_icon()
+ else
+ to_chat(user, "The controls are locked!")
+ else
+ to_chat(user, "The [src] needs to be firmly secured to the floor first.")
+ return 1
+
+
+/obj/machinery/power/emitter/emp_act(var/severity)//Emitters are hardened but still might have issues
+// add_load(1000)
+/* if((severity == 1)&&prob(1)&&prob(1))
+ if(src.active)
+ src.active = 0
+ src.use_power = IDLE_POWER_USE */
+ return 1
+
+/obj/machinery/power/emitter/attack_animal(mob/living/simple_animal/M)
+ if(ismegafauna(M) && anchored)
+ state = 0
+ anchored = FALSE
+ M.visible_message("[M] rips [src] free from its moorings!")
+ else
+ ..()
+ if(!anchored)
+ step(src, get_dir(M, src))
+
+/obj/machinery/power/emitter/process()
+ if(stat & (BROKEN))
+ return
+ if(src.state != 2 || (!powernet && active_power_usage))
+ src.active = 0
+ update_icon()
+ return
+ if(active == TRUE)
+ if(!active_power_usage || surplus() >= active_power_usage)
+ add_load(active_power_usage)
+ if(!powered)
+ powered = 1
+ update_icon()
+ investigate_log("regained power and turned on","singulo")
+ else
+ if(powered)
+ powered = 0
+ update_icon()
+ investigate_log("lost power and turned off","singulo")
+ return
+
+ if(!check_delay())
+ return FALSE
+ fire_beam()
+
+/obj/machinery/power/emitter/proc/check_delay()
+ if((last_shot + fire_delay) <= world.time)
+ return TRUE
+ return FALSE
+
+/obj/machinery/power/emitter/proc/fire_beam()
+ var/obj/item/projectile/P = new projectile_type(get_turf(src))
+ playsound(get_turf(src), projectile_sound, 50, TRUE)
+ if(prob(35))
+ sparks.start()
+ switch(dir)
+ if(NORTH)
+ P.yo = 20
+ P.xo = 0
+ if(NORTHEAST)
+ P.yo = 20
+ P.xo = 20
+ if(EAST)
+ P.yo = 0
+ P.xo = 20
+ if(SOUTHEAST)
+ P.yo = -20
+ P.xo = 20
+ if(WEST)
+ P.yo = 0
+ P.xo = -20
+ if(SOUTHWEST)
+ P.yo = -20
+ P.xo = -20
+ if(NORTHWEST)
+ P.yo = 20
+ P.xo = -20
+ else // Any other
+ P.yo = -20
+ P.xo = 0
+
+ last_shot = world.time
+ if(shot_number < 3)
+ fire_delay = 20
+ shot_number ++
+ else
+ fire_delay = rand(minimum_fire_delay, maximum_fire_delay)
+ shot_number = 0
+ P.setDir(dir)
+ P.starting = loc
+ P.Angle = null
+ P.fire()
+ return P
+
+/obj/machinery/power/emitter/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/multitool))
+ update_multitool_menu(user)
+ return 1
+
+ if(istype(W, /obj/item/wrench))
+ if(active)
+ to_chat(user, "Turn off the [src] first.")
+ return
+ switch(state)
+ if(0)
+ state = 1
+ playsound(src.loc, W.usesound, 75, 1)
+ user.visible_message("[user.name] secures [src.name] to the floor.", \
+ "You secure the external reinforcing bolts to the floor.", \
+ "You hear a ratchet")
+ src.anchored = 1
+ if(1)
+ state = 0
+ playsound(src.loc,W.usesound, 75, 1)
+ user.visible_message("[user.name] unsecures [src.name] reinforcing bolts from the floor.", \
+ "You undo the external reinforcing bolts.", \
+ "You hear a ratchet")
+ src.anchored = 0
+ if(2)
+ to_chat(user, "The [src.name] needs to be unwelded from the floor.")
+ return
+
+ if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda))
+ if(emagged)
+ to_chat(user, "The lock seems to be broken")
+ return
+ if(src.allowed(user))
+ if(active)
+ src.locked = !src.locked
+ to_chat(user, "The controls are now [src.locked ? "locked." : "unlocked."]")
+ else
+ src.locked = 0 //just in case it somehow gets locked
+ to_chat(user, "The controls can only be locked when the [src] is online")
+ else
+ to_chat(user, "Access denied.")
+ return
+
+ if(default_deconstruction_screwdriver(user, "emitter_open", "emitter", W))
+ return
+
+ if(exchange_parts(user, W))
+ return
+
if(default_deconstruction_crowbar(user, W))
- return
-
- return ..()
-
-/obj/machinery/power/emitter/emag_act(var/mob/living/user as mob)
- if(!emagged)
- locked = 0
- emagged = 1
- if(user)
- user.visible_message("[user.name] emags the [src.name].","You short out the lock.")
+ return
+
+ return ..()
+
+/obj/machinery/power/emitter/emag_act(var/mob/living/user as mob)
+ if(!emagged)
+ locked = 0
+ emagged = 1
+ if(user)
+ user.visible_message("[user.name] emags the [src.name].","You short out the lock.")
/obj/machinery/power/emitter/welder_act(mob/user, obj/item/I)