From 59680db1861629804c9ca0d6ddef30bb2588924b Mon Sep 17 00:00:00 2001 From: SteelSlayer Date: Wed, 18 Mar 2020 12:56:15 -0500 Subject: [PATCH] CRLF to LF --- .../components/binary_devices/dp_vent_pump.dm | 538 ++--- .../components/binary_devices/passive_gate.dm | 384 +-- .../components/binary_devices/pump.dm | 522 ++--- .../components/binary_devices/volume_pump.dm | 514 ++-- .../components/trinary_devices/filter.dm | 534 ++--- code/game/machinery/alarm.dm | 2074 ++++++++--------- code/game/machinery/buttons.dm | 412 ++-- .../embedded_controller_base.dm | 174 +- code/game/machinery/lightswitch.dm | 332 +-- code/game/machinery/machinery.dm | 1126 ++++----- code/modules/power/singularity/emitter.dm | 636 ++--- 11 files changed, 3623 insertions(+), 3623 deletions(-) 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)