diff --git a/baystation12.dme b/baystation12.dme index 64bb7f88d5..70f38378d6 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1225,9 +1225,9 @@ #include "code\modules\nano\JSON Reader.dm" #include "code\modules\nano\JSON Writer.dm" #include "code\modules\nano\nanoexternal.dm" +#include "code\modules\nano\nanointeraction.dm" #include "code\modules\nano\nanomanager.dm" #include "code\modules\nano\nanomapgen.dm" -#include "code\modules\nano\nanoprocs.dm" #include "code\modules\nano\nanoui.dm" #include "code\modules\nano\modules\crew_monitor.dm" #include "code\modules\nano\modules\power_monitor.dm" diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm index 068f7efdb3..63a0549acc 100644 --- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm @@ -173,7 +173,7 @@ use_power = !use_power if(signal.data["panic_siphon"]) //must be before if("scrubbing" thing - panic = text2num(signal.data["panic_siphon"] != null) + panic = text2num(signal.data["panic_siphon"]) if(panic) use_power = 1 scrubbing = 0 @@ -189,8 +189,12 @@ if(signal.data["scrubbing"] != null) scrubbing = text2num(signal.data["scrubbing"]) + if(scrubbing) + panic = 0 if(signal.data["toggle_scrubbing"]) scrubbing = !scrubbing + if(scrubbing) + panic = 0 var/list/toggle = list() diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 2ffdcc6e2f..a2e78a10f9 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -195,7 +195,6 @@ if(RCON_YES) remote_control = 1 - updateDialog() return /obj/machinery/alarm/proc/handle_heating_cooling(var/datum/gas_mixture/environment) @@ -468,7 +467,7 @@ frequency.post_signal(src, alert_signal) /obj/machinery/alarm/attack_ai(mob/user) - return interact(user) + ui_interact(user) /obj/machinery/alarm/attack_hand(mob/user) . = ..() @@ -477,315 +476,179 @@ return interact(user) /obj/machinery/alarm/interact(mob/user) - user.set_machine(src) + ui_interact(user) + wires.Interact(user) - if(buildstage!=2) - return +/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/custom_state = null) + var/data[0] + var/remote_connection = 0 + var/remote_access = 0 + if(custom_state) + var/list/state = custom_state.href_list(user) + remote_connection = state["remote_connection"] // Remote connection means we're non-adjacent/connecting from another computer + remote_access = state["remote_access"] // Remote access means we also have the privilege to alter the air alarm. - if((get_dist(src, user) > 1 )) - if (!istype(user, /mob/living/silicon)) - user.machine = null - user << browse(null, "window=air_alarm") - user << browse(null, "window=AAlarmwires") - return + data["locked"] = locked && !user.isSilicon() + data["remote_connection"] = remote_connection + data["remote_access"] = remote_access + data["rcon"] = rcon_setting + data["screen"] = screen + populate_status(data) - else if (istype(user, /mob/living/silicon) && aidisabled) - user << "AI control for this Air Alarm interface has been disabled." - user << browse(null, "window=air_alarm") - return + if(!(locked && !remote_connection) || remote_access || user.isSilicon()) + populate_controls(data) - if(wiresexposed && (!istype(user, /mob/living/silicon/ai))) - wires.Interact(user) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if(!ui) + ui = new(user, src, ui_key, "air_alarm.tmpl", src.name, 625, 625, master_ui = master_ui, custom_state = custom_state) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) - if(!shorted) - user << browse(return_text(user),"window=air_alarm") - onclose(user, "air_alarm") - - return - -/obj/machinery/alarm/proc/return_text(mob/user) - if(!(istype(user, /mob/living/silicon)) && locked) - return "\The [src][return_status()]
[rcon_text()]
(Swipe ID card to unlock interface)" - else - return "\The [src][return_status()]
[rcon_text()]
[return_controls()]" - -/obj/machinery/alarm/proc/return_status() +/obj/machinery/alarm/proc/populate_status(var/data) var/turf/location = get_turf(src) var/datum/gas_mixture/environment = location.return_air() var/total = environment.total_moles - var/output = "Air Status:
" - if(total == 0) - output += "Warning: Cannot obtain air sample for analysis." - return output + var/list/environment_data = new + data["has_environment"] = total + if(total) + var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume - output += {" - -"} + var/list/current_settings = TLV["pressure"] + var/pressure = environment.return_pressure() + var/pressure_danger = get_danger_level(pressure, current_settings) + environment_data[++environment_data.len] = list("name" = "Pressure", "value" = pressure, "unit" = "kPa", "danger_level" = pressure_danger) + data["total_danger"] = pressure_danger - var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume + current_settings = TLV["oxygen"] + var/oxygen_danger = get_danger_level(environment.gas["oxygen"]*partial_pressure, current_settings) + environment_data[++environment_data.len] = list("name" = "Oxygen", "value" = environment.gas["oxygen"] / total * 100, "unit" = "%", "danger_level" = oxygen_danger) + data["total_danger"] = max(oxygen_danger, data["total_danger"]) - var/list/current_settings = TLV["pressure"] - var/environment_pressure = environment.return_pressure() - var/pressure_dangerlevel = get_danger_level(environment_pressure, current_settings) + current_settings = TLV["carbon dioxide"] + var/carbon_dioxide_danger = get_danger_level(environment.gas["carbon dioxide"]*partial_pressure, current_settings) + environment_data[++environment_data.len] = list("name" = "Carbon dioxide", "value" = environment.gas["carbon dioxide"] / total * 100, "unit" = "%", "danger_level" = carbon_dioxide_danger) + data["total_danger"] = max(carbon_dioxide_danger, data["total_danger"]) - current_settings = TLV["oxygen"] - var/oxygen_dangerlevel = get_danger_level(environment.gas["oxygen"]*partial_pressure, current_settings) - var/oxygen_percent = round(environment.gas["oxygen"] / total * 100, 2) + current_settings = TLV["phoron"] + var/phoron_danger = get_danger_level(environment.gas["phoron"]*partial_pressure, current_settings) + environment_data[++environment_data.len] = list("name" = "Toxins", "value" = environment.gas["phoron"] / total * 100, "unit" = "%", "danger_level" = phoron_danger) + data["total_danger"] = max(phoron_danger, data["total_danger"]) - current_settings = TLV["carbon dioxide"] - var/co2_dangerlevel = get_danger_level(environment.gas["carbon_dioxide"]*partial_pressure, current_settings) - var/co2_percent = round(environment.gas["carbon_dioxide"] / total * 100, 2) + current_settings = TLV["temperature"] + var/temperature_danger = get_danger_level(environment.temperature, current_settings) + environment_data[++environment_data.len] = list("name" = "Temperature", "value" = environment.temperature, "unit" = "K ([round(environment.temperature - T0C, 0.1)]C)", "danger_level" = temperature_danger) + data["total_danger"] = max(temperature_danger, data["total_danger"]) - current_settings = TLV["phoron"] - var/phoron_dangerlevel = get_danger_level(environment.gas["phoron"]*partial_pressure, current_settings) - var/phoron_percent = round(environment.gas["phoron"] / total * 100, 2) - - //current_settings = TLV["other"] - //var/other_moles = 0.0 - //for(var/datum/gas/G in environment.trace_gases) - // other_moles+=G.moles - //var/other_dangerlevel = get_danger_level(other_moles*partial_pressure, current_settings) - - current_settings = TLV["temperature"] - var/temperature_dangerlevel = get_danger_level(environment.temperature, current_settings) - - output += {" -Pressure: [environment_pressure]kPa
-Oxygen: [oxygen_percent]%
-Carbon dioxide: [co2_percent]%
-Toxins: [phoron_percent]%
-"} - //if (other_dangerlevel==2) - // output += "Notice: High Concentration of Unknown Particles Detected
" - //else if (other_dangerlevel==1) - // output += "Notice: Low Concentration of Unknown Particles Detected
" - - output += "Temperature: [environment.temperature]K ([round(environment.temperature - T0C, 0.1)]C)
" - - //'Local Status' should report the LOCAL status, damnit. - output += "Local Status: " - switch(max(pressure_dangerlevel,oxygen_dangerlevel,co2_dangerlevel,phoron_dangerlevel,other_dangerlevel,temperature_dangerlevel)) - if(2) - output += "DANGER: Internals Required
" - if(1) - output += "Caution
" - if(0) - output += "Optimal
" - - output += "Area Status: " - if(alarm_area.atmosalm) - output += "Atmos alert in area" - else if (alarm_area.fire) - output += "Fire alarm in area" - else - output += "No alerts" - - return output - -/obj/machinery/alarm/proc/rcon_text() - var/dat = "" - - //Hackish, I know. I didn't feel like bothering to rework all of this. - dat += "
Remote Control:
" - if(rcon_setting == RCON_NO) - dat += "Off" - else - dat += "Off" - dat += " | " - if(rcon_setting == RCON_AUTO) - dat += "Auto" - else - dat += "Auto" - dat += " | " - if(rcon_setting == RCON_YES) - dat += "On" - else - dat += "On
Thermostat:
[target_temperature - T0C]C
" - - return dat - -/obj/machinery/alarm/proc/return_controls(var/source = src) - var/output = ""//"[alarm_zone] Air [name]
" + data["environment"] = environment_data + data["atmos_alarm"] = alarm_area.atmosalm + data["fire_alarm"] = alarm_area.fire != null + data["target_temperature"] = "[target_temperature - T0C]C" +/obj/machinery/alarm/proc/populate_controls(var/list/data) switch(screen) - if (AALARM_SCREEN_MAIN) - if(alarm_area.atmosalm) - output += "Reset - Area Atmospheric Alarm
" - else - output += "Activate - Area Atmospheric Alarm
" + if(AALARM_SCREEN_MAIN) + data["mode"] = mode + if(AALARM_SCREEN_VENT) + var/vents[0] + for(var/id_tag in alarm_area.air_vent_names) + var/long_name = alarm_area.air_vent_names[id_tag] + var/list/info = alarm_area.air_vent_info[id_tag] + if(!info) + continue + vents[++vents.len] = list( + "id_tag" = id_tag, + "long_name" = sanitize(long_name), + "power" = info["power"], + "checks" = info["checks"], + "direction" = info["direction"], + "external" = info["external"] + ) + data["vents"] = vents + if(AALARM_SCREEN_SCRUB) + var/scrubbers[0] + for(var/id_tag in alarm_area.air_scrub_names) + var/long_name = alarm_area.air_scrub_names[id_tag] + var/list/info = alarm_area.air_scrub_info[id_tag] + if(!info) + continue + scrubbers[++scrubbers.len] = list( + "id_tag" = id_tag, + "long_name" = sanitize(long_name), + "power" = info["power"], + "scrubbing" = info["scrubbing"], + "panic" = info["panic"], + "filters" = list() + ) + scrubbers[scrubbers.len]["filters"] += list(list("name" = "Oxygen", "command" = "o2_scrub", "val" = info["filter_o2"])) + scrubbers[scrubbers.len]["filters"] += list(list("name" = "Nitrogen", "command" = "n2_scrub", "val" = info["filter_n2"])) + scrubbers[scrubbers.len]["filters"] += list(list("name" = "Carbon Dioxide", "command" = "co2_scrub","val" = info["filter_co2"])) + scrubbers[scrubbers.len]["filters"] += list(list("name" = "Toxin" , "command" = "tox_scrub","val" = info["filter_phoron"])) + scrubbers[scrubbers.len]["filters"] += list(list("name" = "Nitrous Oxide", "command" = "n2o_scrub","val" = info["filter_n2o"])) + data["scrubbers"] = scrubbers + if(AALARM_SCREEN_MODE) + var/modes[0] + modes[++modes.len] = list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0) + modes[++modes.len] = list("name" = "Replace Air - Siphons out air while replacing", "mode" = AALARM_MODE_REPLACEMENT, "selected" = mode == AALARM_MODE_REPLACEMENT, "danger" = 0) + modes[++modes.len] = list("name" = "Panic - Siphons air out of the room", "mode" = AALARM_MODE_PANIC, "selected" = mode == AALARM_MODE_PANIC, "danger" = 1) + modes[++modes.len] = list("name" = "Cycle - Siphons air before replacing", "mode" = AALARM_MODE_CYCLE, "selected" = mode == AALARM_MODE_CYCLE, "danger" = 1) + modes[++modes.len] = list("name" = "Fill - Shuts off scrubbers and opens vents", "mode" = AALARM_MODE_FILL, "selected" = mode == AALARM_MODE_FILL, "danger" = 0) + modes[++modes.len] = list("name" = "Off - Shuts off vents and scrubbers", "mode" = AALARM_MODE_OFF, "selected" = mode == AALARM_MODE_OFF, "danger" = 0) + data["modes"] = modes + data["mode"] = mode + if(AALARM_SCREEN_SENSORS) + var/list/selected + var/thresholds[0] - output += {" -Scrubbers Control
-Vents Control
-Set environmentals mode
-Sensor Settings
-
-"} - if (mode==AALARM_MODE_PANIC) - output += "PANIC SYPHON ACTIVE
Turn syphoning off" - else - output += "ACTIVATE PANIC SYPHON IN AREA" - - - if (AALARM_SCREEN_VENT) - var/sensor_data = "" - if(alarm_area.air_vent_names.len) - for(var/id_tag in alarm_area.air_vent_names) - var/long_name = alarm_area.air_vent_names[id_tag] - var/list/data = alarm_area.air_vent_info[id_tag] - if(!data) - continue; - var/state = "" - - sensor_data += {" -[long_name][state]
-Operating: -[data["power"]?"on":"off"] -
-Pressure checks: -external -internal -
-External pressure bound: -- -- -- -- -[data["external"]] -+ -+ -+ -+ - (reset) -
-"} - if (data["direction"] == "siphon") - sensor_data += {" -Direction: -siphoning -
-"} - sensor_data += {"
"} - else - sensor_data = "No vents connected.
" - output = {"Main menu
[sensor_data]"} - if (AALARM_SCREEN_SCRUB) - var/sensor_data = "" - 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/data = alarm_area.air_scrub_info[id_tag] - if(!data) - continue; - var/state = "" - - sensor_data += {" -[long_name][state]
-Operating: -[data["power"]?"on":"off"]
-Type: -[data["scrubbing"]?"scrubbing":"syphoning"]
-"} - - if(data["scrubbing"]) - sensor_data += {" -Filtering: -Oxygen -[data["filter_o2"]?"on":"off"]; -Nitrogen -[data["filter_n2"]?"on":"off"]; -Carbon Dioxide -[data["filter_co2"]?"on":"off"]; -Toxins -[data["filter_phoron"]?"on":"off"]; -Nitrous Oxide -[data["filter_n2o"]?"on":"off"] -
-"} - sensor_data += {" -Panic syphon: [data["panic"]?"PANIC SYPHON ACTIVATED":""] -Dea":"red'>A")]ctivate
-
-"} - else - sensor_data = "No scrubbers connected.
" - output = {"Main menu
[sensor_data]"} - - if (AALARM_SCREEN_MODE) - output += "Main menu
Air machinery mode for the area:" - - if (AALARM_SCREEN_SENSORS) - output += {" -Main menu
-Alarm thresholds:
-Partial pressure for gases - - - -"} - var/list/gases = list( + var/list/gas_names = list( "oxygen" = "O2", "carbon dioxide" = "CO2", "phoron" = "Toxin", - "other" = "Other",) - - var/list/selected - for (var/g in gases) - output += "" + "other" = "Other") + for (var/g in gas_names) + thresholds[++thresholds.len] = list("name" = gas_names[g], "settings" = list()) selected = TLV[g] for(var/i = 1, i <= 4, i++) - output += "" - output += "" + thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = i, "selected" = selected[i])) selected = TLV["pressure"] - output += " " + thresholds[++thresholds.len] = list("name" = "Pressure", "settings" = list()) for(var/i = 1, i <= 4, i++) - output += "" - output += "" + thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = i, "selected" = selected[i])) selected = TLV["temperature"] - output += "" + thresholds[++thresholds.len] = list("name" = "Temperature", "settings" = list()) for(var/i = 1, i <= 4, i++) - output += "" - output += "
min2min1max1max2
[gases[g]][selected[i] >= 0 ? selected[i] :"OFF"]
Pressure[selected[i] >= 0 ? selected[i] :"OFF"]
Temperature[selected[i] >= 0 ? selected[i] :"OFF"]
" + thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = i, "selected" = selected[i])) - return output -/obj/machinery/alarm/Topic(href, href_list, var/nowindow = 0, var/remote = 0) - if(..(href, href_list, nowindow, !remote) || !( Adjacent(usr) || nowindow || istype(usr, /mob/living/silicon)) ) // dont forget calling super in machine Topics -walter0o - usr.machine = null - usr << browse(null, "window=air_alarm") - usr << browse(null, "window=AAlarmwires") - return + data["thresholds"] = thresholds - add_fingerprint(usr) - usr.set_machine(src) +/obj/machinery/alarm/CanUseTopic(var/mob/user, href_list, var/datum/topic_state/custom_state) + if(buildstage != 2) + return STATUS_CLOSE + + if(aidisabled && user.isAI()) + user << "AI control for \the [src] interface has been disabled." + return STATUS_CLOSE + + . = shorted ? STATUS_DISABLED : STATUS_INTERACTIVE + + if(. == STATUS_INTERACTIVE) + var/extra_href = custom_state.href_list(usr) + // Prevent remote users from altering RCON settings unless they already have access (I realize the risks) + if(href_list["rcon"] && extra_href["remote_connection"] && !extra_href["remote_access"]) + . = STATUS_UPDATE + + //TODO: Move the rest of if(!locked || extra_href["remote_access"] || usr.isAI()) and hrefs here + + return min(..(), .) + +/obj/machinery/alarm/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/custom_state) + if(..(href, href_list, nowindow, custom_state)) + return 1 // hrefs that can always be called -walter0o if(href_list["rcon"]) @@ -798,28 +661,38 @@ table tr:first-child th:first-child { border: none;} rcon_setting = RCON_AUTO if(RCON_YES) rcon_setting = RCON_YES - else - return + return 1 if(href_list["temperature"]) var/list/selected = TLV["temperature"] var/max_temperature = min(selected[3] - T0C, MAX_TEMPERATURE) var/min_temperature = max(selected[2] - T0C, MIN_TEMPERATURE) - var/input_temperature = input("What temperature would you like the system to mantain? (Capped between [min_temperature]C and [max_temperature]C)", "Thermostat Controls") as num|null - if(!input_temperature || input_temperature > max_temperature || input_temperature < min_temperature) - usr << "Temperature must be between [min_temperature]C and [max_temperature]C" - else - target_temperature = input_temperature + T0C + var/input_temperature = input("What temperature would you like the system to mantain? (Capped between [min_temperature] and [max_temperature]C)", "Thermostat Controls", target_temperature - T0C) as num|null + if(isnum(input_temperature)) + if(input_temperature > max_temperature || input_temperature < min_temperature) + usr << "Temperature must be between [min_temperature]C and [max_temperature]C" + else + target_temperature = input_temperature + T0C + return 1 // hrefs that need the AA unlocked -walter0o - if(!locked || remote || istype(usr, /mob/living/silicon)) - + var/extra_href = custom_state.href_list(usr) + if(!(locked && !extra_href["remote_connection"]) || extra_href["remote_access"] || usr.isSilicon()) if(href_list["command"]) var/device_id = href_list["id_tag"] switch(href_list["command"]) + if("set_external_pressure") + var/input_pressure = input("What pressure you like the system to mantain?", "Pressure Controls") as num|null + if(isnum(input_pressure)) + send_signal(device_id, list(href_list["command"] = input_pressure)) + return 1 + + if("reset_external_pressure") + send_signal(device_id, list(href_list["command"] = ONE_ATMOSPHERE)) + return 1 + if( "power", "adjust_external_pressure", - "set_external_pressure", "checks", "o2_scrub", "n2_scrub", @@ -830,6 +703,7 @@ table tr:first-child th:first-child { border: none;} "scrubbing") send_signal(device_id, list(href_list["command"] = text2num(href_list["val"]) ) ) + return 1 if("set_threshold") var/env = href_list["env"] @@ -838,7 +712,7 @@ table tr:first-child th:first-child { border: none;} var/list/thresholds = list("lower bound", "low warning", "high warning", "upper bound") var/newval = input("Enter [thresholds[threshold]] for [env]", "Alarm triggers", selected[threshold]) as null|num if (isnull(newval)) - return + return 1 if (newval<0) selected[threshold] = -1.0 else if (env=="temperature" && newval>5000) @@ -880,9 +754,11 @@ table tr:first-child th:first-child { border: none;} selected[3] = selected[4] apply_mode() + return 1 if(href_list["screen"]) screen = text2num(href_list["screen"]) + return 1 if(href_list["atmos_unlock"]) switch(href_list["atmos_unlock"]) @@ -890,24 +766,24 @@ table tr:first-child th:first-child { border: none;} alarm_area.air_doors_close() if("1") alarm_area.air_doors_open() + return 1 if(href_list["atmos_alarm"]) if (alarm_area.atmosalert(2)) apply_danger_level(2) update_icon() + return 1 if(href_list["atmos_reset"]) if (alarm_area.atmosalert(0)) apply_danger_level(0) update_icon() + return 1 if(href_list["mode"]) mode = text2num(href_list["mode"]) apply_mode() - - if(!nowindow) - updateUsrDialog() - + return 1 /obj/machinery/alarm/attackby(obj/item/W as obj, mob/user as mob) src.add_fingerprint(user) @@ -937,7 +813,6 @@ table tr:first-child th:first-child { border: none;} if(allowed(usr) && !wires.IsIndexCut(AALARM_WIRE_IDSCAN)) locked = !locked user << "\blue You [ locked ? "lock" : "unlock"] the Air Alarm interface." - updateUsrDialog() else user << "\red Access denied." return diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index a722131102..a6eb8765f1 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -9,11 +9,11 @@ density = 1 anchored = 1.0 circuit = "/obj/item/weapon/circuitboard/atmoscontrol" - var/obj/machinery/alarm/current var/overridden = 0 //not set yet, can't think of a good way to do it req_access = list(access_ce) var/list/monitored_alarm_ids = null var/list/monitored_alarms = null + var/ui_ref /obj/machinery/computer/atmoscontrol/laptop name = "Atmospherics Laptop" @@ -32,36 +32,29 @@ monitored_alarms = dd_sortedObjectList(monitored_alarms) /obj/machinery/computer/atmoscontrol/attack_ai(var/mob/user as mob) - return interact(user) + return ui_interact(user) /obj/machinery/computer/atmoscontrol/attack_hand(mob/user) if(..()) return - return interact(user) + return ui_interact(user) -/obj/machinery/computer/atmoscontrol/interact(mob/user) - user.set_machine(src) - if(allowed(user)) - overridden = 1 - else if(!emagged) - overridden = 0 - var/dat = "Main Menu
" - if(monitored_alarms && monitored_alarms.len == 1) - current = monitored_alarms[1] - if(current) - dat += specific() - else - for(var/obj/machinery/alarm/alarm in monitored_alarms ? monitored_alarms : machines) - dat += "" - switch(max(alarm.danger_level, alarm.alarm_area.atmosalm)) - if (0) - dat += "" - if (1) - dat += "" - if (2) - dat += "" - dat += "[sanitize(alarm.name)]
" - user << browse(dat, "window=atmoscontrol") +/obj/machinery/computer/atmoscontrol/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + var/data[0] + var/alarms[0] + + // TODO: Move these to a cache, similar to cameras + for(var/obj/machinery/alarm/alarm in (monitored_alarms ? monitored_alarms : machines)) + alarms[++alarms.len] = list("name" = sanitize(alarm.name), "ref"= "\ref[alarm]", "danger" = max(alarm.danger_level, alarm.alarm_area.atmosalm)) + data["alarms"] = alarms + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if(!ui) + ui = new(user, src, ui_key, "atmos_control.tmpl", src.name, 625, 625) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) + ui_ref = ui /obj/machinery/computer/atmoscontrol/attackby(var/obj/item/I as obj, var/mob/user as mob) if(istype(I, /obj/item/weapon/card/emag) && !emagged) @@ -73,23 +66,33 @@ return return ..() -/obj/machinery/computer/atmoscontrol/proc/specific() - if(!current) - return "" - var/dat = "

[current.name]


" - dat += current.return_status() - if(current.remote_control || overridden) - dat += "
[current.return_controls(src)]" - return dat - //a bunch of this is copied from atmos alarms /obj/machinery/computer/atmoscontrol/Topic(href, href_list) if(..()) - return - if(href_list["reset"]) - current = null + return 1 + if(href_list["alarm"]) - current = locate(href_list["alarm"]) - else if(current) - current.Topic(href, href_list, 1, 1) - interact(usr) + if(ui_ref) + var/obj/machinery/alarm/alarm = locate(href_list["alarm"]) in (monitored_alarms ? monitored_alarms : machines) + if(alarm) + var/datum/topic_state/TS = generate_state(alarm) + alarm.ui_interact(usr, master_ui = ui_ref, custom_state = TS) + return 1 + +/obj/machinery/computer/atmoscontrol/proc/generate_state(var/alarm) + var/datum/topic_state/air_alarm/state = new() + state.atmos_control = src + state.air_alarm = alarm + return state + +/datum/topic_state/air_alarm + flags = NANO_IGNORE_DISTANCE + var/obj/machinery/computer/atmoscontrol/atmos_control = null + var/obj/machinery/alarm/air_alarm = null + +/datum/topic_state/air_alarm/href_list(var/mob/user) + var/list/extra_href = list() + extra_href["remote_connection"] = 1 + extra_href["remote_access"] = user && (atmos_control.allowed(user) || atmos_control.emagged || air_alarm.rcon_setting == RCON_YES || (air_alarm.alarm_area.atmosalm && air_alarm.rcon_setting == RCON_AUTO)) + + return extra_href diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 819cc05632..042889157a 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -182,13 +182,18 @@ Class Procs: /obj/machinery/proc/inoperable(var/additional_flags = 0) return (stat & (NOPOWER|BROKEN|additional_flags)) +/obj/machinery/CanUseTopic(var/mob/user, var/be_close) + if(!interact_offline && (stat & (NOPOWER|BROKEN))) + return STATUS_CLOSE -/obj/machinery/Topic(href, href_list, var/nowindow = 0, var/checkrange = 1) - if(..()) - return 1 - if(!interact_offline && stat & (NOPOWER|BROKEN)) - return 1 - return 0 + return ..() + +/obj/machinery/CouldUseTopic(var/mob/user) + ..() + user.set_machine(src) + +/obj/machinery/CouldNotUseTopic(var/mob/user) + usr.unset_machine() //////////////////////////////////////////////////////////////////////////////////////////// diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 8f54b76717..b67ce9023e 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -16,15 +16,27 @@ var/damtype = "brute" var/force = 0 -/obj/Topic(href, href_list, var/nowindow = 0, var/checkrange = 1) +/obj/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/custom_state) // Calling Topic without a corresponding window open causes runtime errors if(!nowindow && ..()) return 1 - if(usr.can_interact_with_interface(nano_host(), checkrange) != STATUS_INTERACTIVE) - return 1 - add_fingerprint(usr) - return 0 + // In the far future no checks are made in an overriding Topic() beyond if(..()) return + // Instead any such checks are made in CanUseTopic() + var/obj/host = nano_host() + if(host.CanUseTopic(usr, href_list, custom_state) == STATUS_INTERACTIVE) + CouldUseTopic(usr) + return 0 + + CouldNotUseTopic(usr) + return 1 + +/obj/proc/CouldUseTopic(var/mob/user) + var/atom/host = nano_host() + host.add_fingerprint(user) + +/obj/proc/CouldNotUseTopic(var/mob/user) + // Nada /obj/item/proc/is_used_on(obj/O, mob/user) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 3c983bcc22..bc9ba4a33d 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -80,6 +80,18 @@ return 1 return 0 +/mob/proc/isSilicon() + return 0 + +/mob/living/silicon/isSilicon() + return 1 + +/mob/proc/isAI() + return 0 + +/mob/living/silicon/ai/isAI() + return 1 + /proc/ispAI(A) if(istype(A, /mob/living/silicon/pai)) return 1 diff --git a/code/modules/nano/nanoexternal.dm b/code/modules/nano/nanoexternal.dm index 50e2b706f8..b029019f1a 100644 --- a/code/modules/nano/nanoexternal.dm +++ b/code/modules/nano/nanoexternal.dm @@ -1,5 +1,5 @@ - // This file contains all Nano procs/definitions for external classes/objects - + // This file contains all Nano procs/definitions for external classes/objects + /** * Called when a Nano UI window is closed * This is how Nano handles closed windows @@ -15,7 +15,7 @@ if (istype(ui)) ui.close() - + if(ui.ref) var/href = "close=1" src.Topic(href, params2list(href), ui.ref) // this will direct to the atom's Topic() proc via client.Topic() @@ -31,14 +31,14 @@ * ui_interact is currently defined for /atom/movable * * @param user /mob The mob who is interacting with this ui - * @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main") - * @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui + * @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main") + * @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui * @param force_open boolean Force the UI to (re)open, even if it's already open * * @return nothing */ -/atom/movable/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/atom/movable/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/nano_ui/master_ui = null, var/datum/topic_state/custom_state = null) return - + // Used by the Nano UI Manager (/datum/nanomanager) to track UIs opened by this mob /mob/var/list/open_uis = list() diff --git a/code/modules/nano/nanointeraction.dm b/code/modules/nano/nanointeraction.dm new file mode 100644 index 0000000000..09b46eb30e --- /dev/null +++ b/code/modules/nano/nanointeraction.dm @@ -0,0 +1,118 @@ +/atom/movable/proc/nano_host() + return src + +/obj/nano_module/nano_host() + return loc + + +/atom/movable/proc/CanUseTopic(var/mob/user, href_list, var/datum/topic_state/custom_state) + return user.can_use_topic(nano_host(), custom_state) + + +/mob/proc/can_use_topic(var/mob/user, var/datum/topic_state/custom_state) + return STATUS_CLOSE // By default no mob can do anything with NanoUI + +/mob/dead/observer/can_use_topic() + if(check_rights(R_ADMIN, 0)) + return STATUS_INTERACTIVE // Admins are more equal + return STATUS_UPDATE // Ghosts can view updates + +/mob/living/silicon/pai/can_use_topic(var/src_object) + if(src_object == src && !stat) + return STATUS_INTERACTIVE + else + return ..() + +/mob/living/silicon/robot/can_use_topic(var/src_object, var/datum/topic_state/custom_state) + if(stat || !client) + return STATUS_CLOSE + if(lockcharge || stunned || weakened) + return STATUS_DISABLED + // robots can interact with things they can see within their view range + if(!(custom_state.flags & NANO_IGNORE_DISTANCE) && (src_object in view(src))) + return STATUS_INTERACTIVE // interactive (green visibility) + return STATUS_DISABLED // no updates, completely disabled (red visibility) + +/mob/living/silicon/robot/syndicate/can_use_topic(var/src_object) + . = ..() + if(. != STATUS_INTERACTIVE) + return + + if(z in config.admin_levels) // Syndicate borgs can interact with everything on the admin level + return STATUS_INTERACTIVE + if(istype(get_area(src), /area/syndicate_station)) // If elsewhere, they can interact with everything on the syndicate shuttle + return STATUS_INTERACTIVE + if(istype(src_object, /obj/machinery)) // Otherwise they can only interact with emagged machinery + var/obj/machinery/Machine = src_object + if(Machine.emagged) + return STATUS_INTERACTIVE + return STATUS_UPDATE + +/mob/living/silicon/ai/can_use_topic(var/src_object) + if(!client || check_unable(1)) + return STATUS_CLOSE + // Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras) + // unless it's on the same level as the object it's interacting with. + var/turf/T = get_turf(src_object) + if(!T || !(z == T.z || (T.z in config.player_levels))) + return STATUS_CLOSE + + // If an object is in view then we can interact with it + if(src_object in view(client.view, src)) + return STATUS_INTERACTIVE + + // If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view + if(is_in_chassis()) + //stop AIs from leaving windows open and using then after they lose vision + //apc_override is needed here because AIs use their own APC when powerless + if(cameranet && !cameranet.checkTurfVis(get_turf(src_object))) + return apc_override ? STATUS_INTERACTIVE : STATUS_CLOSE + return STATUS_INTERACTIVE + + return STATUS_CLOSE + +/mob/living/proc/shared_living_nano_interaction(var/src_object) + if (src.stat != CONSCIOUS) + return STATUS_CLOSE // no updates, close the interface + else if (restrained() || lying || stat || stunned || weakened) + return STATUS_UPDATE // update only (orange visibility) + return STATUS_INTERACTIVE + +/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object) + if(!isturf(src_object.loc)) + if(src_object.loc == src) // Item in the inventory + return STATUS_INTERACTIVE + if(src.contents.Find(src_object.loc)) // A hidden uplink inside an item + return STATUS_INTERACTIVE + + if (!(src_object in view(4, src))) // If the src object is not in visable, disable updates + return STATUS_CLOSE + + var/dist = get_dist(src_object, src) + if (dist <= 1) + return STATUS_INTERACTIVE // interactive (green visibility) + else if (dist <= 2) + return STATUS_UPDATE // update only (orange visibility) + else if (dist <= 4) + return STATUS_DISABLED // no updates, completely disabled (red visibility) + return STATUS_CLOSE + +/mob/living/can_use_topic(var/src_object, var/datum/topic_state/custom_state) + . = shared_living_nano_interaction(src_object) + if(. == STATUS_INTERACTIVE && !(custom_state.flags & NANO_IGNORE_DISTANCE)) + . = shared_living_nano_distance(src_object) + if(STATUS_INTERACTIVE) + return STATUS_UPDATE + +/mob/living/carbon/human/can_use_topic(var/src_object, var/datum/topic_state/custom_state) + . = shared_living_nano_interaction(src_object) + if(. == STATUS_INTERACTIVE && !(custom_state.flags & NANO_IGNORE_DISTANCE)) + . = shared_living_nano_distance(src_object) + if(. == STATUS_UPDATE && (TK in mutations)) // If we have telekinesis and remain close enough, allow interaction. + return STATUS_INTERACTIVE + +/datum/topic_state + var/flags = 0 + +/datum/topic_state/proc/href_list(var/mob/user) + return list() \ No newline at end of file diff --git a/code/modules/nano/nanomanager.dm b/code/modules/nano/nanomanager.dm index ddc3fcac9f..794d9c5727 100644 --- a/code/modules/nano/nanomanager.dm +++ b/code/modules/nano/nanomanager.dm @@ -186,7 +186,8 @@ return 0 // wasn't open processing_uis.Remove(ui) - ui.user.open_uis.Remove(ui) + if(ui.user) // Sanity check in case a user has been deleted (say a blown up borg watching the alarm interface) + ui.user.open_uis.Remove(ui) var/list/uis = open_uis[src_object_key][ui.ui_key] uis.Remove(ui) diff --git a/code/modules/nano/nanoprocs.dm b/code/modules/nano/nanoprocs.dm deleted file mode 100644 index 65432a8f24..0000000000 --- a/code/modules/nano/nanoprocs.dm +++ /dev/null @@ -1,11 +0,0 @@ -/atom/movable/proc/nano_host() - return src - -/obj/nano_module/nano_host() - return loc - -/atom/movable/proc/nano_can_update() - return 1 - -/obj/machinery/nano_can_update() - return !(stat & (NOPOWER|BROKEN)) diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm index 04ef3cc95b..0a6b6ede8e 100644 --- a/code/modules/nano/nanoui.dm +++ b/code/modules/nano/nanoui.dm @@ -52,6 +52,11 @@ nanoui is used to open and update nano browser uis // the current status/visibility of the ui var/status = STATUS_INTERACTIVE + // Relationship between a master interface and its children. Used in update_status + var/datum/nanoui/master_ui + var/list/datum/nanoui/children = list() + var/datum/topic_state/custom_state = null + var/cached_data = null /** @@ -68,17 +73,22 @@ nanoui is used to open and update nano browser uis * * @return /nanoui new nanoui object */ -/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null) +/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/custom_state = null) user = nuser src_object = nsrc_object ui_key = nui_key window_id = "[ui_key]\ref[src_object]" + src.master_ui = master_ui + if(master_ui) + master_ui.children += src + src.custom_state = custom_state ? custom_state : new/datum/topic_state() + // add the passed template filename as the "main" template, this is required add_template("main", ntemplate_filename) if (ntitle) - title = ntitle + title = sanitize(ntitle) if (nwidth) width = nwidth if (nheight) @@ -133,120 +143,13 @@ nanoui is used to open and update nano browser uis */ /datum/nanoui/proc/update_status(var/push_update = 0) var/atom/movable/host = src_object.nano_host() - if(!host.nano_can_update()) - close() - return - - var/status = user.can_interact_with_interface(host.nano_host()) - if(status == STATUS_CLOSE) + var/new_status = host.CanUseTopic(user, list(), custom_state) + if(master_ui) + new_status = min(new_status, master_ui.status) + if(new_status == STATUS_CLOSE) close() else - set_status(status, push_update) - -/* - Procs called by update_status() -*/ - -/mob/living/silicon/pai/can_interact_with_interface(src_object) - if(src_object == src && !stat) - return STATUS_INTERACTIVE - else - return ..() - -/mob/proc/can_interact_with_interface(var/src_object) - return STATUS_CLOSE // By default no mob can do anything with NanoUI - -/mob/dead/observer/can_interact_with_interface() - if(check_rights(R_ADMIN, 0)) - return STATUS_INTERACTIVE // Admins are more equal - return STATUS_UPDATE // Ghosts can view updates - -/mob/living/silicon/robot/can_interact_with_interface(var/src_object) - if(stat || !client) - return STATUS_CLOSE - if(lockcharge || stunned || weakened) - return STATUS_DISABLED - if (src_object in view(client.view, src)) // robots can see and interact with things they can see within their view range - return STATUS_INTERACTIVE // interactive (green visibility) - return STATUS_DISABLED // no updates, completely disabled (red visibility) - -/mob/living/silicon/robot/syndicate/can_interact_with_interface(var/src_object) - . = ..() - if(. != STATUS_INTERACTIVE) - return - - if(z in config.admin_levels) // Syndicate borgs can interact with everything on the admin level - return STATUS_INTERACTIVE - if(istype(get_area(src), /area/syndicate_station)) // If elsewhere, they can interact with everything on the syndicate shuttle - return STATUS_INTERACTIVE - if(istype(src_object, /obj/machinery)) // Otherwise they can only interact with emagged machinery - var/obj/machinery/Machine = src_object - if(Machine.emagged) - return STATUS_INTERACTIVE - return STATUS_UPDATE - -/mob/living/silicon/ai/can_interact_with_interface(var/src_object) - if(!client || check_unable(1)) - return STATUS_CLOSE - // Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras) - // unless it's on the same level as the object it's interacting with. - var/turf/T = get_turf(src_object) - if(!T || !(z == T.z || (T.z in config.player_levels))) - return STATUS_CLOSE - - // If an object is in view then we can interact with it - if(src_object in view(client.view, src)) - return STATUS_INTERACTIVE - - // If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view - if(is_in_chassis()) - //stop AIs from leaving windows open and using then after they lose vision - //apc_override is needed here because AIs use their own APC when powerless - if(cameranet && !cameranet.checkTurfVis(get_turf(src_object))) - return apc_override ? STATUS_INTERACTIVE : STATUS_CLOSE - return STATUS_INTERACTIVE - - return STATUS_CLOSE - -/mob/living/proc/shared_living_nano_interaction(var/src_object) - if (src.stat != CONSCIOUS) - return STATUS_CLOSE // no updates, close the interface - else if (restrained() || lying || stat || stunned || weakened) - return STATUS_UPDATE // update only (orange visibility) - return STATUS_INTERACTIVE - -/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object) - if(!isturf(src_object.loc)) - if(src_object.loc == src) // Item in the inventory - return STATUS_INTERACTIVE - if(src.contents.Find(src_object.loc)) // A hidden uplink inside an item - return STATUS_INTERACTIVE - - if (!(src_object in view(4, src))) // If the src object is not in visable, disable updates - return STATUS_CLOSE - - var/dist = get_dist(src_object, src) - if (dist <= 1) - return STATUS_INTERACTIVE // interactive (green visibility) - else if (dist <= 2) - return STATUS_UPDATE // update only (orange visibility) - else if (dist <= 4) - return STATUS_DISABLED // no updates, completely disabled (red visibility) - return STATUS_CLOSE - -/mob/living/can_interact_with_interface(var/src_object, var/be_close = 1) - . = shared_living_nano_interaction(src_object) - if(. == STATUS_INTERACTIVE && be_close) - . = shared_living_nano_distance(src_object) - if(STATUS_INTERACTIVE) - return STATUS_UPDATE - -/mob/living/carbon/human/can_interact_with_interface(var/src_object, var/be_close = 1) - . = shared_living_nano_interaction(src_object) - if(. == STATUS_INTERACTIVE && be_close) - . = shared_living_nano_distance(src_object) - if(. == STATUS_UPDATE && (TK in mutations)) // If we have telekinesis and remain close enough, allow interaction. - return STATUS_INTERACTIVE + set_status(new_status, push_update) /** * Set the ui to auto update (every master_controller tick) @@ -489,7 +392,6 @@ nanoui is used to open and update nano browser uis * @return nothing */ /datum/nanoui/proc/open() - var/window_size = "" if (width && height) window_size = "size=[width]x[height];" @@ -509,6 +411,8 @@ nanoui is used to open and update nano browser uis is_auto_updating = 0 nanomanager.ui_closed(src) user << browse(null, "window=[window_id]") + for(var/datum/nanoui/child in children) + child.close() /** * Set the UI window to call the nanoclose verb when the window is closed @@ -573,7 +477,7 @@ nanoui is used to open and update nano browser uis set_map_z_level(text2num(href_list["mapZLevel"])) map_update = 1 - if ((src_object && src_object.Topic(href, href_list)) || map_update) + if ((src_object && src_object.Topic(href, href_list, 0, custom_state)) || map_update) nanomanager.update_uis(src_object) // update all UIs attached to src_object /** @@ -600,5 +504,4 @@ nanoui is used to open and update nano browser uis * @return nothing */ /datum/nanoui/proc/update(var/force_open = 0) - src_object.ui_interact(user, ui_key, src, force_open) - + src_object.ui_interact(user, ui_key, src, force_open, master_ui, custom_state) diff --git a/code/setup.dm b/code/setup.dm index 06235da7fc..fb54f3c067 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -759,3 +759,4 @@ var/list/be_special_flags = list( #define STATUS_DISABLED 0 // RED Visability #define STATUS_CLOSE -1 // Close the interface +#define NANO_IGNORE_DISTANCE 1 \ No newline at end of file diff --git a/nano/css/shared.css b/nano/css/shared.css index b81990b7a3..ee4725a4bb 100644 --- a/nano/css/shared.css +++ b/nano/css/shared.css @@ -128,7 +128,7 @@ img, a img { h1, h2, h3, h4, h5, h6 { margin: 0; padding: 12px 0 6px 0; - color: #517087; + color: #FFFFFF; clear: both; } @@ -491,6 +491,14 @@ div.notice { text-align: center; } +table.fixed { + table-layout:fixed; +} + +table.fixed td { + overflow: hidden; +} + /* Table stuffs for power monitor */ table.pmon { border: 2px solid RoyalBlue; diff --git a/nano/js/nano_base_helpers.js b/nano/js/nano_base_helpers.js index d5a019e2f8..20e6160fed 100644 --- a/nano/js/nano_base_helpers.js +++ b/nano/js/nano_base_helpers.js @@ -48,6 +48,10 @@ NanoBaseHelpers = function () round: function(number) { return Math.round(number); }, + // Returns the number fixed to 1 decimal + fixed: function(number) { + return Math.round(number * 10) / 10; + }, // Round a number down to integer floor: function(number) { return Math.floor(number); diff --git a/nano/templates/air_alarm.tmpl b/nano/templates/air_alarm.tmpl new file mode 100644 index 0000000000..6ba6b14057 --- /dev/null +++ b/nano/templates/air_alarm.tmpl @@ -0,0 +1,217 @@ + +

Air Status

+{{if data.has_environment}} + {{for data.environment}} + {{:value.name}}: + {{if value.danger_level == 2}} + + {{else value.danger_level == 1}} + + {{else}} + + {{/if}} + {{:helper.fixed(value.value, 1)}} + {{:value.unit}}
+ {{/for}} + Local Status: {{if value.danger_level == 2}} + DANGER: Internals Required + {{else value.danger_level == 1}} + Caution + {{else}} + Optimal + {{/if}} +
+ Area Status: {{if data.atmos_alarm}}Atmosphere alert in area{{else data.fire_alarm}}Fire alarm in area{{else}}No alerts{{/if}} +{{else}} + Warning: Cannot obtain air sample for analysis. +{{/if}} +
+ + + + + + + + + + + + + +
+
+

Remote Control

+
+

Thermostat

+
+
+
+
+ {{:helper.link('Off', null, { 'rcon' : 1}, data.remote_connection && !data.remote_access ? (data.rcon == 1 ? 'yellowButton' : 'disabled') : null, data.rcon == 1 ? 'selected' : null)}} + {{:helper.link('Auto', null, { 'rcon' : 2}, data.remote_connection && !data.remote_access ? (data.rcon == 2 ? 'yellowButton' : 'disabled') : null, data.rcon == 2 ? 'selected' : null)}} + {{:helper.link('On', null, { 'rcon' : 3}, data.remote_connection && !data.remote_access ? (data.rcon == 3 ? 'yellowButton' : 'disabled') : null, data.rcon == 3 ? 'selected' : null)}} +
+
+
+ {{:helper.link(data.target_temperature, null, { 'temperature' : 1})}} +
+
+{{if data.locked || (data.remote_connection && ! data.remote_access)}} + {{if data.remote_connection}} + (Current remote control settings and alarm status restricts access.) + {{else}} + (Swipe ID card to unlock interface.) + {{/if}} +{{else}} + {{if data.screen != 1}} +
{{:helper.link('Main Menu', null, { 'screen' : 1})}}
+ {{/if}} + {{if data.screen == 1}} +
+ {{if data.atmos_alarm}} + {{:helper.link('Reset - Area Atmospheric Alarm', null, { 'atmos_reset' : 1})}} + {{else}} + {{:helper.link('Activate - Area Atmospheric Alarm', null, { 'atmos_alarm' : 1})}} + {{/if}} +
+
+
+ {{:helper.link('Scrubbers Control', null, { 'screen' : 3})}} +
+
+ {{:helper.link('Vents Control', null, { 'screen' : 2})}} +
+
+ {{:helper.link('Set Environmental Mode', null, { 'screen' : 4})}} +
+
+ {{:helper.link('Sensor Settings', null, { 'screen' : 5})}} +
+
+ {{if data.mode==3}} + {{:helper.link('PANIC SIPHON ACTIVE - Turn siphoning off', null, { 'mode' : 1}, null, 'redButton')}} + {{else}} + {{:helper.link('ACTIVATE PANIC SIPHON IN AREA', null, { 'mode' : 3}, null, 'yellowButton')}} + {{/if}} + {{else data.screen == 2}} + {{for data.vents}} +
+ {{:value.long_name}}
+
+
+ Operating: +
+
+ {{:helper.link(value.power ? 'On' : 'Off', null, { 'id_tag' : value.id_tag, 'command' : 'power', 'val' : value.power ? 0 : 1}, null, value.power ? null : 'redButton')}} +
+
+
+
+ Operation Mode: +
+
+ {{:value.direction == "siphon" ? 'Siphoning' : 'Pressurizing'}} +
+
+
+
+ Pressure Checks: +
+
+ {{:helper.link('External', null, { 'id_tag' : value.id_tag, 'command' : 'checks', 'val' : value.checks^1}, null, value.checks&1 ? 'selected' : null)}} + {{:helper.link('Internal', null, { 'id_tag' : value.id_tag, 'command' : 'checks', 'val' : value.checks^2}, null, value.checks&2 ? 'selected' : null)}} +
+
+
+
+ External Pressure Bound: +
+
+ {{:helper.link(helper.fixed(value.external,2), null, { 'id_tag' : value.id_tag, 'command' : 'set_external_pressure'})}} + {{:helper.link('Reset', null, { 'id_tag' : value.id_tag, 'command' : 'reset_external_pressure'})}} +
+
+
+ {{empty}} + No vents connected. + {{/for}} + {{else data.screen == 3}} + {{for data.scrubbers}} +
+ {{:value.long_name}}
+
+
+ Operating: +
+
+ {{:helper.link(value.power ? 'On' : 'Off', null, { 'id_tag' : value.id_tag, 'command' : 'power', 'val' : value.power ? 0 : 1}, null, value.power ? null : 'redButton')}} +
+
+
+
+ Operation Mode: +
+
+ {{:helper.link(value.scrubbing ? 'Scrubbing' : 'Siphoning', null, { 'id_tag' : value.id_tag, 'command' : 'scrubbing', 'val' : value.scrubbing ? 0 : 1}, null, value.scrubbing ? null : 'redButton')}} +
+
+
+
+ Filters: +
+
+ {{for value.filters :filterValue:filterIndex}} + {{:helper.link(filterValue.name, null, { 'id_tag' : value.id_tag, 'command' : filterValue.command, 'val' : filterValue.val ? 0 : 1}, null, filterValue.val ? 'selected' : null)}} + {{/for}} +
+
+
+ {{empty}} + No scrubbers connected. + {{/for}} + {{else data.screen == 4}} +

Environmental Modes

+ {{for data.modes}} +
+ {{:helper.link(value.name, null, { 'mode' : value.mode }, null, value.selected ? (value.danger ? 'redButton' : 'selected') : null)}} +
+ {{/for}} + {{else data.screen == 5}} +

Alarm Threshold

+ Partial pressure for gases. + + + + + {{for data.thresholds}} + + + {{for value.settings :settingsValue:settingsIndex}} + + {{/for}} + + {{/for}} +
min2min1max1max2
{{:value.name}} + {{:helper.link(settingsValue.selected >= 0 ? helper.fixed(settingsValue.selected, 2) : "Off", null, { 'command' : 'set_threshold', 'env' : settingsValue.env, 'var' : settingsValue.val })}} +
+ {{/if}} +{{/if}} + \ No newline at end of file diff --git a/nano/templates/atmos_control.tmpl b/nano/templates/atmos_control.tmpl new file mode 100644 index 0000000000..5e9a1acfe4 --- /dev/null +++ b/nano/templates/atmos_control.tmpl @@ -0,0 +1,5 @@ +
+ {{for data.alarms}} + {{:helper.link(value.name, null, {'alarm' : value.ref}, null, value.danger == 2 ? 'redButton' : (value.danger == 1 ? 'yellowButton' : null))}} + {{/for}} +
\ No newline at end of file diff --git a/nano/templates/atmosphere_monitor.tmpl b/nano/templates/atmosphere_monitor.tmpl new file mode 100644 index 0000000000..0089467e43 --- /dev/null +++ b/nano/templates/atmosphere_monitor.tmpl @@ -0,0 +1,37 @@ + + +{{for data.categories}} +

{{:value.category}}

+ {{for value.alarms :alarmValue:alarmIndex}} + {{if alarmValue.origin_lost}} + {{:alarmValue.name}} Alarm Origin Lost
+ {{else}} + {{:alarmValue.name}}
+ {{/if}} + {{if alarmValue.has_cameras || alarmValue.lost_sources != ""}} +
+ {{if alarmValue.has_cameras}} +
+ {{for alarmValue.cameras :cameraValue:cameraIndex}} + {{if cameraValue.deact}} + {{:helper.link(cameraValue.name + " (deactivated)", '', {}, 'inactive')}} + {{else}} + {{:helper.link(cameraValue.name, '', {'switchTo' : cameraValue.camera})}} + {{/if}} + {{/for}} +
+ {{/if}} + {{if alarmValue.lost_sources != ""}} +
+

Lost Alarm Sources: {{:alarmValue.lost_sources}}

+
+ {{/if}} +
+ {{/if}} + {{empty}} + --All Systems Nominal + {{/for}} +{{/for}} \ No newline at end of file