diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm
index 85087a1f8a..5f559b62cb 100644
--- a/code/__HELPERS/lists.dm
+++ b/code/__HELPERS/lists.dm
@@ -297,6 +297,31 @@ proc/listclearnulls(list/list)
return (result + R.Copy(Ri, 0))
+// List of lists, sorts by element[key] - for things like crew monitoring computer sorting records by name.
+/proc/sortByKey(var/list/L, var/key)
+ if(L.len < 2)
+ return L
+ var/middle = L.len / 2 + 1
+ return mergeKeyedLists(sortByKey(L.Copy(0, middle), key), sortByKey(L.Copy(middle), key), key)
+
+/proc/mergeKeyedLists(var/list/L, var/list/R, var/key)
+ var/Li=1
+ var/Ri=1
+ var/list/result = new()
+ while(Li <= L.len && Ri <= R.len)
+ if(sorttext(L[Li][key], R[Ri][key]) < 1)
+ // Works around list += list2 merging lists; it's not pretty but it works
+ result += "temp item"
+ result[result.len] = R[Ri++]
+ else
+ result += "temp item"
+ result[result.len] = L[Li++]
+
+ if(Li <= L.len)
+ return (result + L.Copy(Li, 0))
+ return (result + R.Copy(Ri, 0))
+
+
//Mergesort: any value in a list, preserves key=value structure
/proc/sortAssoc(var/list/L)
if(L.len < 2)
diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm
index 49d12a4847..91778fb723 100644
--- a/code/game/machinery/computer/crew.dm
+++ b/code/game/machinery/computer/crew.dm
@@ -43,67 +43,65 @@
if(..()) return
if (src.z > 6)
usr << "\red Unable to establish a connection: \black You're too far away from the station!"
- return
+ return 0
if( href_list["close"] )
- usr << browse(null, "window=crewcomp")
+ var/mob/user = usr
+ var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main")
usr.unset_machine()
- return
+ ui.close()
+ return 0
if(href_list["update"])
src.updateDialog()
- return
+ return 1
-
-/obj/machinery/computer/crew/interact(mob/user)
+/obj/machinery/computer/crew/interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
if(stat & (BROKEN|NOPOWER))
return
- if(!istype(user, /mob/living/silicon) && get_dist(src, user) > 1)
- user.unset_machine()
- user << browse(null, "window=powcomp")
- return
user.set_machine(src)
src.scan()
- var/t = "Crew Monitoring
"
- t += "
Refresh "
- t += "Close
"
- t += "| Name | Vitals | Position |
"
- var/list/logs = list()
+
+ var/data[0]
+ var/list/crewmembers = list()
+
for(var/obj/item/clothing/under/C in src.tracked)
- var/log = ""
+
+
var/turf/pos = get_turf(C)
+
if((C) && (C.has_sensor) && (pos) && (pos.z == src.z) && C.sensor_mode)
if(istype(C.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/H = C.loc
- var/dam1 = round(H.getOxyLoss(),1)
- var/dam2 = round(H.getToxLoss(),1)
- var/dam3 = round(H.getFireLoss(),1)
- var/dam4 = round(H.getBruteLoss(),1)
+ var/list/crewmemberData = list()
- var/life_status = "[H.stat > 1 ? "Deceased" : "Living"]"
- var/damage_report = "([dam1]/[dam2]/[dam3]/[dam4])"
+ crewmemberData["sensor_type"] = C.sensor_mode
+ crewmemberData["dead"] = H.stat > 1
+ crewmemberData["oxy"] = round(H.getOxyLoss(), 1)
+ crewmemberData["tox"] = round(H.getToxLoss(), 1)
+ crewmemberData["fire"] = round(H.getFireLoss(), 1)
+ crewmemberData["brute"] = round(H.getBruteLoss(), 1)
+ crewmemberData["name"] = (H.wear_id ? H.wear_id.name : "Unknown")
+ crewmemberData["area"] = get_area(H)
+ crewmemberData["x"] = pos.x
+ crewmemberData["y"] = pos.y
- if(H.wear_id)
- log += "| [H.wear_id.name] | "
- else
- log += "
| Unknown | "
+ // Works around list += list2 merging lists; it's not pretty but it works
+ crewmembers += "temporary item"
+ crewmembers[crewmembers.len] = crewmemberData
- switch(C.sensor_mode)
- if(1)
- log += "[life_status] | Not Available |
"
- if(2)
- log += "[life_status] [damage_report] | Not Available | "
- if(3)
- var/area/player_area = get_area(H)
- log += "[life_status] [damage_report] | [player_area.name] ([pos.x], [pos.y]) | "
- logs += log
- logs = sortList(logs)
- for(var/log in logs)
- t += log
- t += "
"
- t += ""
- user << browse(t, "window=crewcomp;size=900x600")
- onclose(user, "crewcomp")
+ crewmembers = sortByKey(crewmembers, "name")
+
+ data["crewmembers"] = crewmembers
+
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
+ if(!ui)
+ ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 600)
+ ui.set_initial_data(data)
+ ui.open()
+
+ // should make the UI auto-update; doesn't seem to?
+ ui.set_auto_update(1)
/obj/machinery/computer/crew/proc/scan()
diff --git a/nano/css/shared.css b/nano/css/shared.css
index b49b742344..650d956f64 100644
--- a/nano/css/shared.css
+++ b/nano/css/shared.css
@@ -519,5 +519,24 @@ th.misc
}
+/* Damage colors for crew monitoring computer */
+.burn
+{
+ color: orange;
+}
+.brute
+{
+ color: red;
+}
+
+.toxin
+{
+ color: green;
+}
+
+.oxyloss
+{
+ color: blue;
+}
diff --git a/nano/templates/crew_monitor.tmpl b/nano/templates/crew_monitor.tmpl
new file mode 100644
index 0000000000..b42e4a56ad
--- /dev/null
+++ b/nano/templates/crew_monitor.tmpl
@@ -0,0 +1,23 @@
+
+
+
+ Functions:
+
+
+ {{:~link('Refresh', 'refresh', {'update' : 1}, null)}}
+ {{:~link('Close', 'close', {'close' : 1}, null)}}
+
+
+
+ {{for crewmembers}}
+ {{if sensor_type == 1}}
+ | {{:name}} | {{:dead ? "Deceased" : "Living"}} | Not Available |
+ {{else sensor_type == 2}}
+ | {{:name}} | {{:dead ? "Deceased" : "Living"}} ({{:oxy}}/{{:tox}}/{{:fire}}/{{:brute}}) | Not Available |
+ {{else sensor_type == 3}}
+ | {{:name}} | {{:dead ? "Deceased" : "Living"}} ({{:oxy}}/{{:tox}}/{{:fire}}/{{:brute}}) | {{:area}}({{:x}}, {{:y}}) |
+ {{/if}}
+ {{/for}}
+
\ No newline at end of file