diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm
index 53e47d9acfe..b8afc5cb720 100644
--- a/code/__defines/machinery.dm
+++ b/code/__defines/machinery.dm
@@ -163,3 +163,8 @@ if (!(DATUM.datum_flags & DF_ISPROCESSING)) {\
#define START_PROCESSING_POWER_OBJECT(Datum) START_PROCESSING_IN_LIST(Datum, global.processing_power_items)
#define STOP_PROCESSING_POWER_OBJECT(Datum) STOP_PROCESSING_IN_LIST(Datum, global.processing_power_items)
+
+// Computer login types
+#define LOGIN_TYPE_NORMAL 1
+#define LOGIN_TYPE_AI 2
+#define LOGIN_TYPE_ROBOT 3
\ No newline at end of file
diff --git a/code/__defines/tgui.dm b/code/__defines/tgui.dm
index a6708c8bb7a..3d706a4e0fa 100644
--- a/code/__defines/tgui.dm
+++ b/code/__defines/tgui.dm
@@ -16,4 +16,14 @@
/// Get a window id based on the provided pool index
#define TGUI_WINDOW_ID(index) "tgui-window-[index]"
/// Get a pool index of the provided window id
-#define TGUI_WINDOW_INDEX(window_id) text2num(copytext(window_id, 13))
\ No newline at end of file
+#define TGUI_WINDOW_INDEX(window_id) text2num(copytext(window_id, 13))
+
+/// Max length for Modal Input
+#define TGUI_MODAL_INPUT_MAX_LENGTH 1024
+/// Max length for Modal Input for names
+#define TGUI_MODAL_INPUT_MAX_LENGTH_NAME 64 // Names for generally anything don't go past 32, let alone 64.
+
+#define TGUI_MODAL_OPEN 1
+#define TGUI_MODAL_DELEGATE 2
+#define TGUI_MODAL_ANSWER 3
+#define TGUI_MODAL_CLOSE 4
\ No newline at end of file
diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm
index 194ec86d3d9..40dbaf49cbe 100644
--- a/code/_helpers/game.dm
+++ b/code/_helpers/game.dm
@@ -636,4 +636,62 @@ datum/projectile_data
min(list_x),
min(list_y),
max(list_x),
- max(list_y))
\ No newline at end of file
+ max(list_y))
+
+// Will recursively loop through an atom's contents and check for mobs, then it will loop through every atom in that atom's contents.
+// It will keep doing this until it checks every content possible. This will fix any problems with mobs, that are inside objects,
+// being unable to hear people due to being in a box within a bag.
+
+/proc/recursive_mob_check(var/atom/O, var/list/L = list(), var/recursion_limit = 3, var/client_check = 1, var/sight_check = 1, var/include_radio = 1)
+
+ //GLOB.debug_mob += O.contents.len
+ if(!recursion_limit)
+ return L
+ for(var/atom/A in O.contents)
+
+ if(ismob(A))
+ var/mob/M = A
+ if(client_check && !M.client)
+ L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio)
+ continue
+ if(sight_check && !isInSight(A, O))
+ continue
+ L |= M
+ //log_world("[recursion_limit] = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])")
+
+ else if(include_radio && istype(A, /obj/item/radio))
+ if(sight_check && !isInSight(A, O))
+ continue
+ L |= A
+
+ if(isobj(A) || ismob(A))
+ L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio)
+ return L
+
+// The old system would loop through lists for a total of 5000 per function call, in an empty server.
+// This new system will loop at around 1000 in an empty server.
+
+/proc/get_mobs_in_view(var/R, var/atom/source, var/include_clientless = FALSE)
+ // Returns a list of mobs in range of R from source. Used in radio and say code.
+
+ var/turf/T = get_turf(source)
+ var/list/hear = list()
+
+ if(!T)
+ return hear
+
+ var/list/range = hear(R, T)
+
+ for(var/atom/A in range)
+ if(ismob(A))
+ var/mob/M = A
+ if(M.client || include_clientless)
+ hear += M
+ //log_world("Start = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])")
+ else if(istype(A, /obj/item/radio))
+ hear += A
+
+ if(isobj(A) || ismob(A))
+ hear |= recursive_mob_check(A, hear, 3, 1, 0, 1)
+
+ return hear
\ No newline at end of file
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index be5f6b33db3..ff483432edd 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -445,6 +445,8 @@ var/global/list/PDA_Manifest = list()
G.fields["religion"] = "Unknown"
G.fields["photo_front"] = front
G.fields["photo_side"] = side
+ G.fields["photo-south"] = "'data:image/png;base64,[icon2base64(front)]'"
+ G.fields["photo-west"] = "'data:image/png;base64,[icon2base64(side)]'"
G.fields["notes"] = "No notes found."
if(hidden)
hidden_general += G
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index b1d994d3a36..1229a0a9cb6 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -12,6 +12,8 @@
var/throwpass = 0
var/germ_level = GERM_LEVEL_AMBIENT // The higher the germ level, the more germ on the atom.
var/simulated = 1 //filter for actions - used by lighting overlays
+ var/atom_say_verb = "says"
+ var/bubble_icon = "normal" ///what icon the atom uses for speechbubbles
var/fluorescent // Shows up under a UV light.
var/last_bumped = 0
@@ -610,3 +612,20 @@
"}
var/turf/T = get_turf(src)
. += "
[ADMIN_COORDJMP(T)]"
+
+/atom/proc/atom_say(message)
+ if(!message)
+ return
+ var/list/speech_bubble_hearers = list()
+ for(var/mob/M in get_mobs_in_view(7, src))
+ M.show_message("[src] [atom_say_verb], \"[message]\"", 2, null, 1)
+ if(M.client)
+ speech_bubble_hearers += M.client
+
+ if(length(speech_bubble_hearers))
+ var/image/I = image('icons/mob/talk.dmi', src, "[bubble_icon][say_test(message)]", FLY_LAYER)
+ I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
+ INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_hearers, 30)
+
+/atom/proc/speech_bubble(bubble_state = "", bubble_loc = src, list/bubble_recipients = list())
+ return
diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm
index b9b8f6db8a9..a72c92d47c3 100644
--- a/code/game/dna/dna_modifier.dm
+++ b/code/game/dna/dna_modifier.dm
@@ -5,6 +5,11 @@
#define DNA2_BUF_UE 2
#define DNA2_BUF_SE 4
+#define PAGE_UI "ui"
+#define PAGE_SE "se"
+#define PAGE_BUFFER "buffer"
+#define PAGE_REJUVENATORS "rejuvenators"
+
//list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0),
/datum/dna2/record
var/datum/dna/dna = null
@@ -38,6 +43,22 @@
ser["type"] = "se"
return ser
+/datum/dna2/record/proc/copy()
+ var/datum/dna2/record/newrecord = new /datum/dna2/record
+ newrecord.dna = dna.Clone()
+ newrecord.types = types
+ newrecord.name = name
+ newrecord.mind = mind
+ newrecord.ckey = ckey
+ newrecord.languages = languages
+ newrecord.implant = implant
+ newrecord.flavor = flavor
+ newrecord.gender = gender
+ newrecord.body_descriptors = body_descriptors.Copy()
+ newrecord.genetic_modifiers = genetic_modifiers.Copy()
+ return newrecord
+
+
/////////////////////////// DNA MACHINES
/obj/machinery/dna_scannernew
name = "\improper DNA modifier"
@@ -55,13 +76,28 @@
var/mob/living/carbon/occupant = null
var/obj/item/weapon/reagent_containers/glass/beaker = null
var/opened = 0
+ var/damage_coeff
+ var/scan_level
+ var/precision_coeff
/obj/machinery/dna_scannernew/Initialize()
. = ..()
default_apply_parts()
+ RefreshParts()
+
+/obj/machinery/dna_scannernew/RefreshParts()
+ scan_level = 0
+ damage_coeff = 0
+ precision_coeff = 0
+ for(var/obj/item/weapon/stock_parts/scanning_module/P in component_parts)
+ scan_level += P.rating
+ for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts)
+ precision_coeff = P.rating
+ for(var/obj/item/weapon/stock_parts/micro_laser/P in component_parts)
+ damage_coeff = P.rating
/obj/machinery/dna_scannernew/relaymove(mob/user as mob)
- if (user.stat)
+ if(user.stat)
return
src.go_out()
return
@@ -71,7 +107,7 @@
set category = "Object"
set name = "Eject DNA Scanner"
- if (usr.stat != 0)
+ if(usr.stat != 0)
return
eject_occupant()
@@ -98,15 +134,15 @@
set category = "Object"
set name = "Enter DNA Scanner"
- if (usr.stat != 0)
+ if(usr.stat != 0)
return
- if (!ishuman(usr) && !issmall(usr)) //Make sure they're a mob that has dna
+ if(!ishuman(usr) && !issmall(usr)) //Make sure they're a mob that has dna
to_chat(usr, "Try as you might, you can not climb up into the scanner.")
return
- if (src.occupant)
+ if(src.occupant)
to_chat(usr, "The scanner is already occupied!")
return
- if (usr.abiotic())
+ if(usr.abiotic())
to_chat(usr, "The subject cannot have abiotic items on.")
return
usr.stop_pulling()
@@ -116,7 +152,7 @@
src.occupant = usr
src.icon_state = "scanner_1"
src.add_fingerprint(usr)
- return
+ SStgui.update_uis(src)
/obj/machinery/dna_scannernew/attackby(var/obj/item/weapon/item as obj, var/mob/user as mob)
if(istype(item, /obj/item/weapon/reagent_containers/glass))
@@ -128,10 +164,11 @@
user.drop_item()
item.loc = src
user.visible_message("\The [user] adds \a [item] to \the [src]!", "You add \a [item] to \the [src]!")
+ SStgui.update_uis(src)
return
else if(istype(item, /obj/item/organ/internal/brain))
- if (src.occupant)
+ if(src.occupant)
to_chat(user, "The scanner is already occupied!")
return
var/obj/item/organ/internal/brain/brain = item
@@ -141,19 +178,20 @@
put_in(brain.brainmob)
src.add_fingerprint(user)
user.visible_message("\The [user] adds \a [item] to \the [src]!", "You add \a [item] to \the [src]!")
+ SStgui.update_uis(src)
return
else
to_chat(user, "\The [brain] is not acceptable for genetic sampling!")
- else if (!istype(item, /obj/item/weapon/grab))
+ else if(!istype(item, /obj/item/weapon/grab))
return
var/obj/item/weapon/grab/G = item
- if (!ismob(G.affecting))
+ if(!ismob(G.affecting))
return
- if (src.occupant)
+ if(src.occupant)
to_chat(user, "The scanner is already occupied!")
return
- if (G.affecting.abiotic())
+ if(G.affecting.abiotic())
to_chat(user, "The subject cannot have abiotic items on.")
return
put_in(G.affecting)
@@ -180,12 +218,12 @@
if(ghost.mind == M.mind)
to_chat(ghost, "Your corpse has been placed into a cloning scanner. Return to your body if you want to be resurrected/cloned! (Verbs -> Ghost -> Re-enter corpse)")
break
- return
+ SStgui.update_uis(src)
/obj/machinery/dna_scannernew/proc/go_out()
- if ((!( src.occupant ) || src.locked))
+ if((!( src.occupant ) || src.locked))
return
- if (src.occupant.client)
+ if(src.occupant.client)
src.occupant.client.eye = src.occupant.client.mob
src.occupant.client.perspective = MOB_PERSPECTIVE
if(istype(occupant,/mob/living/carbon/brain))
@@ -198,7 +236,7 @@
src.occupant.loc = src.loc
src.occupant = null
src.icon_state = "scanner_0"
- return
+ SStgui.update_uis(src)
/obj/machinery/dna_scannernew/ex_act(severity)
switch(severity)
@@ -211,7 +249,7 @@
qdel(src)
return
if(2.0)
- if (prob(50))
+ if(prob(50))
for(var/atom/movable/A as mob|obj in src)
A.loc = src.loc
ex_act(severity)
@@ -220,7 +258,7 @@
qdel(src)
return
if(3.0)
- if (prob(25))
+ if(prob(25))
for(var/atom/movable/A as mob|obj in src)
A.loc = src.loc
ex_act(severity)
@@ -251,21 +289,20 @@
var/injector_ready = 0 //Quick fix for issue 286 (screwdriver the screen twice to restore injector) -Pete
var/obj/machinery/dna_scannernew/connected = null
var/obj/item/weapon/disk/data/disk = null
- var/selected_menu_key = null
+ var/selected_menu_key = PAGE_UI
anchored = 1
use_power = USE_POWER_IDLE
idle_power_usage = 10
active_power_usage = 400
- var/waiting_for_user_input=0 // Fix for #274 (Mash create block injector without answering dialog to make unlimited injectors) - N3X
/obj/machinery/computer/scan_consolenew/attackby(obj/item/I as obj, mob/user as mob)
- if (istype(I, /obj/item/weapon/disk/data)) //INSERT SOME diskS
- if (!src.disk)
+ if(istype(I, /obj/item/weapon/disk/data)) //INSERT SOME diskS
+ if(!src.disk)
user.drop_item()
I.loc = src
src.disk = I
to_chat(user, "You insert [I].")
- SSnanoui.update_uis(src) // update all UIs attached to src
+ SStgui.update_uis(src) // update all UIs attached to src
return
else
..()
@@ -279,7 +316,7 @@
qdel(src)
return
if(2.0)
- if (prob(50))
+ if(prob(50))
//SN src = null
qdel(src)
return
@@ -315,35 +352,28 @@
/obj/machinery/computer/scan_consolenew/process() //not really used right now
if(stat & (NOPOWER|BROKEN))
return
- if (!( src.status )) //remove this
+ if(!( src.status )) //remove this
return
return
*/
/obj/machinery/computer/scan_consolenew/attack_ai(user as mob)
src.add_hiddenprint(user)
- ui_interact(user)
+ tgui_interact(user)
/obj/machinery/computer/scan_consolenew/attack_hand(user as mob)
if(!..())
- ui_interact(user)
-
- /**
- * The ui_interact proc is used to open and update Nano UIs
- * If ui_interact is not used then the UI will not update correctly
- * ui_interact is currently defined for /atom/movable (which is inherited by /obj and /mob)
- *
- * @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
- *
- * @return nothing
- */
-/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ tgui_interact(user)
+/obj/machinery/computer/scan_consolenew/tgui_interact(mob/user, datum/tgui/ui)
if(!connected || user == connected.occupant || user.stat)
return
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "DNAModifier", name)
+ ui.open()
+/obj/machinery/computer/scan_consolenew/tgui_data(mob/user)
// this is the data which will be sent to the ui
var/data[0]
data["selectedMenuKey"] = selected_menu_key
@@ -355,7 +385,7 @@
data["hasDisk"] = disk ? 1 : 0
var/diskData[0]
- if (!disk || !disk.buf)
+ if(!disk || !disk.buf)
diskData["data"] = null
diskData["owner"] = null
diskData["label"] = null
@@ -383,7 +413,7 @@
data["selectedUITargetHex"] = selected_ui_target_hex
var/occupantData[0]
- if (!src.connected.occupant || !src.connected.occupant.dna)
+ if(!src.connected.occupant || !src.connected.occupant.dna)
occupantData["name"] = null
occupantData["stat"] = null
occupantData["isViableSubject"] = null
@@ -398,7 +428,7 @@
occupantData["name"] = connected.occupant.real_name
occupantData["stat"] = connected.occupant.stat
occupantData["isViableSubject"] = 1
- if (NOCLONE in connected.occupant.mutations || !src.connected.occupant.dna)
+ if(NOCLONE in connected.occupant.mutations || !src.connected.occupant.dna)
occupantData["isViableSubject"] = 0
occupantData["health"] = connected.occupant.health
occupantData["maxHealth"] = connected.occupant.maxHealth
@@ -414,423 +444,357 @@
data["beakerVolume"] = 0
if(connected.beaker)
data["beakerLabel"] = connected.beaker.label_text ? connected.beaker.label_text : null
- if (connected.beaker.reagents && connected.beaker.reagents.reagent_list.len)
+ if(connected.beaker.reagents && connected.beaker.reagents.reagent_list.len)
for(var/datum/reagent/R in connected.beaker.reagents.reagent_list)
data["beakerVolume"] += R.volume
- // update the ui if it exists, returns null if no ui is passed/found
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- // the ui does not exist, so we'll create a new() one
- // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
- ui = new(user, src, ui_key, "dna_modifier.tmpl", "DNA Modifier Console", 660, 700)
- // when the ui is first opened this is the data it will use
- ui.set_initial_data(data)
- // open the new ui window
- ui.open()
- // auto update every Master Controller tick
- ui.set_auto_update(1)
+ // Transfer modal information if there is one
+ data["modal"] = tgui_modal_data(src)
-/obj/machinery/computer/scan_consolenew/Topic(href, href_list)
+ return data
+
+/obj/machinery/computer/scan_consolenew/tgui_act(action, params)
if(..())
- return 0 // don't update uis
+ return FALSE // don't update uis
if(!istype(usr.loc, /turf))
- return 0 // don't update uis
+ return FALSE // don't update uis
if(!src || !src.connected)
- return 0 // don't update uis
+ return FALSE // don't update uis
if(irradiating) // Make sure that it isn't already irradiating someone...
- return 0 // don't update uis
+ return FALSE // don't update uis
add_fingerprint(usr)
- if (href_list["selectMenuKey"])
- selected_menu_key = href_list["selectMenuKey"]
- return 1 // return 1 forces an update to all Nano uis attached to src
+ if(tgui_act_modal(action, params))
+ return TRUE
- if (href_list["toggleLock"])
- if ((src.connected && src.connected.occupant))
- src.connected.locked = !( src.connected.locked )
- return 1 // return 1 forces an update to all Nano uis attached to src
-
- if (href_list["pulseRadiation"])
- irradiating = src.radiation_duration
- var/lock_state = src.connected.locked
- src.connected.locked = 1//lock it
- SSnanoui.update_uis(src) // update all UIs attached to src
-
- sleep(10*src.radiation_duration) // sleep for radiation_duration seconds
-
- irradiating = 0
-
- if (!src.connected.occupant)
- return 1 // return 1 forces an update to all Nano uis attached to src
-
- if (prob(95))
- if(prob(75))
- randmutb(src.connected.occupant)
- else
- randmuti(src.connected.occupant)
- else
- if(prob(95))
- randmutg(src.connected.occupant)
- else
- randmuti(src.connected.occupant)
-
- src.connected.occupant.apply_effect(((src.radiation_intensity*3)+src.radiation_duration*3), IRRADIATE, check_protection = 0)
- src.connected.locked = lock_state
- return 1 // return 1 forces an update to all Nano uis attached to src
-
- if (href_list["radiationDuration"])
- if (text2num(href_list["radiationDuration"]) > 0)
- if (src.radiation_duration < 20)
- src.radiation_duration += 2
- else
- if (src.radiation_duration > 2)
- src.radiation_duration -= 2
- return 1 // return 1 forces an update to all Nano uis attached to src
-
- if (href_list["radiationIntensity"])
- if (text2num(href_list["radiationIntensity"]) > 0)
- if (src.radiation_intensity < 10)
- src.radiation_intensity++
- else
- if (src.radiation_intensity > 1)
- src.radiation_intensity--
- return 1 // return 1 forces an update to all Nano uis attached to src
-
- ////////////////////////////////////////////////////////
-
- if (href_list["changeUITarget"] && text2num(href_list["changeUITarget"]) > 0)
- if (src.selected_ui_target < 15)
- src.selected_ui_target++
- src.selected_ui_target_hex = src.selected_ui_target
- switch(selected_ui_target)
- if(10)
- src.selected_ui_target_hex = "A"
- if(11)
- src.selected_ui_target_hex = "B"
- if(12)
- src.selected_ui_target_hex = "C"
- if(13)
- src.selected_ui_target_hex = "D"
- if(14)
- src.selected_ui_target_hex = "E"
- if(15)
- src.selected_ui_target_hex = "F"
- else
- src.selected_ui_target = 0
- src.selected_ui_target_hex = 0
- return 1 // return 1 forces an update to all Nano uis attached to src
-
- if (href_list["changeUITarget"] && text2num(href_list["changeUITarget"]) < 1)
- if (src.selected_ui_target > 0)
- src.selected_ui_target--
- src.selected_ui_target_hex = src.selected_ui_target
- switch(selected_ui_target)
- if(10)
- src.selected_ui_target_hex = "A"
- if(11)
- src.selected_ui_target_hex = "B"
- if(12)
- src.selected_ui_target_hex = "C"
- if(13)
- src.selected_ui_target_hex = "D"
- if(14)
- src.selected_ui_target_hex = "E"
- else
- src.selected_ui_target = 15
- src.selected_ui_target_hex = "F"
- return 1 // return 1 forces an update to all Nano uis attached to src
-
- if (href_list["selectUIBlock"] && href_list["selectUISubblock"]) // This chunk of code updates selected block / sub-block based on click
- var/select_block = text2num(href_list["selectUIBlock"])
- var/select_subblock = text2num(href_list["selectUISubblock"])
- if ((select_block <= DNA_UI_LENGTH) && (select_block >= 1))
- src.selected_ui_block = select_block
- if ((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1))
- src.selected_ui_subblock = select_subblock
- return 1 // return 1 forces an update to all Nano uis attached to src
-
- if (href_list["pulseUIRadiation"])
- var/block = src.connected.occupant.dna.GetUISubBlock(src.selected_ui_block,src.selected_ui_subblock)
-
- irradiating = src.radiation_duration
- var/lock_state = src.connected.locked
- src.connected.locked = 1//lock it
- SSnanoui.update_uis(src) // update all UIs attached to src
-
- sleep(10*src.radiation_duration) // sleep for radiation_duration seconds
-
- irradiating = 0
-
- if (!src.connected.occupant)
- return 1
-
- if (prob((80 + (src.radiation_duration / 2))))
- block = miniscrambletarget(num2text(selected_ui_target), src.radiation_intensity, src.radiation_duration)
- src.connected.occupant.dna.SetUISubBlock(src.selected_ui_block,src.selected_ui_subblock,block)
- src.connected.occupant.UpdateAppearance()
- src.connected.occupant.apply_effect((src.radiation_intensity+src.radiation_duration), IRRADIATE, check_protection = 0)
- else
- if (prob(20+src.radiation_intensity))
- randmutb(src.connected.occupant)
- domutcheck(src.connected.occupant,src.connected)
- else
- randmuti(src.connected.occupant)
- src.connected.occupant.UpdateAppearance()
- src.connected.occupant.apply_effect(((src.radiation_intensity*2)+src.radiation_duration), IRRADIATE, check_protection = 0)
- src.connected.locked = lock_state
- return 1 // return 1 forces an update to all Nano uis attached to src
-
- ////////////////////////////////////////////////////////
-
- if (href_list["injectRejuvenators"])
- if (!connected.occupant)
- return 0
- var/inject_amount = round(text2num(href_list["injectRejuvenators"]), 5) // round to nearest 5
- if (inject_amount < 0) // Since the user can actually type the commands himself, some sanity checking
- inject_amount = 0
- if (inject_amount > 50)
- inject_amount = 50
- connected.beaker.reagents.trans_to_mob(connected.occupant, inject_amount, CHEM_BLOOD)
- return 1 // return 1 forces an update to all Nano uis attached to src
-
- ////////////////////////////////////////////////////////
-
- if (href_list["selectSEBlock"] && href_list["selectSESubblock"]) // This chunk of code updates selected block / sub-block based on click (se stands for strutural enzymes)
- var/select_block = text2num(href_list["selectSEBlock"])
- var/select_subblock = text2num(href_list["selectSESubblock"])
- if ((select_block <= DNA_SE_LENGTH) && (select_block >= 1))
- src.selected_se_block = select_block
- if ((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1))
- src.selected_se_subblock = select_subblock
- //testing("User selected block [selected_se_block] (sent [select_block]), subblock [selected_se_subblock] (sent [select_block]).")
- return 1 // return 1 forces an update to all Nano uis attached to src
-
- if (href_list["pulseSERadiation"])
- var/block = src.connected.occupant.dna.GetSESubBlock(src.selected_se_block,src.selected_se_subblock)
- //var/original_block=block
- //testing("Irradiating SE block [src.selected_se_block]:[src.selected_se_subblock] ([block])...")
-
- irradiating = src.radiation_duration
- var/lock_state = src.connected.locked
- src.connected.locked = 1 //lock it
- SSnanoui.update_uis(src) // update all UIs attached to src
-
- sleep(10*src.radiation_duration) // sleep for radiation_duration seconds
-
- irradiating = 0
-
- if(src.connected.occupant)
- if (prob((80 + (src.radiation_duration / 2))))
- // FIXME: Find out what these corresponded to and change them to the WHATEVERBLOCK they need to be.
- //if ((src.selected_se_block != 2 || src.selected_se_block != 12 || src.selected_se_block != 8 || src.selected_se_block || 10) && prob (20))
- var/real_SE_block=selected_se_block
- block = miniscramble(block, src.radiation_intensity, src.radiation_duration)
- if(prob(20))
- if (src.selected_se_block > 1 && src.selected_se_block < DNA_SE_LENGTH/2)
- real_SE_block++
- else if (src.selected_se_block > DNA_SE_LENGTH/2 && src.selected_se_block < DNA_SE_LENGTH)
- real_SE_block--
-
- //testing("Irradiated SE block [real_SE_block]:[src.selected_se_subblock] ([original_block] now [block]) [(real_SE_block!=selected_se_block) ? "(SHIFTED)":""]!")
- connected.occupant.dna.SetSESubBlock(real_SE_block,selected_se_subblock,block)
- src.connected.occupant.apply_effect((src.radiation_intensity+src.radiation_duration), IRRADIATE, check_protection = 0)
- domutcheck(src.connected.occupant,src.connected)
- else
- src.connected.occupant.apply_effect(((src.radiation_intensity*2)+src.radiation_duration), IRRADIATE, check_protection = 0)
- if (prob(80-src.radiation_duration))
- //testing("Random bad mut!")
- randmutb(src.connected.occupant)
- domutcheck(src.connected.occupant,src.connected)
- else
- randmuti(src.connected.occupant)
- //testing("Random identity mut!")
- src.connected.occupant.UpdateAppearance()
- src.connected.locked = lock_state
- return 1 // return 1 forces an update to all Nano uis attached to src
-
- if(href_list["ejectBeaker"])
- if(connected.beaker)
- var/obj/item/weapon/reagent_containers/glass/B = connected.beaker
- B.loc = connected.loc
- connected.beaker = null
- return 1
-
- if(href_list["ejectOccupant"])
- connected.eject_occupant()
- return 1
-
- // Transfer Buffer Management
- if(href_list["bufferOption"])
- var/bufferOption = href_list["bufferOption"]
-
- // These bufferOptions do not require a bufferId
- if (bufferOption == "wipeDisk")
- if ((isnull(src.disk)) || (src.disk.read_only))
- //src.temphtml = "Invalid disk. Please try again."
- return 0
-
- src.disk.buf=null
- //src.temphtml = "Data saved."
- return 1
-
- if (bufferOption == "ejectDisk")
- if (!src.disk)
+ . = TRUE
+ switch(action)
+ if("selectMenuKey")
+ var/key = params["key"]
+ if(!(key in list(PAGE_UI, PAGE_SE, PAGE_BUFFER, PAGE_REJUVENATORS)))
return
- src.disk.loc = get_turf(src)
- src.disk = null
- return 1
+ selected_menu_key = key
+ if("toggleLock")
+ if(connected && connected.occupant)
+ connected.locked = !(connected.locked)
- // All bufferOptions from here on require a bufferId
- if (!href_list["bufferId"])
- return 0
+ if("pulseRadiation")
+ irradiating = radiation_duration
+ var/lock_state = connected.locked
+ connected.locked = TRUE //lock it
- var/bufferId = text2num(href_list["bufferId"])
-
- if (bufferId < 1 || bufferId > 3)
- return 0 // Not a valid buffer id
-
- if (bufferOption == "saveUI")
- if(src.connected.occupant && src.connected.occupant.dna)
- var/datum/dna2/record/databuf=new
- databuf.types = DNA2_BUF_UE
- databuf.dna = src.connected.occupant.dna.Clone()
- if(ishuman(connected.occupant))
- var/mob/living/carbon/human/H = connected.occupant
- databuf.dna.real_name = H.dna.real_name
- databuf.gender = H.gender
- databuf.body_descriptors = H.descriptors
- databuf.name = "Unique Identifier"
- src.buffers[bufferId] = databuf
- return 1
-
- if (bufferOption == "saveUIAndUE")
- if(src.connected.occupant && src.connected.occupant.dna)
- var/datum/dna2/record/databuf=new
- databuf.types = DNA2_BUF_UI|DNA2_BUF_UE
- databuf.dna = src.connected.occupant.dna.Clone()
- if(ishuman(connected.occupant))
- var/mob/living/carbon/human/H = connected.occupant
- databuf.dna.real_name = H.dna.real_name
- databuf.gender = H.gender
- databuf.body_descriptors = H.descriptors
- databuf.name = "Unique Identifier + Unique Enzymes"
- src.buffers[bufferId] = databuf
- return 1
-
- if (bufferOption == "saveSE")
- if(src.connected.occupant && src.connected.occupant.dna)
- var/datum/dna2/record/databuf=new
- databuf.types = DNA2_BUF_SE
- databuf.dna = src.connected.occupant.dna.Clone()
- if(ishuman(connected.occupant))
- var/mob/living/carbon/human/H = connected.occupant
- databuf.dna.real_name = H.dna.real_name
- databuf.gender = H.gender
- databuf.body_descriptors = H.descriptors
- databuf.name = "Structural Enzymes"
- src.buffers[bufferId] = databuf
- return 1
-
- if (bufferOption == "clear")
- src.buffers[bufferId]=new /datum/dna2/record()
- return 1
-
- if (bufferOption == "changeLabel")
- var/datum/dna2/record/buf = src.buffers[bufferId]
- var/text = sanitize(input(usr, "New Label:", "Edit Label", buf.name) as text|null, MAX_NAME_LEN)
- buf.name = text
- src.buffers[bufferId] = buf
- return 1
-
- if (bufferOption == "transfer")
- if (!src.connected.occupant || (NOCLONE in src.connected.occupant.mutations) || !src.connected.occupant.dna)
- return
-
- irradiating = 2
- var/lock_state = src.connected.locked
- src.connected.locked = 1//lock it
- SSnanoui.update_uis(src) // update all UIs attached to src
-
- sleep(10*2) // sleep for 2 seconds
+ SStgui.update_uis(src) // update all UIs attached to src
+ sleep(10 * radiation_duration) // sleep for radiation_duration seconds
irradiating = 0
- src.connected.locked = lock_state
+ connected.locked = lock_state
- var/datum/dna2/record/buf = src.buffers[bufferId]
+ if(!connected.occupant)
+ return
- if ((buf.types & DNA2_BUF_UI))
- if ((buf.types & DNA2_BUF_UE))
- src.connected.occupant.real_name = buf.dna.real_name
- src.connected.occupant.name = buf.dna.real_name
- if(ishuman(connected.occupant))
- var/mob/living/carbon/human/H = connected.occupant
- H.gender = buf.gender
- H.descriptors = buf.body_descriptors
- src.connected.occupant.UpdateAppearance(buf.dna.UI.Copy())
- else if (buf.types & DNA2_BUF_SE)
- src.connected.occupant.dna.SE = buf.dna.SE
- src.connected.occupant.dna.UpdateSE()
- if(ishuman(connected.occupant))
- var/mob/living/carbon/human/H = connected.occupant
- H.gender = buf.gender
- H.descriptors = buf.body_descriptors
- domutcheck(src.connected.occupant,src.connected)
- src.connected.occupant.apply_effect(rand(20,50), IRRADIATE, check_protection = 0)
- return 1
-
- if (bufferOption == "createInjector")
- if (src.injector_ready || waiting_for_user_input)
-
- var/success = 1
- var/obj/item/weapon/dnainjector/I = new /obj/item/weapon/dnainjector
- var/datum/dna2/record/buf = src.buffers[bufferId]
- if(href_list["createBlockInjector"])
- waiting_for_user_input=1
- var/list/selectedbuf
- if(buf.types & DNA2_BUF_SE)
- selectedbuf=buf.dna.SE
- else
- selectedbuf=buf.dna.UI
- var/blk = input(usr,"Select Block","Block") in all_dna_blocks(selectedbuf)
- success = setInjectorBlock(I,blk,buf)
+ if(prob(95))
+ if(prob(75))
+ randmutb(connected.occupant)
else
- I.buf = buf
- waiting_for_user_input=0
- if(success)
- I.loc = src.loc
- I.name += " ([buf.name])"
- //src.temphtml = "Injector created."
- src.injector_ready = 0
- spawn(300)
- src.injector_ready = 1
- //else
- //src.temphtml = "Error in injector creation."
- //else
- //src.temphtml = "Replicator not ready yet."
- return 1
+ randmuti(connected.occupant)
+ else
+ if(prob(95))
+ randmutg(connected.occupant)
+ else
+ randmuti(connected.occupant)
- if (bufferOption == "loadDisk")
- if ((isnull(src.disk)) || (!src.disk.buf))
- //src.temphtml = "Invalid disk. Please try again."
- return 0
+ connected.occupant.apply_effect(((radiation_intensity*3)+radiation_duration*3), IRRADIATE, check_protection = 0)
+ if("radiationDuration")
+ radiation_duration = clamp(text2num(params["value"]), 1, 20)
+ if("radiationIntensity")
+ radiation_intensity = clamp(text2num(params["value"]), 1, 10)
+ ////////////////////////////////////////////////////////
+ if("changeUITarget")
+ selected_ui_target = clamp(text2num(params["value"]), 1, 15)
+ selected_ui_target_hex = num2text(selected_ui_target, 1, 16)
+ if("selectUIBlock") // This chunk of code updates selected block / sub-block based on click
+ var/select_block = text2num(params["block"])
+ var/select_subblock = text2num(params["subblock"])
+ if(!select_block || !select_subblock)
+ return
- src.buffers[bufferId]=src.disk.buf
- //src.temphtml = "Data loaded."
- return 1
+ selected_ui_block = clamp(select_block, 1, DNA_UI_LENGTH)
+ selected_ui_subblock = clamp(select_subblock, 1, DNA_BLOCK_SIZE)
+ if("pulseUIRadiation")
+ var/block = connected.occupant.dna.GetUISubBlock(selected_ui_block,selected_ui_subblock)
- if (bufferOption == "saveDisk")
- if ((isnull(src.disk)) || (src.disk.read_only))
- //src.temphtml = "Invalid disk. Please try again."
- return 0
+ irradiating = radiation_duration
+ var/lock_state = connected.locked
+ connected.locked = TRUE //lock it
- var/datum/dna2/record/buf = src.buffers[bufferId]
+ SStgui.update_uis(src) // update all UIs attached to src
+ sleep(10 * radiation_duration) // sleep for radiation_duration seconds
- src.disk.buf = buf
- src.disk.name = "data disk - '[buf.dna.real_name]'"
- //src.temphtml = "Data saved."
- return 1
+ irradiating = 0
+ connected.locked = lock_state
+
+ if(!connected.occupant)
+ return
+
+ if(prob((80 + (radiation_duration / 2))))
+ block = miniscrambletarget(num2text(selected_ui_target), radiation_intensity, radiation_duration)
+ connected.occupant.dna.SetUISubBlock(selected_ui_block,selected_ui_subblock,block)
+ connected.occupant.UpdateAppearance()
+ connected.occupant.apply_effect((radiation_intensity+radiation_duration), IRRADIATE, check_protection = 0)
+ else
+ if(prob(20 + radiation_intensity))
+ randmutb(connected.occupant)
+ domutcheck(connected.occupant,connected)
+ else
+ randmuti(connected.occupant)
+ connected.occupant.UpdateAppearance()
+ connected.occupant.apply_effect(((radiation_intensity*2)+radiation_duration), IRRADIATE, check_protection = 0)
+ ////////////////////////////////////////////////////////
+ if("injectRejuvenators")
+ if(!connected.occupant || !connected.beaker)
+ return
+ var/inject_amount = clamp(round(text2num(params["amount"]), 5), 0, 50) // round to nearest 5 and clamp to 0-50
+ if(!inject_amount)
+ return
+ connected.beaker.reagents.trans_to_mob(connected.occupant, inject_amount, CHEM_BLOOD)
+ ////////////////////////////////////////////////////////
+ if("selectSEBlock") // This chunk of code updates selected block / sub-block based on click (se stands for strutural enzymes)
+ var/select_block = text2num(params["block"])
+ var/select_subblock = text2num(params["subblock"])
+ if(!select_block || !select_subblock)
+ return
+
+ selected_se_block = clamp(select_block, 1, DNA_SE_LENGTH)
+ selected_se_subblock = clamp(select_subblock, 1, DNA_BLOCK_SIZE)
+ if("pulseSERadiation")
+ var/block = connected.occupant.dna.GetSESubBlock(selected_se_block,selected_se_subblock)
+ //var/original_block=block
+ //testing("Irradiating SE block [selected_se_block]:[selected_se_subblock] ([block])...")
+
+ irradiating = radiation_duration
+ var/lock_state = connected.locked
+ connected.locked = TRUE //lock it
+
+ SStgui.update_uis(src) // update all UIs attached to src
+ sleep(10 * radiation_duration) // sleep for radiation_duration seconds
+
+ irradiating = 0
+ connected.locked = lock_state
+
+ if(connected.occupant)
+ if(prob((80 + (radiation_duration / 2))))
+ // FIXME: Find out what these corresponded to and change them to the WHATEVERBLOCK they need to be.
+ //if((selected_se_block != 2 || selected_se_block != 12 || selected_se_block != 8 || selected_se_block || 10) && prob (20))
+ var/real_SE_block=selected_se_block
+ block = miniscramble(block, radiation_intensity, radiation_duration)
+ if(prob(20))
+ if(selected_se_block > 1 && selected_se_block < DNA_SE_LENGTH/2)
+ real_SE_block++
+ else if(selected_se_block > DNA_SE_LENGTH/2 && selected_se_block < DNA_SE_LENGTH)
+ real_SE_block--
+
+ //testing("Irradiated SE block [real_SE_block]:[selected_se_subblock] ([original_block] now [block]) [(real_SE_block!=selected_se_block) ? "(SHIFTED)":""]!")
+ connected.occupant.dna.SetSESubBlock(real_SE_block,selected_se_subblock,block)
+ connected.occupant.apply_effect((radiation_intensity+radiation_duration), IRRADIATE, check_protection = 0)
+ domutcheck(connected.occupant,connected)
+ else
+ connected.occupant.apply_effect(((radiation_intensity*2)+radiation_duration), IRRADIATE, check_protection = 0)
+ if (prob(80-radiation_duration))
+ //testing("Random bad mut!")
+ randmutb(connected.occupant)
+ domutcheck(connected.occupant,connected)
+ else
+ randmuti(connected.occupant)
+ //testing("Random identity mut!")
+ connected.occupant.UpdateAppearance()
+ if("ejectBeaker")
+ if(connected.beaker)
+ var/obj/item/weapon/reagent_containers/glass/B = connected.beaker
+ B.loc = connected.loc
+ connected.beaker = null
+ if("ejectOccupant")
+ connected.eject_occupant()
+ // Transfer Buffer Management
+ if("bufferOption")
+ var/bufferOption = params["option"]
+ var/bufferId = text2num(params["id"])
+ if(bufferId < 1 || bufferId > 3) // Not a valid buffer id
+ return
+
+ var/datum/dna2/record/buffer = buffers[bufferId]
+ switch(bufferOption)
+ if("saveUI")
+ if(connected.occupant && connected.occupant.dna)
+ var/datum/dna2/record/databuf=new
+ databuf.types = DNA2_BUF_UI // DNA2_BUF_UE
+ databuf.dna = connected.occupant.dna.Clone()
+ if(ishuman(connected.occupant))
+ var/mob/living/carbon/human/H = connected.occupant
+ databuf.dna.real_name = H.dna.real_name
+ databuf.gender = H.gender
+ databuf.body_descriptors = H.descriptors
+ databuf.name = "Unique Identifier"
+ buffers[bufferId] = databuf
+ if("saveUIAndUE")
+ if(connected.occupant && connected.occupant.dna)
+ var/datum/dna2/record/databuf=new
+ databuf.types = DNA2_BUF_UI|DNA2_BUF_UE
+ databuf.dna = connected.occupant.dna.Clone()
+ if(ishuman(connected.occupant))
+ var/mob/living/carbon/human/H = connected.occupant
+ databuf.dna.real_name = H.dna.real_name
+ databuf.gender = H.gender
+ databuf.body_descriptors = H.descriptors
+ databuf.name = "Unique Identifier + Unique Enzymes"
+ buffers[bufferId] = databuf
+ if("saveSE")
+ if(connected.occupant && connected.occupant.dna)
+ var/datum/dna2/record/databuf=new
+ databuf.types = DNA2_BUF_SE
+ databuf.dna = connected.occupant.dna.Clone()
+ if(ishuman(connected.occupant))
+ var/mob/living/carbon/human/H = connected.occupant
+ databuf.dna.real_name = H.dna.real_name
+ databuf.gender = H.gender
+ databuf.body_descriptors = H.descriptors
+ databuf.name = "Structural Enzymes"
+ buffers[bufferId] = databuf
+ if("clear")
+ buffers[bufferId] = new /datum/dna2/record()
+ if("changeLabel")
+ tgui_modal_input(src, "changeBufferLabel", "Please enter the new buffer label:", null, list("id" = bufferId), buffer.name, TGUI_MODAL_INPUT_MAX_LENGTH_NAME)
+ if("transfer")
+ if(!connected.occupant || (NOCLONE in connected.occupant.mutations) || !connected.occupant.dna)
+ return
+
+ irradiating = 2
+ var/lock_state = connected.locked
+ connected.locked = 1//lock it
+
+ SStgui.update_uis(src) // update all UIs attached to src
+ sleep(2 SECONDS) // sleep for 2 seconds
+
+ irradiating = 0
+ connected.locked = lock_state
+
+ var/datum/dna2/record/buf = buffers[bufferId]
+
+ if((buf.types & DNA2_BUF_UI))
+ if((buf.types & DNA2_BUF_UE))
+ connected.occupant.real_name = buf.dna.real_name
+ connected.occupant.name = buf.dna.real_name
+ if(ishuman(connected.occupant))
+ var/mob/living/carbon/human/H = connected.occupant
+ H.gender = buf.gender
+ H.descriptors = buf.body_descriptors
+ connected.occupant.UpdateAppearance(buf.dna.UI.Copy())
+ else if(buf.types & DNA2_BUF_SE)
+ connected.occupant.dna.SE = buf.dna.SE
+ connected.occupant.dna.UpdateSE()
+ if(ishuman(connected.occupant))
+ var/mob/living/carbon/human/H = connected.occupant
+ H.gender = buf.gender
+ H.descriptors = buf.body_descriptors
+ domutcheck(connected.occupant,connected)
+ connected.occupant.apply_effect(rand(20,50), IRRADIATE, check_protection = 0)
+ if("createInjector")
+ if(!injector_ready)
+ return
+ if(text2num(params["block"]) > 0)
+ var/list/choices = all_dna_blocks((buffer.types & DNA2_BUF_SE) ? buffer.dna.SE : buffer.dna.UI)
+ tgui_modal_choice(src, "createInjectorBlock", "Please select the block to create an injector from:", null, list("id" = bufferId), null, choices)
+ else
+ create_injector(bufferId, TRUE)
+ if("loadDisk")
+ if(isnull(disk) || disk.read_only)
+ return
+ buffers[bufferId] = disk.buf.copy()
+ if("saveDisk")
+ if(isnull(disk) || disk.read_only)
+ return
+ var/datum/dna2/record/buf = buffers[bufferId]
+ disk.buf = buf.copy()
+ disk.name = "data disk - '[buf.dna.real_name]'"
+
+ if("wipeDisk")
+ if(isnull(disk) || disk.read_only)
+ return
+ disk.buf = null
+ if("ejectDisk")
+ if(!disk)
+ return
+ disk.forceMove(get_turf(src))
+ disk = null
+
+/**
+ * Creates a blank injector with the name of the buffer at the given buffer_id
+ *
+ * Arguments:
+ * * buffer_id - The ID of the buffer
+ * * copy_buffer - Whether the injector should copy the buffer contents
+ */
+/obj/machinery/computer/scan_consolenew/proc/create_injector(buffer_id, copy_buffer = FALSE)
+ if(buffer_id < 1 || buffer_id > length(buffers))
+ return
+
+ // Cooldown
+ injector_ready = FALSE
+ addtimer(CALLBACK(src, .proc/injector_cooldown_finish), 30 SECONDS)
+
+ // Create it
+ var/datum/dna2/record/buf = buffers[buffer_id]
+ var/obj/item/weapon/dnainjector/I = new()
+ I.forceMove(loc)
+ I.name += " ([buf.name])"
+ if(copy_buffer)
+ I.buf = buf.copy()
+ return I
+
+/**
+ * Called when the injector creation cooldown finishes
+ */
+/obj/machinery/computer/scan_consolenew/proc/injector_cooldown_finish()
+ injector_ready = TRUE
+
+/**
+ * Called in tgui_act() to process modal actions
+ *
+ * Arguments:
+ * * action - The action passed by tgui
+ * * params - The params passed by tgui
+ */
+/obj/machinery/computer/scan_consolenew/proc/tgui_act_modal(action, params)
+ . = TRUE
+ var/id = params["id"] // The modal's ID
+ var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"]
+ switch(tgui_modal_act(src, action, params))
+ if(TGUI_MODAL_ANSWER)
+ var/answer = params["answer"]
+ switch(id)
+ if("createInjectorBlock")
+ var/buffer_id = text2num(arguments["id"])
+ if(buffer_id < 1 || buffer_id > length(buffers))
+ return
+ var/datum/dna2/record/buf = buffers[buffer_id]
+ var/obj/item/weapon/dnainjector/I = create_injector(buffer_id)
+ setInjectorBlock(I, answer, buf.copy())
+ if("changeBufferLabel")
+ var/buffer_id = text2num(arguments["id"])
+ if(buffer_id < 1 || buffer_id > length(buffers))
+ return
+ var/datum/dna2/record/buf = buffers[buffer_id]
+ buf.name = answer
+ buffers[buffer_id] = buf
+ else
+ return FALSE
+ else
+ return FALSE
-/////////////////////////// DNA MACHINES
+#undef PAGE_UI
+#undef PAGE_SE
+#undef PAGE_BUFFER
+#undef PAGE_REJUVENATORS
+
+/////////////////////////// DNA MACHINES
\ No newline at end of file
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index c19873fd3d8..242bdf89ad5 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -51,7 +51,7 @@
return
if(sleeper)
- return ui_interact(user)
+ return tgui_interact(user)
/obj/machinery/sleep_console/attackby(var/obj/item/I, var/mob/user)
if(computer_deconstruction_screwdriver(user, I))
@@ -66,97 +66,21 @@
else
icon_state = initial(icon_state)
-/obj/machinery/sleep_console/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = outside_state)
- var/data[0]
-
- var/obj/machinery/sleeper/S = sleeper
- var/mob/living/carbon/human/occupant = sleeper.occupant
-
- data["power"] = S.stat & (NOPOWER|BROKEN) ? 0 : 1
-
- var/list/reagents = list()
- for(var/T in S.available_chemicals)
- var/list/reagent = list()
- reagent["id"] = T
- reagent["name"] = S.available_chemicals[T]
- if(occupant)
- reagent["amount"] = occupant.reagents.get_reagent_amount(T)
- reagents += list(reagent)
- data["reagents"] = reagents.Copy()
-
- if(occupant)
- data["occupant"] = 1
- switch(occupant.stat)
- if(CONSCIOUS)
- data["stat"] = "Conscious"
- if(UNCONSCIOUS)
- data["stat"] = "Unconscious"
- if(DEAD)
- data["stat"] = "Dead"
- data["health"] = occupant.health
- data["maxHealth"] = occupant.getMaxHealth()
- if(iscarbon(occupant))
- var/mob/living/carbon/C = occupant
- data["pulse"] = C.get_pulse(GETPULSE_TOOL)
- data["brute"] = occupant.getBruteLoss()
- data["burn"] = occupant.getFireLoss()
- data["oxy"] = occupant.getOxyLoss()
- data["tox"] = occupant.getToxLoss()
- else
- data["occupant"] = 0
- if(S.beaker)
- data["beaker"] = S.beaker.reagents.get_free_space()
- else
- data["beaker"] = -1
- data["filtering"] = S.filtering
- data["pump"] = S.pumping
-
- var/stasis_level_name = "Error!"
- for(var/N in S.stasis_choices)
- if(S.stasis_choices[N] == S.stasis_level)
- stasis_level_name = N
- break
- data["stasis"] = stasis_level_name
-
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
+/obj/machinery/sleep_console/tgui_interact(mob/user, datum/tgui/ui = null)
+ ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
- ui = new(user, src, ui_key, "sleeper.tmpl", "Sleeper UI", 600, 600, state = state)
- ui.set_initial_data(data)
+ ui = new(user, src, "Sleeper", "Sleeper")
ui.open()
- ui.set_auto_update(1)
-/obj/machinery/sleep_console/Topic(href, href_list)
- if(..())
- return 1
+/obj/machinery/sleep_console/tgui_data(mob/user)
+ if(sleeper)
+ return sleeper.tgui_data(user)
+ return null
- var/obj/machinery/sleeper/S = sleeper
-
- if(usr == S.occupant)
- to_chat(usr, "You can't reach the controls from the inside.")
- return
-
- add_fingerprint(usr)
-
- if(href_list["eject"])
- S.go_out()
- if(href_list["beaker"])
- S.remove_beaker()
- if(href_list["sleeper_filter"])
- if(S.filtering != text2num(href_list["sleeper_filter"]))
- S.toggle_filter()
- if(href_list["pump"])
- if(S.pumping != text2num(href_list["pump"]))
- S.toggle_pump()
- if(href_list["chemical"] && href_list["amount"])
- if(S.occupant && S.occupant.stat != DEAD)
- if(href_list["chemical"] in S.available_chemicals) // Your hacks are bad and you should feel bad
- S.inject_chemical(usr, href_list["chemical"], text2num(href_list["amount"]))
- if(href_list["change_stasis"])
- var/new_stasis = input("Levels deeper than 50% stasis level will render the patient unconscious.","Stasis Level") as null|anything in S.stasis_choices
- if(new_stasis && CanUseTopic(usr, default_state) == STATUS_INTERACTIVE)
- S.stasis_level = S.stasis_choices[new_stasis]
-
- return 1
+/obj/machinery/sleep_console/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state)
+ if(sleeper)
+ return sleeper.tgui_act(action, params, ui, state)
+ return FALSE
/obj/machinery/sleeper
name = "sleeper"
@@ -169,12 +93,19 @@
var/mob/living/carbon/human/occupant = null
var/list/available_chemicals = list()
var/list/base_chemicals = list("inaprovaline" = "Inaprovaline", "paracetamol" = "Paracetamol", "anti_toxin" = "Dylovene", "dexalin" = "Dexalin")
+ var/amounts = list(5, 10)
var/obj/item/weapon/reagent_containers/glass/beaker = null
var/filtering = 0
var/pumping = 0
+ // Currently never changes. On Paradise, max_chem and min_health are based on the matter bins in the sleeper.
+ var/max_chem = 20
+ var/initial_bin_rating = 1
+ var/min_health = -25
var/obj/machinery/sleep_console/console
var/stasis_level = 0 //Every 'this' life ticks are applied to the mob (when life_ticks%stasis_level == 1)
var/stasis_choices = list("Complete (1%)" = 100, "Deep (10%)" = 10, "Moderate (20%)" = 5, "Light (50%)" = 2, "None (100%)" = 0)
+ var/controls_inside = FALSE
+ var/auto_eject_dead = FALSE
use_power = USE_POWER_IDLE
idle_power_usage = 15
@@ -184,6 +115,7 @@
. = ..()
beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
default_apply_parts()
+ update_icon()
/obj/machinery/sleeper/Destroy()
if(console)
@@ -232,14 +164,187 @@
available_chemicals += new_chemicals
return
-/obj/machinery/sleeper/Initialize()
- . = ..()
- update_icon()
+/obj/machinery/sleeper/attack_hand(var/mob/user)
+ if(!controls_inside)
+ return FALSE
+
+ if(user == occupant)
+ tgui_interact(user)
+
+/obj/machinery/sleeper/tgui_interact(mob/user, datum/tgui/ui = null)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "Sleeper", "Sleeper")
+ ui.open()
+
+/obj/machinery/sleeper/tgui_data(mob/user)
+ var/data[0]
+ data["amounts"] = amounts
+ data["hasOccupant"] = occupant ? 1 : 0
+ var/occupantData[0]
+ // var/crisis = 0
+ if(occupant)
+ occupantData["name"] = occupant.name
+ occupantData["stat"] = occupant.stat
+ occupantData["health"] = occupant.health
+ occupantData["maxHealth"] = occupant.maxHealth
+ occupantData["minHealth"] = config.health_threshold_dead
+ occupantData["bruteLoss"] = occupant.getBruteLoss()
+ occupantData["oxyLoss"] = occupant.getOxyLoss()
+ occupantData["toxLoss"] = occupant.getToxLoss()
+ occupantData["fireLoss"] = occupant.getFireLoss()
+ occupantData["paralysis"] = occupant.paralysis
+ occupantData["hasBlood"] = 0
+ occupantData["bodyTemperature"] = occupant.bodytemperature
+ occupantData["maxTemp"] = 1000 // If you get a burning vox armalis into the sleeper, congratulations
+ // Because we can put simple_animals in here, we need to do something tricky to get things working nice
+ occupantData["temperatureSuitability"] = 0 // 0 is the baseline
+ if(ishuman(occupant) && occupant.species)
+ // I wanna do something where the bar gets bluer as the temperature gets lower
+ // For now, I'll just use the standard format for the temperature status
+ var/datum/species/sp = occupant.species
+ if(occupant.bodytemperature < sp.cold_level_3)
+ occupantData["temperatureSuitability"] = -3
+ else if(occupant.bodytemperature < sp.cold_level_2)
+ occupantData["temperatureSuitability"] = -2
+ else if(occupant.bodytemperature < sp.cold_level_1)
+ occupantData["temperatureSuitability"] = -1
+ else if(occupant.bodytemperature > sp.heat_level_3)
+ occupantData["temperatureSuitability"] = 3
+ else if(occupant.bodytemperature > sp.heat_level_2)
+ occupantData["temperatureSuitability"] = 2
+ else if(occupant.bodytemperature > sp.heat_level_1)
+ occupantData["temperatureSuitability"] = 1
+ else if(isanimal(occupant))
+ var/mob/living/simple_mob/silly = occupant
+ if(silly.bodytemperature < silly.minbodytemp)
+ occupantData["temperatureSuitability"] = -3
+ else if(silly.bodytemperature > silly.maxbodytemp)
+ occupantData["temperatureSuitability"] = 3
+ // Blast you, imperial measurement system
+ occupantData["btCelsius"] = occupant.bodytemperature - T0C
+ occupantData["btFaren"] = ((occupant.bodytemperature - T0C) * (9.0/5.0))+ 32
+
+
+ // crisis = (occupant.health < min_health)
+ // I'm not sure WHY you'd want to put a simple_animal in a sleeper, but precedent is precedent
+ // Runtime is aptly named, isn't she?
+ if(ishuman(occupant) && !(NO_BLOOD in occupant.species.flags) && occupant.vessel)
+ occupantData["pulse"] = occupant.get_pulse(GETPULSE_TOOL)
+ occupantData["hasBlood"] = 1
+ var/blood_volume = round(occupant.vessel.get_reagent_amount("blood"))
+ occupantData["bloodLevel"] = blood_volume
+ occupantData["bloodMax"] = occupant.species.blood_volume
+ occupantData["bloodPercent"] = round(100*(blood_volume/occupant.species.blood_volume), 0.01) //copy pasta ends here
+
+ occupantData["bloodType"] = occupant.dna.b_type
+
+ data["occupant"] = occupantData
+ data["maxchem"] = max_chem
+ data["minhealth"] = min_health
+ data["dialysis"] = filtering
+ data["stomachpumping"] = pumping
+ data["auto_eject_dead"] = auto_eject_dead
+ if(beaker)
+ data["isBeakerLoaded"] = 1
+ if(beaker.reagents)
+ data["beakerMaxSpace"] = beaker.reagents.maximum_volume
+ data["beakerFreeSpace"] = beaker.reagents.get_free_space()
+ else
+ data["beakerMaxSpace"] = 0
+ data["beakerFreeSpace"] = 0
+ else
+ data["isBeakerLoaded"] = FALSE
+
+
+ var/stasis_level_name = "Error!"
+ for(var/N in stasis_choices)
+ if(stasis_choices[N] == stasis_level)
+ stasis_level_name = N
+ break
+ data["stasis"] = stasis_level_name
+
+ var/chemicals[0]
+ for(var/re in available_chemicals)
+ var/datum/reagent/temp = SSchemistry.chemical_reagents[re]
+ if(temp)
+ var/reagent_amount = 0
+ var/pretty_amount
+ var/injectable = occupant ? 1 : 0
+ var/overdosing = 0
+ var/caution = 0 // To make things clear that you're coming close to an overdose
+ // if(crisis && !(temp.id in emergency_chems))
+ // injectable = 0
+
+ if(occupant && occupant.reagents)
+ reagent_amount = occupant.reagents.get_reagent_amount(temp.id)
+ // If they're mashing the highest concentration, they get one warning
+ if(temp.overdose && reagent_amount + 10 > (temp.overdose * occupant?.species.chemOD_threshold))
+ caution = 1
+ if(temp.overdose && reagent_amount > (temp.overdose * occupant?.species.chemOD_threshold))
+ overdosing = 1
+
+ pretty_amount = round(reagent_amount, 0.05)
+
+ chemicals.Add(list(list("title" = temp.name, "id" = temp.id, "commands" = list("chemical" = temp.id), "occ_amount" = reagent_amount, "pretty_amount" = pretty_amount, "injectable" = injectable, "overdosing" = overdosing, "od_warning" = caution)))
+ data["chemicals"] = chemicals
+ return data
+
+
+/obj/machinery/sleeper/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state)
+ if(..())
+ return
+ if(!controls_inside && usr == occupant)
+ return
+ if(panel_open)
+ to_chat(usr, "Close the maintenance panel first.")
+ return
+
+ . = TRUE
+ switch(action)
+ if("chemical")
+ if(!occupant)
+ return
+ if(occupant.stat == DEAD)
+ var/datum/gender/G = gender_datums[occupant.get_visible_gender()]
+ to_chat(usr, "This person has no life to preserve anymore. Take [G.him] to a department capable of reanimating [G.him].")
+ return
+ var/chemical = params["chemid"]
+ var/amount = text2num(params["amount"])
+ if(!length(chemical) || amount <= 0)
+ return
+ if(occupant.health > min_health) //|| (chemical in emergency_chems))
+ inject_chemical(usr, chemical, amount)
+ else
+ to_chat(usr, "This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!")
+ if("removebeaker")
+ remove_beaker()
+ if("togglefilter")
+ toggle_filter()
+ if("togglepump")
+ toggle_pump()
+ if("ejectify")
+ go_out()
+ if("changestasis")
+ var/new_stasis = input("Levels deeper than 50% stasis level will render the patient unconscious.","Stasis Level") as null|anything in stasis_choices
+ if(new_stasis)
+ stasis_level = stasis_choices[new_stasis]
+ if("auto_eject_dead_on")
+ auto_eject_dead = TRUE
+ if("auto_eject_dead_off")
+ auto_eject_dead = FALSE
+ else
+ return FALSE
+ add_fingerprint(usr)
/obj/machinery/sleeper/process()
if(stat & (NOPOWER|BROKEN))
return
if(occupant)
+ if(auto_eject_dead && occupant.stat == DEAD)
+ playsound(loc, 'sound/machines/buzz-sigh.ogg', 40)
+ go_out()
+ return
occupant.Stasis(stasis_level)
if(filtering > 0)
@@ -404,9 +509,11 @@
/obj/machinery/sleeper/proc/inject_chemical(var/mob/living/user, var/chemical, var/amount)
if(stat & (BROKEN|NOPOWER))
return
+ if(!(amount in amounts))
+ return
if(occupant && occupant.reagents)
- if(occupant.reagents.get_reagent_amount(chemical) + amount <= 20)
+ if(occupant.reagents.get_reagent_amount(chemical) + amount <= max_chem)
use_power(amount * CHEM_SYNTH_ENERGY)
occupant.reagents.add_reagent(chemical, amount)
to_chat(user, "Occupant now has [occupant.reagents.get_reagent_amount(chemical)] units of [available_chemicals[chemical]] in their bloodstream.")
diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm
index 482988caf27..8d06be107eb 100644
--- a/code/game/machinery/adv_med.dm
+++ b/code/game/machinery/adv_med.dm
@@ -1,7 +1,7 @@
// Pretty much everything here is stolen from the dna scanner FYI
/obj/machinery/bodyscanner
- var/mob/living/carbon/occupant
+ var/mob/living/carbon/human/occupant
var/locked
name = "Body Scanner"
icon = 'icons/obj/Cryogenic2.dmi'
@@ -14,6 +14,8 @@
active_power_usage = 10000 //10 kW. It's a big all-body scanner.
light_color = "#00FF00"
var/obj/machinery/body_scanconsole/console
+ var/known_implants = list(/obj/item/weapon/implant/health, /obj/item/weapon/implant/chem, /obj/item/weapon/implant/death_alarm, /obj/item/weapon/implant/loyalty, /obj/item/weapon/implant/tracking, /obj/item/weapon/implant/language, /obj/item/weapon/implant/language/eal, /obj/item/weapon/implant/backup, /obj/item/device/nif) //VOREStation Add - Backup Implant, NIF
+ var/printing_text = null
/obj/machinery/bodyscanner/Initialize()
. = ..()
@@ -57,13 +59,14 @@
update_icon() //icon_state = "body_scanner_1" //VOREStation Edit - Health display for consoles with light and such.
add_fingerprint(user)
qdel(G)
+ SStgui.update_uis(src)
if(!occupant)
if(default_deconstruction_screwdriver(user, G))
return
if(default_deconstruction_crowbar(user, G))
return
-/obj/machinery/bodyscanner/MouseDrop_T(mob/living/carbon/O, mob/user as mob)
+/obj/machinery/bodyscanner/MouseDrop_T(mob/living/carbon/human/O, mob/user as mob)
if(!istype(O))
return 0 //not a mob
if(user.incapacitated())
@@ -99,6 +102,7 @@
occupant = O
update_icon() //icon_state = "body_scanner_1" //VOREStation Edit - Health display for consoles with light and such.
add_fingerprint(user)
+ SStgui.update_uis(src)
/obj/machinery/bodyscanner/relaymove(mob/user as mob)
if(user.incapacitated())
@@ -124,6 +128,7 @@
occupant.loc = src.loc
occupant = null
update_icon() //icon_state = "body_scanner_1" //VOREStation Edit - Health display for consoles with light and such.
+ SStgui.update_uis(src)
return
/obj/machinery/bodyscanner/ex_act(severity)
@@ -157,10 +162,349 @@
else
return
+/obj/machinery/bodyscanner/tgui_interact(mob/user, datum/tgui/ui = null)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "BodyScanner", "Body Scanner")
+ ui.open()
+
+/obj/machinery/bodyscanner/tgui_data(mob/user)
+ var/list/data = list()
+
+ data["occupied"] = occupant ? TRUE : FALSE
+
+ var/occupantData[0]
+ if(occupant && ishuman(occupant))
+ update_icon() //VOREStation Edit - Health display for consoles with light and such.
+ var/mob/living/carbon/human/H = occupant
+ occupantData["name"] = H.name
+ occupantData["stat"] = H.stat
+ occupantData["health"] = H.health
+ occupantData["maxHealth"] = H.getMaxHealth()
+
+ occupantData["hasVirus"] = H.virus2.len
+
+ occupantData["bruteLoss"] = H.getBruteLoss()
+ occupantData["oxyLoss"] = H.getOxyLoss()
+ occupantData["toxLoss"] = H.getToxLoss()
+ occupantData["fireLoss"] = H.getFireLoss()
+
+ occupantData["radLoss"] = H.radiation
+ occupantData["cloneLoss"] = H.getCloneLoss()
+ occupantData["brainLoss"] = H.getBrainLoss()
+ occupantData["paralysis"] = H.paralysis
+ occupantData["paralysisSeconds"] = round(H.paralysis / 4)
+ occupantData["bodyTempC"] = H.bodytemperature-T0C
+ occupantData["bodyTempF"] = (((H.bodytemperature-T0C) * 1.8) + 32)
+
+ occupantData["hasBorer"] = H.has_brain_worms()
+
+ var/bloodData[0]
+ if(H.vessel)
+ var/blood_volume = round(H.vessel.get_reagent_amount("blood"))
+ var/blood_max = H.species.blood_volume
+ bloodData["volume"] = blood_volume
+ bloodData["percent"] = round(((blood_volume / blood_max)*100))
+
+ occupantData["blood"] = bloodData
+
+ var/reagentData[0]
+ if(H.reagents.reagent_list.len >= 1)
+ for(var/datum/reagent/R in H.reagents.reagent_list)
+ reagentData[++reagentData.len] = list("name" = R.name, "amount" = R.volume)
+ else
+ reagentData = null
+
+ occupantData["reagents"] = reagentData
+
+ var/ingestedData[0]
+ if(H.ingested.reagent_list.len >= 1)
+ for(var/datum/reagent/R in H.ingested.reagent_list)
+ ingestedData[++ingestedData.len] = list("name" = R.name, "amount" = R.volume)
+ else
+ ingestedData = null
+
+ occupantData["ingested"] = ingestedData
+
+ var/extOrganData[0]
+ for(var/obj/item/organ/external/E in H.organs)
+ var/organData[0]
+ organData["name"] = E.name
+ organData["open"] = E.open
+ organData["germ_level"] = E.germ_level
+ organData["bruteLoss"] = E.brute_dam
+ organData["fireLoss"] = E.burn_dam
+ organData["totalLoss"] = E.brute_dam + E.burn_dam
+ organData["maxHealth"] = E.max_damage
+ organData["bruised"] = E.min_bruised_damage
+ organData["broken"] = E.min_broken_damage
+
+ var/implantData[0]
+ for(var/obj/I in E.implants)
+ var/implantSubData[0]
+ implantSubData["name"] = I.name
+ if(is_type_in_list(I, known_implants))
+ implantSubData["known"] = 1
+
+ implantData.Add(list(implantSubData))
+
+ organData["implants"] = implantData
+ organData["implants_len"] = implantData.len
+
+ var/organStatus[0]
+ if(E.status & ORGAN_DESTROYED)
+ organStatus["destroyed"] = 1
+ if(E.status & ORGAN_BROKEN)
+ organStatus["broken"] = E.broken_description
+ if(E.robotic >= ORGAN_ROBOT)
+ organStatus["robotic"] = 1
+ if(E.splinted)
+ organStatus["splinted"] = 1
+ if(E.status & ORGAN_BLEEDING)
+ organStatus["bleeding"] = 1
+ if(E.status & ORGAN_DEAD)
+ organStatus["dead"] = 1
+
+ organData["status"] = organStatus
+
+ if(istype(E, /obj/item/organ/external/chest) && H.is_lung_ruptured())
+ organData["lungRuptured"] = 1
+
+ for(var/datum/wound/W in E.wounds)
+ if(W.internal)
+ organData["internalBleeding"] = 1
+ break
+
+ extOrganData.Add(list(organData))
+
+ occupantData["extOrgan"] = extOrganData
+
+ var/intOrganData[0]
+ for(var/obj/item/organ/I in H.internal_organs)
+ var/organData[0]
+ organData["name"] = I.name
+ if(I.status & ORGAN_ASSISTED)
+ organData["desc"] = "Assisted"
+ else if(I.robotic >= ORGAN_ROBOT)
+ organData["desc"] = "Mechanical"
+ else
+ organData["desc"] = null
+ organData["germ_level"] = I.germ_level
+ organData["damage"] = I.damage
+ organData["maxHealth"] = I.max_damage
+ organData["bruised"] = I.min_bruised_damage
+ organData["broken"] = I.min_broken_damage
+ organData["robotic"] = (I.robotic >= ORGAN_ROBOT)
+ organData["dead"] = (I.status & ORGAN_DEAD)
+
+ intOrganData.Add(list(organData))
+
+ occupantData["intOrgan"] = intOrganData
+
+ occupantData["blind"] = (H.sdisabilities & BLIND)
+ occupantData["nearsighted"] = (H.disabilities & NEARSIGHTED)
+ occupantData = attempt_vr(src, "get_occupant_data_vr", list(occupantData, H)) //VOREStation Insert
+ data["occupant"] = occupantData
+
+ return data
+
+/obj/machinery/bodyscanner/tgui_act(action, params)
+ if(..())
+ return
+
+ . = TRUE
+ switch(action)
+ if("ejectify")
+ eject()
+ if("print_p")
+ var/atom/target = console ? console : src
+ visible_message("[target] rattles and prints out a sheet of paper.")
+ var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(get_turf(target))
+ var/name = occupant ? occupant.name : "Unknown"
+ P.info = "
| Organ | " + dat += "Burn Damage | " + dat += "Brute Damage | " + dat += "Other Wounds | " + dat += "||||
|---|---|---|---|---|---|---|---|
| [e.name] | [e.burn_dam] | [e.brute_dam] | [robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured][o_dead] | " + else + dat += "[e.name] | - | - | Not Found | " + dat += "
| [i.name] | N/A | [i.damage] | [infection]:[mech][i_dead] | " + dat += " |
| Organ | " - dat += "Burn Damage | " - dat += "Brute Damage | " - dat += "Other Wounds | " - dat += "||||
|---|---|---|---|---|---|---|---|
| [e.name] | [e.burn_dam] | [e.brute_dam] | [robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured][o_dead] | " - else - dat += "[e.name] | - | - | Not Found | " - dat += "
| [i.name] | N/A | [i.damage] | [infection]:[mech][i_dead] | " - dat += " |
| Name: [active1.fields["name"]] \
- ID: [active1.fields["id"]] \n \ - Entity Classification: [active1.fields["brain_type"]] \n \ - Sex: [active1.fields["sex"]] \n" - if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2))) - dat += "Gender identity: [active2.fields["id_gender"]] " + add_fingerprint(user) + tgui_interact(user) + + +/obj/machinery/computer/med_data/tgui_interact(mob/user, datum/tgui/ui = null) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "MedicalRecords", "Medical Records") // 800, 380 + ui.open() + ui.set_autoupdate(FALSE) + + +/obj/machinery/computer/med_data/tgui_data(mob/user) + var/data[0] + data["temp"] = temp + data["scan"] = scan ? scan.name : null + data["authenticated"] = authenticated + data["rank"] = rank + data["screen"] = screen + data["printing"] = printing + data["isAI"] = isAI(user) + data["isRobot"] = isrobot(user) + if(authenticated) + switch(screen) + if(MED_DATA_R_LIST) + if(!isnull(data_core.general)) + var/list/records = list() + data["records"] = records + for(var/datum/data/record/R in sortRecord(data_core.general)) + records[++records.len] = list("ref" = "\ref[R]", "id" = R.fields["id"], "name" = R.fields["name"]) + if(MED_DATA_RECORD) + var/list/general = list() + data["general"] = general + if(istype(active1, /datum/data/record) && data_core.general.Find(active1)) + var/list/fields = list() + general["fields"] = fields + fields[++fields.len] = FIELD("Name", active1.fields["name"], null) + fields[++fields.len] = FIELD("ID", active1.fields["id"], null) + fields[++fields.len] = FIELD("Sex", active1.fields["sex"], "sex") + fields[++fields.len] = FIELD("Age", active1.fields["age"], "age") + fields[++fields.len] = FIELD("Fingerprint", active1.fields["fingerprint"], "fingerprint") + fields[++fields.len] = FIELD("Physical Status", active1.fields["p_stat"], "p_stat") + fields[++fields.len] = FIELD("Mental Status", active1.fields["m_stat"], "m_stat") + var/list/photos = list() + general["photos"] = photos + photos[++photos.len] = active1.fields["photo-south"] + photos[++photos.len] = active1.fields["photo-west"] + general["has_photos"] = (active1.fields["photo-south"] || active1.fields["photo-west"] ? 1 : 0) + general["empty"] = 0 + else + general["empty"] = 1 + + var/list/medical = list() + data["medical"] = medical + if(istype(active2, /datum/data/record) && data_core.medical.Find(active2)) + var/list/fields = list() + medical["fields"] = fields + fields[++fields.len] = MED_FIELD("Gender identity", active2.fields["id_gender"], "id_gender", TRUE) + fields[++fields.len] = MED_FIELD("Blood Type", active2.fields["b_type"], "blood_type", FALSE) + fields[++fields.len] = MED_FIELD("DNA", active2.fields["b_dna"], "b_dna", TRUE) + fields[++fields.len] = MED_FIELD("Brain Type", active2.fields["brain_type"], "brain_type", TRUE) + fields[++fields.len] = MED_FIELD("Important Notes", active2.fields["notes"], "notes", TRUE) + if(!active2.fields["comments"] || !islist(active2.fields["comments"])) + active2.fields["comments"] = list() + medical["comments"] = active2.fields["comments"] + medical["empty"] = 0 + else + medical["empty"] = 1 + if(MED_DATA_V_DATA) + data["virus"] = list() + for(var/ID in virusDB) + var/datum/data/record/v = virusDB[ID] + data["virus"] += list(list("name" = v.fields["name"], "D" = v)) + if(MED_DATA_MEDBOT) + data["medbots"] = list() + for(var/mob/living/bot/medbot/M in mob_list) + if(M.z != z) + continue + var/turf/T = get_turf(M) + if(T) + var/medbot = list() + var/area/A = get_area(T) + medbot["name"] = M.name + medbot["area"] = A.name + medbot["x"] = T.x + medbot["y"] = T.y + medbot["on"] = M.on + if(!isnull(M.reagent_glass) && M.use_beaker) + medbot["use_beaker"] = 1 + medbot["total_volume"] = M.reagent_glass.reagents.total_volume + medbot["maximum_volume"] = M.reagent_glass.reagents.maximum_volume else - dat += "Gender identity: Unknown " - dat += "Age: [active1.fields["age"]] \n \ - Fingerprint: [active1.fields["fingerprint"]] \n \ - Physical Status: [active1.fields["p_stat"]] \n \ - Mental Status: [active1.fields["m_stat"]] | \
- Photo:![]() ![]() |
| Brute: | -{{:data.occupant.bruteLoss}} | -Brain: | -{{:data.occupant.brainLoss}} | -
| Burn: | -{{:data.occupant.fireLoss}} | -Radiation: | -{{:data.occupant.radLoss}} | -
| Oxygen: | -{{:data.occupant.oxyLoss}} | -Genetic: | -{{:data.occupant.cloneLoss}} | -
| Toxins: | -{{:data.occupant.toxLoss}} | -Paralysis: | -{{:data.occupant.paralysis}}% ({{:data.occupant.paralysisSeconds}} seconds left!) | -
| Body Temperature: | -{{:helper.round(data.occupant.bodyTempC*10)/10}}°C, {{:helper.round(data.occupant.bodyTempF*10)/10}}°F | -||
| Body Weight: | -{{:helper.round(data.occupant.weight)}} lbs, {{:helper.round( - data.occupant.weight/2.20463)}} kgs | - {{if data.occupant.humanPrey}} -||
| Foreign Humanoids: | -{{:data.occupant.humanPrey}} | -||
| Foreign Creatures: | -{{:data.occupant.livingPrey}} | -||
| Foreign Objects: | -{{:data.occupant.objectPrey}} | -
| Volume: | -{{:data.occupant.blood.volume}} | -Percent: | -{{:data.occupant.blood.percent}}% | -
| {{:value.name}}: | -{{:value.amount}} | -
| {{:value.name}}: | -{{:value.amount}} | -