From 4e036c77e3df7a22cd11d5fa81a2461f04b2a224 Mon Sep 17 00:00:00 2001
From: Arthri <41360489+Arthri@users.noreply.github.com>
Date: Sun, 5 May 2024 06:10:53 +0800
Subject: [PATCH] /tg/ui Virology PanD.E.M.I.C 2200 (PanDEMIC) (#24533)
* /tg/ui PanDEMIC
* Fix types on booleans
* [ci skip]
* Fix oversights
[ci skip]
* Fix styling
* Apply suggestions from code review
Co-authored-by: Aylong <69762909+AyIong@users.noreply.github.com>
* Apply suggestions from code review
Co-authored-by: Aylong <69762909+AyIong@users.noreply.github.com>
* Remove unused field
* Optimize ui_data
* Make clone cooldown spin
* Change unit
[ci skip]
* Remove use of !!
* Fix Flex style prop accidental override
* Rewrite Stack to Flex
* Revert changes to Stack
* [ci skip]
* Build and update tgui
* Move force update code
* Build and update tgui
* trigger ci
* Fix style
---------
Co-authored-by: Arthri <41360489+a@users.noreply.github.com>
Co-authored-by: Aylong <69762909+AyIong@users.noreply.github.com>
Co-authored-by: /tg/ui Builder <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
---
code/controllers/subsystem/SStgui.dm | 7 +-
.../reagents/chemistry/machinery/pandemic.dm | 410 ++++++++++--------
tgui/packages/tgui/components/Flex.tsx | 5 +-
tgui/packages/tgui/interfaces/PanDEMIC.tsx | 374 ++++++++++++++++
.../tgui/styles/interfaces/PanDEMIC.scss | 30 ++
tgui/packages/tgui/styles/main.scss | 1 +
tgui/public/tgui-panel.bundle.js | 4 +-
tgui/public/tgui.bundle.css | 2 +-
tgui/public/tgui.bundle.js | 152 +++----
9 files changed, 715 insertions(+), 270 deletions(-)
create mode 100644 tgui/packages/tgui/interfaces/PanDEMIC.tsx
create mode 100644 tgui/packages/tgui/styles/interfaces/PanDEMIC.scss
diff --git a/code/controllers/subsystem/SStgui.dm b/code/controllers/subsystem/SStgui.dm
index d84c486c615..0f0392941d3 100644
--- a/code/controllers/subsystem/SStgui.dm
+++ b/code/controllers/subsystem/SStgui.dm
@@ -187,7 +187,7 @@ SUBSYSTEM_DEF(tgui)
*
* return int The number of UIs updated.
*/
-/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object)
+/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object, full_update = FALSE)
var/count = 0
var/key = "[src_object.UID()]"
// No UIs opened for this src_object
@@ -196,7 +196,10 @@ SUBSYSTEM_DEF(tgui)
for(var/datum/tgui/ui in open_uis_by_src[key])
// Check if UI is valid.
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user))
- ui.process(force = TRUE)
+ if(full_update)
+ ui.send_full_update(null, TRUE)
+ else
+ ui.process(force = TRUE)
count++
return count
diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm
index 51862c1a89c..1c07afabb50 100644
--- a/code/modules/reagents/chemistry/machinery/pandemic.dm
+++ b/code/modules/reagents/chemistry/machinery/pandemic.dm
@@ -11,6 +11,7 @@
var/temp_html = ""
var/printing = null
var/wait = null
+ var/selected_strain_index = 1
var/obj/item/reagent_containers/beaker = null
/obj/machinery/computer/pandemic/Initialize(mapload)
@@ -26,23 +27,33 @@
stat |= BROKEN
update_icon()
-/obj/machinery/computer/pandemic/proc/GetVirusByIndex(index)
+/obj/machinery/computer/pandemic/proc/GetViruses()
if(beaker && beaker.reagents)
if(length(beaker.reagents.reagent_list))
var/datum/reagent/blood/BL = locate() in beaker.reagents.reagent_list
if(BL)
if(BL.data && BL.data["viruses"])
var/list/viruses = BL.data["viruses"]
- return viruses[index]
+ return viruses
-/obj/machinery/computer/pandemic/proc/GetResistancesByIndex(index)
+/obj/machinery/computer/pandemic/proc/GetVirusByIndex(index)
+ var/list/viruses = GetViruses()
+ if(viruses && index > 0 && index <= length(viruses))
+ return viruses[index]
+
+/obj/machinery/computer/pandemic/proc/GetResistances()
if(beaker && beaker.reagents)
if(length(beaker.reagents.reagent_list))
var/datum/reagent/blood/BL = locate() in beaker.reagents.reagent_list
if(BL)
if(BL.data && BL.data["resistances"])
var/list/resistances = BL.data["resistances"]
- return resistances[index]
+ return resistances
+
+/obj/machinery/computer/pandemic/proc/GetResistancesByIndex(index)
+ var/list/resistances = GetResistances()
+ if(resistances && index > 0 && index <= length(resistances))
+ return resistances[index]
/obj/machinery/computer/pandemic/proc/GetVirusTypeByIndex(index)
var/datum/disease/D = GetVirusByIndex(index)
@@ -68,117 +79,233 @@
if(!wait)
. += "waitlight"
-/obj/machinery/computer/pandemic/Topic(href, href_list)
+/obj/machinery/computer/pandemic/proc/create_culture(name, bottle_type = "culture", cooldown = 50)
+ var/obj/item/reagent_containers/glass/bottle/B = new/obj/item/reagent_containers/glass/bottle(loc)
+ B.icon_state = "round_bottle"
+ B.pixel_x = rand(-3, 3)
+ B.pixel_y = rand(-3, 3)
+ replicator_cooldown(cooldown)
+ B.name = "[name] [bottle_type] bottle"
+ return B
+
+/obj/machinery/computer/pandemic/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
-
- usr.set_machine(src)
- if(!beaker) return
-
- if(href_list["create_vaccine"])
- if(!wait)
- var/obj/item/reagent_containers/glass/bottle/B = new/obj/item/reagent_containers/glass/bottle(loc)
- if(B)
- B.pixel_x = rand(-3, 3)
- B.pixel_y = rand(-3, 3)
- var/path = GetResistancesByIndex(text2num(href_list["create_vaccine"]))
- var/vaccine_type = path
- var/vaccine_name = "Unknown"
-
- if(!ispath(vaccine_type))
- if(GLOB.archive_diseases[path])
- var/datum/disease/D = GLOB.archive_diseases[path]
- if(D)
- vaccine_name = D.name
- vaccine_type = path
- else if(vaccine_type)
- var/datum/disease/D = new vaccine_type(0, null)
- if(D)
- vaccine_name = D.name
-
- if(vaccine_type)
-
- B.name = "[vaccine_name] vaccine bottle"
- B.reagents.add_reagent("vaccine", 15, list(vaccine_type))
- replicator_cooldown(200)
- else
- temp_html = "The replicator is not ready yet."
- updateUsrDialog()
+ if(inoperable())
return
- else if(href_list["create_virus_culture"])
- if(!wait)
- var/type = GetVirusTypeByIndex(text2num(href_list["create_virus_culture"]))//the path is received as string - converting
+
+
+ . = TRUE
+
+ switch(action)
+ if("clone_strain")
+ if(wait)
+ atom_say("The replicator is not ready yet.")
+ return
+
+ var/strain_index = text2num(params["strain_index"])
+ if(isnull(strain_index))
+ atom_say("Unable to respond to command.")
+ return
+ var/datum/disease/virus = GetVirusByIndex(strain_index)
var/datum/disease/D = null
+ if(!virus)
+ atom_say("Unable to find requested strain.")
+ return
+ var/type = virus.GetDiseaseID()
if(!ispath(type))
- D = GetVirusByIndex(text2num(href_list["create_virus_culture"]))
- var/datum/disease/advance/A = GLOB.archive_diseases[D.GetDiseaseID()]
+ var/datum/disease/advance/A = GLOB.archive_diseases[type]
if(A)
D = new A.type(0, A)
else if(type)
if(type in GLOB.diseases) // Make sure this is a disease
D = new type(0, null)
if(!D)
+ atom_say("Unable to synthesize requested strain.")
return
- var/name = tgui_input_text(usr, "Name:", "Name the culture", D.name, MAX_NAME_LEN)
+ var/default_name = ""
+ if(D.name == "Unknown" || D.name == "")
+ default_name = replacetext(beaker.name, new/regex(" culture bottle\\Z", "g"), "")
+ else
+ default_name = D.name
+ var/name = tgui_input_text(usr, "Name:", "Name the culture", default_name, MAX_NAME_LEN)
if(name == null || wait)
return
- var/obj/item/reagent_containers/glass/bottle/B = new/obj/item/reagent_containers/glass/bottle(loc)
- B.icon_state = "round_bottle"
- B.pixel_x = rand(-3, 3)
- B.pixel_y = rand(-3, 3)
- replicator_cooldown(50)
- var/list/data = list("viruses"=list(D))
- B.name = "[name] culture bottle"
+ var/obj/item/reagent_containers/glass/bottle/B = create_culture(name)
B.desc = "A small bottle. Contains [D.agent] culture in synthblood medium."
- B.reagents.add_reagent("blood",20,data)
- updateUsrDialog()
- else
- temp_html = "The replicator is not ready yet."
- updateUsrDialog()
- return
- else if(href_list["empty_beaker"])
- beaker.reagents.clear_reagents()
- eject_beaker()
- updateUsrDialog()
- return
- else if(href_list["eject"])
- eject_beaker()
- updateUsrDialog()
- return
- else if(href_list["clear"])
- temp_html = ""
- updateUsrDialog()
- return
- else if(href_list["name_disease"])
- var/new_name = tgui_input_text(usr, "Name the Disease", "New Name", max_length = MAX_NAME_LEN)
- if(!new_name)
- return
- if(..())
- return
- var/id = GetVirusTypeByIndex(text2num(href_list["name_disease"]))
- if(GLOB.archive_diseases[id])
- var/datum/disease/advance/A = GLOB.archive_diseases[id]
+ B.reagents.add_reagent("blood", 20, list("viruses" = list(D)))
+ if("clone_vaccine")
+ if(wait)
+ atom_say("The replicator is not ready yet.")
+ return
+
+ var/resistance_index = text2num(params["resistance_index"])
+ if(isnull(resistance_index))
+ atom_say("Unable to find requested antibody.")
+ return
+ var/vaccine_type = GetResistancesByIndex(resistance_index)
+ var/vaccine_name = "Unknown"
+ if(!ispath(vaccine_type))
+ if(GLOB.archive_diseases[vaccine_type])
+ var/datum/disease/D = GLOB.archive_diseases[vaccine_type]
+ if(D)
+ vaccine_name = D.name
+ else if(vaccine_type)
+ var/datum/disease/D = new vaccine_type(0, null)
+ if(D)
+ vaccine_name = D.name
+
+ if(!vaccine_type)
+ atom_say("Unable to synthesize requested antibody.")
+ return
+
+ var/obj/item/reagent_containers/glass/bottle/B = create_culture(vaccine_name, "vaccine", 200)
+ B.reagents.add_reagent("vaccine", 15, list(vaccine_type))
+ if("eject_beaker")
+ eject_beaker()
+ if("destroy_eject_beaker")
+ beaker.reagents.clear_reagents()
+ eject_beaker()
+ if("print_release_forms")
+ var/strain_index = text2num(params["strain_index"])
+ if(isnull(strain_index))
+ atom_say("Unable to respond to command.")
+ return
+ var/type = GetVirusTypeByIndex(strain_index)
+ if(!type)
+ atom_say("Unable to find requested strain.")
+ return
+ var/datum/disease/advance/A = GLOB.archive_diseases[type]
+ if(!A)
+ atom_say("Unable to find requested strain.")
+ return
+ print_form(A, usr)
+ if("name_strain")
+ var/strain_index = text2num(params["strain_index"])
+ if(isnull(strain_index))
+ atom_say("Unable to respond to command.")
+ return
+ var/type = GetVirusTypeByIndex(strain_index)
+ if(!type)
+ atom_say("Unable to find requested strain.")
+ return
+ var/datum/disease/advance/A = GLOB.archive_diseases[type]
+ if(!A)
+ atom_say("Unable to find requested strain.")
+ return
+ if(A.name != "Unknown")
+ atom_say("Request rejected. Strain already has a name.")
+ return
+ var/new_name = tgui_input_text(usr, "Name the Strain", "New Name", max_length = MAX_NAME_LEN)
+ if(!new_name)
+ return
A.AssignName(new_name)
for(var/datum/disease/advance/AD in GLOB.active_diseases)
AD.Refresh()
- updateUsrDialog()
- else if(href_list["print_form"])
- var/datum/disease/D = GetVirusByIndex(text2num(href_list["print_form"]))
- D = GLOB.archive_diseases[D.GetDiseaseID()]//We know it's advanced no need to check
- print_form(D, usr)
+ if("switch_strain")
+ var/strain_index = text2num(params["strain_index"])
+ if(isnull(strain_index) || strain_index < 1)
+ atom_say("Unable to respond to command.")
+ return
+ var/list/viruses = GetViruses()
+ if(strain_index > length(viruses))
+ atom_say("Unable to find requested strain.")
+ return
+ selected_strain_index = strain_index;
+ else
+ return FALSE
+/obj/machinery/computer/pandemic/ui_state(mob/user)
+ return GLOB.default_state
- else
- usr << browse(null, "window=pandemic")
- updateUsrDialog()
- return
+/obj/machinery/computer/pandemic/ui_interact(mob/user, datum/tgui/ui = null)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "PanDEMIC", name)
+ ui.open()
- add_fingerprint(usr)
+/obj/machinery/computer/pandemic/ui_data(mob/user)
+ var/datum/reagent/blood/Blood = null
+ if(beaker)
+ var/datum/reagents/R = beaker.reagents
+ for(var/datum/reagent/blood/B in R.reagent_list)
+ if(B)
+ Blood = B
+ break
+
+ var/list/data = list(
+ "synthesisCooldown" = wait ? TRUE : FALSE,
+ "beakerLoaded" = beaker ? TRUE : FALSE,
+ "beakerContainsBlood" = Blood ? TRUE : FALSE,
+ "beakerContainsVirus" = length(Blood?.data["viruses"]) != 0,
+ "selectedStrainIndex" = selected_strain_index,
+ )
+
+ return data
+
+/obj/machinery/computer/pandemic/ui_static_data(mob/user)
+ var/list/data = list()
+ . = data
+
+ var/datum/reagent/blood/Blood = null
+ if(beaker)
+ var/datum/reagents/R = beaker.reagents
+ for(var/datum/reagent/blood/B in R.reagent_list)
+ if(B)
+ Blood = B
+ break
+
+ var/list/strains = list()
+ for(var/datum/disease/D in GetViruses())
+ if(D.visibility_flags & HIDDEN_PANDEMIC)
+ continue
+
+ var/list/symptoms = list()
+ if(istype(D, /datum/disease/advance))
+ var/datum/disease/advance/A = D
+ D = GLOB.archive_diseases[A.GetDiseaseID()]
+ if(!D)
+ CRASH("We weren't able to get the advance disease from the archive.")
+ for(var/datum/symptom/S in A.symptoms)
+ symptoms += list(list(
+ "name" = S.name,
+ "stealth" = S.stealth,
+ "resistance" = S.resistance,
+ "stageSpeed" = S.stage_speed,
+ "transmissibility" = S.transmittable,
+ "complexity" = S.level,
+ ))
+
+ strains += list(list(
+ "commonName" = D.name,
+ "description" = D.desc,
+ "bloodDNA" = Blood.data["blood_DNA"],
+ "bloodType" = Blood.data["blood_type"],
+ "diseaseAgent" = D.agent,
+ "possibleTreatments" = D.cure_text,
+ "transmissionRoute" = D.spread_text,
+ "symptoms" = symptoms,
+ "isAdvanced" = istype(D, /datum/disease/advance),
+ ))
+ data["strains"] = strains
+
+ var/list/resistances = list()
+ for(var/resistance in GetResistances())
+ if(!ispath(resistance))
+ var/datum/disease/D = GLOB.archive_diseases[resistance]
+ if(D)
+ resistances += list(D.name)
+ else if(resistance)
+ var/datum/disease/D = new resistance(0, null)
+ if(D)
+ resistances += list(D.name)
+ data["resistances"] = resistances
/obj/machinery/computer/pandemic/proc/eject_beaker()
beaker.forceMove(loc)
beaker = null
icon_state = "pandemic0"
+ selected_strain_index = 1
//Prints a nice virus release form. Props to Urbanliner for the layout
/obj/machinery/computer/pandemic/proc/print_form(datum/disease/advance/D, mob/living/user)
@@ -241,108 +368,16 @@
P.info = info_text.Join("")
P.update_icon()
+/obj/machinery/computer/pandemic/attack_ai(mob/user)
+ return attack_hand(user)
+
/obj/machinery/computer/pandemic/attack_hand(mob/user)
if(..())
return
- user.set_machine(src)
- var/dat = ""
- if(temp_html)
- dat = "[temp_html]
Main Menu"
- else if(!beaker)
- dat += "Please insert beaker.
"
- dat += "Close"
- else
- var/datum/reagents/R = beaker.reagents
- var/datum/reagent/blood/Blood = null
- for(var/datum/reagent/blood/B in R.reagent_list)
- if(B)
- Blood = B
- break
- if(!R.total_volume||!length(R.reagent_list))
- dat += "The beaker is empty
"
- else if(!Blood)
- dat += "No blood sample found in beaker."
- else if(!Blood.data)
- dat += "No blood data found in beaker."
- else
- dat += "