TGUI Medical: Cloning Console

This commit is contained in:
mochi
2020-07-11 16:50:32 +02:00
parent 27d021e832
commit 3f7d088c99
11 changed files with 734 additions and 354 deletions
+245 -199
View File
@@ -1,3 +1,6 @@
#define MENU_MAIN 1
#define MENU_RECORDS 2
/obj/machinery/computer/cloning
name = "cloning console"
icon = 'icons/obj/computer.dmi'
@@ -6,11 +9,11 @@
circuit = /obj/item/circuitboard/cloning
req_access = list(ACCESS_HEADS) //Only used for record deletion right now.
var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
var/list/pods = list() //Linked cloning pods.
var/temp = ""
var/scantemp = "Scanner ready."
var/menu = 1 //Which menu screen to display
var/list/records = list()
var/list/pods = null //Linked cloning pods.
var/list/temp = null
var/list/scantemp = null
var/menu = MENU_MAIN //Which menu screen to display
var/list/records = null
var/datum/dna2/record/active_record = null
var/obj/item/disk/data/diskette = null //Mostly so the geneticist can steal everything.
var/loading = 0 // Nice loading text
@@ -24,6 +27,9 @@
/obj/machinery/computer/cloning/Initialize()
..()
pods = list()
records = list()
set_scan_temp("Scanner ready.", "good")
updatemodules()
/obj/machinery/computer/cloning/Destroy()
@@ -91,7 +97,7 @@
W.loc = src
src.diskette = W
to_chat(user, "You insert [W].")
SSnanoui.update_uis(src)
SStgui.update_uis(src)
return
else if(istype(W, /obj/item/multitool))
var/obj/item/multitool/M = W
@@ -117,19 +123,21 @@
return
updatemodules()
ui_interact(user)
tgui_interact(user)
/obj/machinery/computer/cloning/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/machinery/computer/cloning/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
if(stat & (NOPOWER|BROKEN))
return
// Set up the Nano UI
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
var/datum/asset/cloning/assets = get_asset_datum(/datum/asset/cloning)
assets.send(user)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "cloning_console.tmpl", "Cloning Console UI", 640, 520)
ui = new(user, src, ui_key, "CloningConsole", "Cloning Console", 640, 520)
ui.open()
/obj/machinery/computer/cloning/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
/obj/machinery/computer/cloning/tgui_data(mob/user)
var/data[0]
data["menu"] = src.menu
data["scanner"] = sanitize("[src.scanner]")
@@ -143,7 +151,18 @@
if(pod.efficiency > 5)
canpodautoprocess = 1
tempods.Add(list(list("pod" = "\ref[pod]", "name" = sanitize(capitalize(pod.name)), "biomass" = pod.biomass)))
var/status = "idle"
if(pod.mess)
status = "mess"
else if(pod.occupant && !(pod.stat & NOPOWER))
status = "cloning"
tempods.Add(list(list(
"pod" = "\ref[pod]",
"name" = sanitize(capitalize(pod.name)),
"biomass" = pod.biomass,
"status" = status,
"progress" = (pod.occupant && pod.occupant.stat != DEAD) ? pod.get_completion() : 0
)))
data["pods"] = tempods
data["loading"] = loading
@@ -168,188 +187,188 @@
temprecords.Add(list(list("record" = "\ref[R]", "realname" = sanitize(tempRealName))))
data["records"] = temprecords
if(src.menu == 3)
if(src.active_record)
data["activerecord"] = "\ref[src.active_record]"
var/obj/item/implant/health/H = null
if(src.active_record.implant)
H = locate(src.active_record.implant)
if(selected_pod && (selected_pod in pods) && selected_pod.biomass >= CLONE_BIOMASS)
data["podready"] = 1
else
data["podready"] = 0
if((H) && (istype(H)))
data["health"] = H.sensehealth()
data["realname"] = sanitize(src.active_record.dna.real_name)
data["unidentity"] = src.active_record.dna.uni_identity
data["strucenzymes"] = src.active_record.dna.struc_enzymes
if(selected_pod && (selected_pod in pods) && selected_pod.biomass >= CLONE_BIOMASS)
data["podready"] = 1
else
data["podready"] = 0
data["modal"] = tgui_modal_data(src)
return data
/obj/machinery/computer/cloning/Topic(href, href_list)
/obj/machinery/computer/cloning/tgui_act(action, params)
if(..())
return 1
if(loading)
return
if(href_list["scan"] && scanner && scanner.occupant)
scantemp = "Scanner ready."
loading = 1
spawn(20)
if(can_brainscan() && scan_mode)
scan_mob(scanner.occupant, scan_brain = 1)
else
scan_mob(scanner.occupant)
loading = 0
SSnanoui.update_uis(src)
if(href_list["task"])
switch(href_list["task"])
if("autoprocess")
autoprocess = 1
SSnanoui.update_uis(src)
if("stopautoprocess")
autoprocess = 0
SSnanoui.update_uis(src)
//No locking an open scanner.
else if((href_list["lock"]) && (!isnull(src.scanner)))
if((!src.scanner.locked) && (src.scanner.occupant))
src.scanner.locked = 1
else
src.scanner.locked = 0
else if(href_list["view_rec"])
src.active_record = locate(href_list["view_rec"])
if(istype(src.active_record,/datum/dna2/record))
if((isnull(src.active_record.ckey)))
qdel(src.active_record)
src.temp = "<span class=\"bad\">Error: Record corrupt.</span>"
else
src.menu = 3
else
src.active_record = null
src.temp = "<span class=\"bad\">Error: Record missing.</span>"
else if(href_list["del_rec"])
if((!src.active_record) || (src.menu < 3))
return
if(src.menu == 3) //If we are viewing a record, confirm deletion
src.temp = "Please confirm that you want to delete the record?"
src.menu = 4
else if(src.menu == 4)
var/obj/item/card/id/C = usr.get_active_hand()
if(istype(C)||istype(C, /obj/item/pda))
if(src.check_access(C))
src.records.Remove(src.active_record)
qdel(src.active_record)
src.temp = "Record deleted."
src.menu = 2
. = TRUE
switch(tgui_modal_act(src, action, params))
if(TGUI_MODAL_ANSWER)
if(params["id"] == "del_rec" && active_record)
var/obj/item/card/id/C = usr.get_active_hand()
if(!istype(C) && !istype(C, /obj/item/pda))
set_temp("ID not in hand.", "danger")
return
if(check_access(C))
records.Remove(active_record)
qdel(active_record)
set_temp("Record deleted.", "success")
menu = MENU_RECORDS
else
src.temp = "<span class=\"bad\">Error: Access denied.</span>"
else if(href_list["disk"]) //Load or eject.
switch(href_list["disk"])
if("load")
if((isnull(src.diskette)) || isnull(src.diskette.buf))
src.temp = "<span class=\"bad\">Error: The disk's data could not be read.</span>"
SSnanoui.update_uis(src)
return
if(isnull(src.active_record))
src.temp = "<span class=\"bad\">Error: No active record was found.</span>"
src.menu = 1
SSnanoui.update_uis(src)
return
src.active_record = src.diskette.buf.copy()
src.temp = "Load successful."
if("eject")
if(!isnull(src.diskette))
src.diskette.loc = src.loc
src.diskette = null
else if(href_list["save_disk"]) //Save to disk!
if((isnull(src.diskette)) || (src.diskette.read_only) || (isnull(src.active_record)))
src.temp = "<span class=\"bad\">Error: The data could not be saved.</span>"
SSnanoui.update_uis(src)
set_temp("Access denied.", "danger")
return
// DNA2 makes things a little simpler.
src.diskette.buf=src.active_record.copy()
src.diskette.buf.types=0
switch(href_list["save_disk"]) //Save as Ui/Ui+Ue/Se
if("ui")
src.diskette.buf.types=DNA2_BUF_UI
if("ue")
src.diskette.buf.types=DNA2_BUF_UI|DNA2_BUF_UE
if("se")
src.diskette.buf.types=DNA2_BUF_SE
src.diskette.name = "data disk - '[src.active_record.dna.real_name]'"
src.temp = "Save \[[href_list["save_disk"]]\] successful."
switch(action)
if("scan")
if(!scanner || !scanner.occupant || loading)
return
set_scan_temp("Scanner ready.", "good")
loading = TRUE
else if(href_list["refresh"])
SSnanoui.update_uis(src)
else if(href_list["selectpod"])
var/obj/machinery/clonepod/selected = locate(href_list["selectpod"])
if(istype(selected) && (selected in pods))
selected_pod = selected
else if(href_list["clone"])
var/datum/dna2/record/C = locate(href_list["clone"])
//Look for that player! They better be dead!
if(istype(C))
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
if(!pods.len)
temp = "<span class=\"bad\">Error: No cloning pod detected.</span>"
else
var/obj/machinery/clonepod/pod = selected_pod
var/cloneresult
if(!selected_pod)
temp = "<span class=\"bad\">Error: No cloning pod selected.</span>"
else if(pod.occupant)
temp = "<span class=\"bad\">Error: The cloning pod is currently occupied.</span>"
else if(pod.biomass < CLONE_BIOMASS)
temp = "<span class=\"bad\">Error: Not enough biomass.</span>"
else if(pod.mess)
temp = "<span class=\"bad\">Error: The cloning pod is malfunctioning.</span>"
else if(!config.revival_cloning)
temp = "<span class=\"bad\">Error: Unable to initiate cloning cycle.</span>"
spawn(20)
if(can_brainscan() && scan_mode)
scan_mob(scanner.occupant, scan_brain = TRUE)
else
cloneresult = pod.growclone(C)
if(cloneresult)
if(cloneresult > 0)
temp = "Initiating cloning cycle..."
records.Remove(C)
qdel(C)
menu = 1
scan_mob(scanner.occupant)
loading = FALSE
SStgui.update_uis(src)
if("autoprocess")
autoprocess = text2num(params["on"]) > 0
if("lock")
if(isnull(scanner) || !scanner.occupant) //No locking an open scanner.
return
scanner.locked = !scanner.locked
if("view_rec")
var/ref = params["ref"]
if(!length(ref))
return
active_record = locate(ref)
if(istype(active_record))
if(isnull(active_record.ckey))
qdel(active_record)
set_temp("Error: Record corrupt.", "danger")
else
var/obj/item/implant/health/H = null
if(active_record.implant)
H = locate(active_record.implant)
var/list/payload = list(
activerecord = "\ref[active_record]",
health = (H && istype(H)) ? H.sensehealth() : "",
realname = sanitize(active_record.dna.real_name),
unidentity = active_record.dna.uni_identity,
strucenzymes = active_record.dna.struc_enzymes,
);
tgui_modal_message(src, action, "", null, payload)
else
active_record = null
set_temp("Error: Record missing.", "danger")
if("del_rec")
if(!active_record)
return
tgui_modal_boolean(src, action, "Please confirm that you want to delete the record by holding your ID and pressing Delete:", yes_text = "Delete", no_text = "Cancel")
if("disk") // Disk management.
if(!length(params["option"]))
return
switch(params["option"])
if("load")
if(isnull(diskette) || isnull(diskette.buf))
set_temp("Error: The disk's data could not be read.", "danger")
return
else if(isnull(active_record))
set_temp("Error: No active record was found.", "danger")
menu = MENU_MAIN
return
active_record = diskette.buf.copy()
set_temp("Successfully loaded from disk.", "success")
if("save")
if(isnull(diskette) || diskette.read_only || isnull(active_record))
set_temp("Error: The data could not be saved.", "danger")
return
// DNA2 makes things a little simpler.
var/types
switch(params["savetype"]) // Save as Ui/Ui+Ue/Se
if("ui")
types = DNA2_BUF_UI
if("ue")
types = DNA2_BUF_UI|DNA2_BUF_UE
if("se")
types = DNA2_BUF_SE
else
set_temp("Error: Invalid save format.", "danger")
return
diskette.buf = active_record.copy()
diskette.buf.types = types
diskette.name = "data disk - '[active_record.dna.real_name]'"
set_temp("Successfully saved to disk.", "success")
if("eject")
if(!isnull(diskette))
diskette.loc = loc
diskette = null
if("refresh")
SStgui.update_uis(src)
if("selectpod")
var/ref = params["ref"]
if(!length(ref))
return
var/obj/machinery/clonepod/selected = locate(ref)
if(istype(selected) && (selected in pods))
selected_pod = selected
if("clone")
var/ref = params["ref"]
if(!length(ref))
return
var/datum/dna2/record/C = locate(ref)
//Look for that player! They better be dead!
if(istype(C))
tgui_modal_clear(src)
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
if(!length(pods))
set_temp("Error: No cloning pod detected.", "danger")
else
var/obj/machinery/clonepod/pod = selected_pod
var/cloneresult
if(!selected_pod)
set_temp("Error: No cloning pod selected.", "danger")
else if(pod.occupant)
set_temp("Error: The cloning pod is currently occupied.", "danger")
else if(pod.biomass < CLONE_BIOMASS)
set_temp("Error: Not enough biomass.", "danger")
else if(pod.mess)
set_temp("Error: The cloning pod is malfunctioning.", "danger")
else if(!config.revival_cloning)
set_temp("Error: Unable to initiate cloning cycle.", "danger")
else
temp = "[C.name] => <font class='bad'>Initialisation failure.</font>"
cloneresult = pod.growclone(C)
if(cloneresult)
set_temp("Initiating cloning cycle...", "success")
records.Remove(C)
qdel(C)
menu = MENU_MAIN
else
set_temp("Error: Initialisation failure.", "danger")
else
set_temp("Error: Data corruption.", "danger")
if("menu")
menu = clamp(text2num(params["num"]), MENU_MAIN, MENU_RECORDS)
if("toggle_mode")
if(loading)
return
if(can_brainscan())
scan_mode = !scan_mode
else
scan_mode = FALSE
if("eject")
if(usr.incapacitated() || !scanner || loading)
return
scanner.eject_occupant(usr)
scanner.add_fingerprint(usr)
if("cleartemp")
temp = null
else
temp = "<span class=\"bad\">Error: Data corruption.</span>"
else if(href_list["menu"])
src.menu = text2num(href_list["menu"])
temp = ""
scantemp = "Scanner ready."
else if(href_list["toggle_mode"])
if(can_brainscan())
scan_mode = !scan_mode
else
scan_mode = 0
return FALSE
src.add_fingerprint(usr)
SSnanoui.update_uis(src)
return
/obj/machinery/computer/cloning/proc/scan_mob(mob/living/carbon/human/subject as mob, var/scan_brain = 0)
if(stat & NOPOWER)
@@ -360,46 +379,46 @@
return
if(isnull(subject) || (!(ishuman(subject))) || (!subject.dna))
if(isalien(subject))
scantemp = "<span class=\"bad\">Error: Xenomorphs are not scannable.</span>"
SSnanoui.update_uis(src)
set_scan_temp("Xenomorphs are not scannable.", "bad")
SStgui.update_uis(src)
return
// can add more conditions for specific non-human messages here
else
scantemp = "<span class=\"bad\">Error: Subject species is not scannable.</span>"
SSnanoui.update_uis(src)
set_scan_temp("Subject species is not scannable.", "bad")
SStgui.update_uis(src)
return
if(subject.get_int_organ(/obj/item/organ/internal/brain))
var/obj/item/organ/internal/brain/Brn = subject.get_int_organ(/obj/item/organ/internal/brain)
if(istype(Brn))
if(NO_SCAN in Brn.dna.species.species_traits)
scantemp = "<span class=\"bad\">Error: [Brn.dna.species.name_plural] are not scannable.</span>"
SSnanoui.update_uis(src)
set_scan_temp("[Brn.dna.species.name_plural] are not scannable.", "bad")
SStgui.update_uis(src)
return
if(!subject.get_int_organ(/obj/item/organ/internal/brain))
scantemp = "<span class=\"bad\">Error: No brain detected in subject.</span>"
SSnanoui.update_uis(src)
set_scan_temp("No brain detected in subject.", "bad")
SStgui.update_uis(src)
return
if(subject.suiciding)
scantemp = "<span class=\"bad\">Error: Subject has committed suicide and is not scannable.</span>"
SSnanoui.update_uis(src)
set_scan_temp("Subject has committed suicide and is not scannable.", "bad")
SStgui.update_uis(src)
return
if((!subject.ckey) || (!subject.client))
scantemp = "<span class=\"bad\">Error: Subject's brain is not responding. Further attempts after a short delay may succeed.</span>"
SSnanoui.update_uis(src)
set_scan_temp("Subject's brain is not responding. Further attempts after a short delay may succeed.", "bad")
SStgui.update_uis(src)
return
if((NOCLONE in subject.mutations) && src.scanner.scan_level < 2)
scantemp = "<span class=\"bad\">Error: Subject has incompatible genetic mutations.</span>"
SSnanoui.update_uis(src)
set_scan_temp("Subject has incompatible genetic mutations.", "bad")
SStgui.update_uis(src)
return
if(!isnull(find_record(subject.ckey)))
scantemp = "Subject already in database."
SSnanoui.update_uis(src)
set_scan_temp("Subject already in database.")
SStgui.update_uis(src)
return
for(var/obj/machinery/clonepod/pod in pods)
if(pod.occupant && pod.clonemind == subject.mind)
scantemp = "Subject already getting cloned."
SSnanoui.update_uis(src)
set_scan_temp("Subject already getting cloned.")
SStgui.update_uis(src)
return
subject.dna.check_integrity()
@@ -434,8 +453,8 @@
R.mind = "\ref[subject.mind]"
src.records += R
scantemp = "Subject successfully scanned. " + extra_info
SSnanoui.update_uis(src)
set_scan_temp("Subject successfully scanned. [extra_info]", "good")
SStgui.update_uis(src)
//Find a specific record by key.
/obj/machinery/computer/cloning/proc/find_record(var/find_key)
@@ -451,3 +470,30 @@
/obj/machinery/computer/cloning/proc/can_brainscan()
return (scanner && scanner.scan_level > 3)
/**
* Sets a temporary message to display to the user
*
* Arguments:
* * text - Text to display, null/empty to clear the message from the UI
* * style - The style of the message: (color name), info, success, warning, danger
*/
/obj/machinery/computer/cloning/proc/set_temp(text = "", style = "info", update_now = FALSE)
temp = list(text = text, style = style)
if(update_now)
SStgui.update_uis(src)
/**
* Sets a temporary scan message to display to the user
*
* Arguments:
* * text - Text to display, null/empty to clear the message from the UI
* * color - The color of the message: (color name)
*/
/obj/machinery/computer/cloning/proc/set_scan_temp(text = "", color = "", update_now = FALSE)
scantemp = list(text = text, color = color)
if(update_now)
SStgui.update_uis(src)
#undef MENU_MAIN
#undef MENU_RECORDS
+14
View File
@@ -309,6 +309,20 @@ GLOBAL_LIST_EMPTY(asset_datums)
/datum/asset/chem_master/send(client)
send_asset_list(client, assets, verify)
//Cloning pod sprites for UIs
/datum/asset/cloning
var/assets = list()
var/verify = FALSE
/datum/asset/cloning/register()
assets["pod_idle.gif"] = icon('icons/obj/cloning.dmi', "pod_idle")
assets["pod_cloning.gif"] = icon('icons/obj/cloning.dmi', "pod_cloning")
assets["pod_mess.gif"] = icon('icons/obj/cloning.dmi', "pod_mess")
for(var/asset_name in assets)
register_asset(asset_name, assets[asset_name])
/datum/asset/cloning/send(client)
send_asset_list(client, assets, verify)
//Pipe sprites for UIs
/datum/asset/rpd
-148
View File
@@ -1,148 +0,0 @@
<!--
Title: Cloning Console UI
Used In File(s): \code\game\machinery\computer\cloning.dm
-->
<div class="block">
<div class="item">
<div class="itemLabelNarrow">Menu</div>
<div class="itemContentWide">
{{:helper.link('Main', 'home', {'menu' : 1}, data.menu == 1 ? 'selected' : '')}}{{:helper.link('Records', 'folder-open', {'menu' : 2}, data.menu == 2 ? 'selected' : '')}}
</div>
</div>
<div class="item">
<div class="itemLabelNarrow">Refresh</div>
<div class="itemContentWide">
{{:helper.link('Refresh', 'refresh', {'refresh' : 1})}}
</div>
</div>
<div class="item">
<div class="itemLabelNarrow">Autoprocessing</div>
<div class="itemContentWide">
{{if data.autoallowed}}
{{:helper.link('Enabled', 'check', {'task' : 'autoprocess'}, data.autoprocess ? 'selected' : '')}}{{:helper.link('Disabled', 'close', {'task' : 'stopautoprocess'}, !data.autoprocess ? 'selected' : '')}}
{{else}}
{{:helper.link('Enabled', 'check', null, 'disabled')}}{{:helper.link('Disabled', 'close', null, 'selected')}}
{{/if}}
</div>
</div>
{{if data.disk}}
<div class="item">
<div class="itemLabelNarrow">Disk</div>
<div class="itemContentWide">{{:helper.link('Eject', 'eject', {'disk' : 'eject'})}}</div>
</div>
{{/if}}
</div>
{{if data.menu == 1}}
<h2>Modules</h2>
<div class="item">
<div class="itemLabelNarrow">Scanner</div>
<div class="itemContentWide{{if data.scanner}} good{{else}} bad{{/if}}">
{{if data.scanner}} Found!{{else}} Error: Not detected!{{/if}}
</div>
</div>
<div class="item">
<div class="itemLabelNarrow">Pods</div>
<div class="itemContentWide{{if data.numberofpods}} good{{else}} bad{{/if}}">
{{if data.numberofpods}} Found {{:data.numberofpods}}!{{else}} Error: None detected!{{/if}}
</div>
</div>
{{if data.scanner}}
<h2>Scanner Functions</h2>
{{if data.loading}}
<b>Scanning...</b>
{{else}}
<b>{{:data.scantemp}}</b>
{{/if}}
<div class="item">
<div class="itemLabelNarrow">Scan Occupant</div>
<div class="itemContentWide">{{:helper.link('Scan', 'search', {'scan' : 1}, !data.occupant ? 'disabled' : '')}}</div>
</div>
<div class="item">
<div class="itemLabelNarrow">Scanner Lock</div>
<div class="itemContentWide">{{if data.occupant}}{{:helper.link('Engaged', 'lock', {'lock' : 1}, data.locked ? 'selected' : '')}}{{else}} {{:helper.link('Engaged', 'lock', null, 'disabled')}}{{/if}}{{:helper.link('Disengaged', 'unlock', {'lock' : 1}, !data.locked ? 'selected' : '')}}</div>
</div>
{{if data.can_brainscan}}
<div class="item">
<div class="itemLabelNarrow">Scan Mode</div>
<div class="itemContentWide">
{{:helper.link('Brain', null, {'toggle_mode' : 1}, !data.scan_mode ? '' : 'selected')}}{{:helper.link('Body', null, {'toggle_mode' : 1}, data.scan_mode ? '' : 'selected')}}
</div>
</div>
{{/if}}
{{/if}}
{{if data.numberofpods}}
<h2>Pods</h2>
{{for data.pods}}
<b>{{:value.name}}</b></br>
<div class="item">
<div class="itemLabelNarrow">Biomass</div>
<div class="itemContentWide{{if value.biomass > 0}} good{{else}} bad{{/if}}">
{{:value.biomass}}
</div>
</div>
<div class="item">
<div class="itemLabelNarrow">Select</div>
<div class="itemContentWide">
{{:helper.link('Select', 'check', {'selectpod' : value.pod}, value.pod == data.selected_pod ? 'selected' : '')}}
</div>
</div>
{{/for}}
{{/if}}
{{/if}}
{{if data.menu == 2}}
<h2>Current Records</h2>
{{if data.temp}}
<div class="item">
{{:data.temp}}
</div>
{{/if}}
{{for data.records}}
<div>{{:helper.link(value.realname, 'arrow-circle-down', {'view_rec' : value.record})}}</div>
{{empty}}
No records found!
{{/for}}
{{/if}}
{{if data.menu == 3}}
<h2>Selected Record</h2>
{{if data.temp}}
<div class="item">
{{:data.temp}}
</div>
{{/if}}
{{if !data.activerecord}}
<div class="bad">Error: Record not found!</div>
{{else}}
<div class="item">
<b>Real Name:</b> {{:data.realname}}<br />
<b>Health:</b> {{:data.health}} (<span class="oxyloss_light">OXY</span> - <span class="burn">BURN</span> - <span class="toxin_light">TOX</span> - <span class="brute">BRUTE</span>)
</div>
<div class="item">
<b>UI:</b> {{:data.unidentity}}<br />
<b>SE:</b> <div style="word-wrap: break-word;">{{:data.strucenzymes}}</div>
</div>
{{if data.disk}}
<div class="item">
<div class="itemLabelNarrow">Disk</div>
<div class="itemContentWide">{{:helper.link('Load from Disk', 'floppy-o', {'disk' : 'load'})}}{{:helper.link('Save UI + UE', 'arrow-circle-up', {'save_disk' : 'ue'})}}{{:helper.link('Save UI', 'arrow-circle-up', {'save_disk' : 'ui'})}}{{:helper.link('Save SE', 'arrow-circle-up', {'save_disk' : 'se'})}}</div>
</div>
{{/if}}
<div class="item">
<div class="itemLabelNarrow">Actions</div>
<div class="itemContentWide">{{:helper.link('Clone', 'arrow-right', {'clone' : data.activerecord}, !data.podready ? 'disabled' : '')}}{{:helper.link('Delete', 'trash', {'del_rec' : 1})}}</div>
</div>
{{/if}}
{{/if}}
{{if data.menu == 4}}
<h2>Confirm Record Deletion</h2>
{{if data.temp}}
<div class="item">
{{:data.temp}}
</div>
{{/if}}
<div class="item">
{{:helper.link('Scan Card and Confirm', 'trash', {'del_rec' : 1})}}{{:helper.link('Cancel', 'close', {'menu' : 3})}}
</div>
{{/if}}
+1
View File
@@ -92,6 +92,7 @@ const styleMapperByPropName = {
textAlign: mapRawPropTo('text-align'),
verticalAlign: mapRawPropTo('vertical-align'),
textTransform: mapRawPropTo('text-transform'),
wordWrap: mapRawPropTo('word-wrap'),
// Boolean props
inline: mapBooleanPropTo('display', 'inline-block'),
bold: mapBooleanPropTo('font-weight', 'bold'),
+2
View File
@@ -9,6 +9,7 @@ export const Section = props => {
buttons,
content,
stretchContents,
noTopPadding,
children,
scrollable,
...rest
@@ -38,6 +39,7 @@ export const Section = props => {
<Box className={classes([
"Section__content",
!!stretchContents && "Section__content--stretchContents",
!!noTopPadding && "Section__content--noTopPadding",
])}>
{content}
{children}
@@ -0,0 +1,461 @@
import { Fragment } from 'inferno';
import { useBackend } from "../backend";
import { Window } from "../layouts";
import { Box, Button, Flex, Icon, LabeledList, NoticeBox, Section, Tabs, ProgressBar } from "../components";
import { ComplexModal, modalRegisterBodyOverride } from '../interfaces/common/ComplexModal';
import { COLORS } from '../constants';
import { round } from 'common/math';
const viewRecordModalBodyOverride = (modal, context) => {
const { act, data } = useBackend(context);
const {
activerecord,
realname,
health,
unidentity,
strucenzymes,
} = modal.args;
const damages = health.split(' - ');
return (
<Section
level={2}
m="-1rem"
pb="1rem"
title={"Records of " + realname}>
<LabeledList>
<LabeledList.Item label="Name">
{realname}
</LabeledList.Item>
<LabeledList.Item label="Damage">
{damages.length > 1 ? (
<Fragment>
<Box color={COLORS.damageType.oxy} display="inline">
{damages[0]}
</Box>
&nbsp;|&nbsp;
<Box color={COLORS.damageType.toxin} display="inline">
{damages[2]}
</Box>
&nbsp;|&nbsp;
<Box color={COLORS.damageType.brute} display="inline">
{damages[3]}
</Box>
&nbsp;|&nbsp;
<Box color={COLORS.damageType.burn} display="inline">
{damages[1]}
</Box>
</Fragment>
) : (
<Box color="bad">
Unknown
</Box>
)}
</LabeledList.Item>
<LabeledList.Item label="UI" className="LabeledList__breakContents">
{unidentity}
</LabeledList.Item>
<LabeledList.Item label="SE" className="LabeledList__breakContents">
{strucenzymes}
</LabeledList.Item>
<LabeledList.Item label="Disk">
<Button.Confirm
disabled={!data.disk}
icon="arrow-circle-down"
content="Import"
onClick={() => act('disk', {
option: 'load',
})}
/>
<Button
disabled={!data.disk}
icon="arrow-circle-up"
content="Export UI"
onClick={() => act('disk', {
option: 'save',
savetype: 'ui',
})}
/>
<Button
disabled={!data.disk}
icon="arrow-circle-up"
content="Export UI and UE"
onClick={() => act('disk', {
option: 'save',
savetype: 'ue',
})}
/>
<Button
disabled={!data.disk}
icon="arrow-circle-up"
content="Export SE"
onClick={() => act('disk', {
option: 'save',
savetype: 'se',
})}
/>
</LabeledList.Item>
<LabeledList.Item label="Actions">
<Button
disabled={!data.podready}
icon="user-plus"
content="Clone"
onClick={() => act('clone', {
ref: activerecord,
})}
/>
<Button
icon="trash"
content="Delete"
onClick={() => act('del_rec')}
/>
</LabeledList.Item>
</LabeledList>
</Section>
);
};
export const CloningConsole = (props, context) => {
const { act, data } = useBackend(context);
const {
menu,
} = data;
modalRegisterBodyOverride('view_rec', viewRecordModalBodyOverride);
return (
<Window resizable>
<ComplexModal maxWidth="75%" maxHeight="75%" />
<Window.Content className="Layout__content--flexColumn">
<CloningConsoleTemp />
<CloningConsoleStatus />
<CloningConsoleNavigation />
<Section noTopPadding flexGrow="1">
<CloningConsoleBody />
</Section>
</Window.Content>
</Window>
);
};
const CloningConsoleNavigation = (props, context) => {
const { act, data } = useBackend(context);
const {
menu,
} = data;
return (
<Tabs>
<Tabs.Tab
selected={menu === 1}
icon="home"
onClick={() => act('menu', {
num: 1,
})}>
Main
</Tabs.Tab>
<Tabs.Tab
selected={menu === 2}
icon="folder"
onClick={() => act('menu', {
num: 2,
})}>
Records
</Tabs.Tab>
</Tabs>
);
};
const CloningConsoleBody = (props, context) => {
const { data } = useBackend(context);
const {
menu,
} = data;
let body;
if (menu === 1) {
body = <CloningConsoleMain />;
} else if (menu === 2) {
body = <CloningConsoleRecords />;
}
return body;
};
const CloningConsoleMain = (props, context) => {
const { act, data } = useBackend(context);
const {
loading,
scantemp,
occupant,
locked,
can_brainscan,
scan_mode,
numberofpods,
pods,
selected_pod,
} = data;
const isLocked = locked && !!occupant;
return (
<Fragment>
<Section
title="Scanner"
level="2"
buttons={
<Fragment>
<Box display="inline" color="label">
Scanner Lock:&nbsp;
</Box>
<Button
disabled={!occupant}
selected={isLocked}
icon={isLocked ? "toggle-on" : "toggle-off"}
content={isLocked ? "Engaged" : "Disengaged"}
onClick={() => act('lock')}
/>
<Button
disabled={isLocked || !occupant}
icon="user-slash"
content="Eject Occupant"
onClick={() => act('eject')}
/>
</Fragment>
}>
<LabeledList>
<LabeledList.Item label="Status">
{loading ? (
<Box color="average">
<Icon name="spinner" spin />&nbsp;
Scanning...
</Box>
) : (
<Box color={scantemp.color}>
{scantemp.text}
</Box>
)}
</LabeledList.Item>
{!!can_brainscan && (
<LabeledList.Item label="Scan Mode">
<Button
icon={scan_mode ? "brain" : "male"}
content={scan_mode ? "Brain" : "Body"}
onClick={() => act('toggle_mode')}
/>
</LabeledList.Item>
)}
</LabeledList>
<Button
disabled={!occupant || loading}
icon="user"
content="Scan Occupant"
mt="0.5rem"
mb="0"
onClick={() => act('scan')}
/>
</Section>
<Section title="Pods" level="2">
{numberofpods
? pods.map((pod, i) => {
let podAction;
if (pod.status === "cloning") {
podAction = (
<ProgressBar
min="0"
max="100"
value={pod.progress / 100}
ranges={{
good: [0.75, Infinity],
average: [0.25, 0.75],
bad: [-Infinity, 0.25],
}}
mt="0.5rem">
<Box textAlign="center">
{round(pod.progress) + "%"}
</Box>
</ProgressBar>
);
} else if (pod.status === "mess") {
podAction = (
<Box bold color="bad" mt="0.5rem">
ERROR
</Box>
);
} else {
podAction = (
<Button
selected={selected_pod === pod.pod}
icon={selected_pod === pod.pod && "check"}
content="Select"
mt="0.5rem"
onClick={() => act('selectpod', {
ref: pod.pod,
})}
/>
);
}
return (
<Box
key={i}
width="64px"
textAlign="center"
display="inline-block"
mr="0.5rem">
<img
src={"pod_" + pod.status + ".gif"}
style={{
width: "100%",
"-ms-interpolation-mode": "nearest-neighbor",
}}
/>
<Box color="label">
Pod #{i + 1}
</Box>
<Box
bold
color={pod.biomass >= 150 ? "good" : "bad"}
display="inline">
<Icon
name={pod.biomass >= 150 ? "circle" : "circle-o"}
/>&nbsp;
{pod.biomass}
</Box>
{podAction}
</Box>
);
})
: (
<Box color="bad">
No pods detected. Unable to clone.
</Box>
)}
</Section>
</Fragment>
);
};
const CloningConsoleRecords = (props, context) => {
const { act, data } = useBackend(context);
const {
records,
} = data;
if (!records.length) {
return (
<Flex height="100%">
<Flex.Item
grow="1"
align="center"
textAlign="center"
color="label">
<Icon
name="user-slash"
mb="0.5rem"
size="5"
/><br />
No records found.
</Flex.Item>
</Flex>
);
}
return (
<Box mt="0.5rem">
{records.map((record, i) => (
<Button
key={i}
icon="user"
mb="0.5rem"
content={record.realname}
onClick={() => act('view_rec', {
ref: record.record,
})}
/>
))}
</Box>
);
};
const CloningConsoleTemp = (props, context) => {
const { act, data } = useBackend(context);
const {
temp,
} = data;
if (!temp || !temp.text || temp.text.length <= 0) {
return;
}
const tempProp = { [temp.style]: true };
return (
<NoticeBox {...tempProp}>
<Box display="inline-block" verticalAlign="middle">
{temp.text}
</Box>
<Button
icon="times-circle"
float="right"
onClick={() => act('cleartemp')}
/>
<Box clear="both" />
</NoticeBox>
);
};
const CloningConsoleStatus = (props, context) => {
const { act, data } = useBackend(context);
const {
scanner,
numberofpods,
autoallowed,
autoprocess,
disk,
} = data;
return (
<Section
title="Status"
buttons={
<Fragment>
{!!autoallowed && (
<Fragment>
<Box display="inline" color="label">
Auto-processing:&nbsp;
</Box>
<Button
selected={autoprocess}
icon={autoprocess ? "toggle-on" : "toggle-off"}
content={autoprocess ? "Enabled" : "Disabled"}
onClick={() => act('autoprocess', {
on: autoprocess ? 0 : 1,
})}
/>
</Fragment>
)}
<Button
disabled={!disk}
icon="eject"
content="Eject Disk"
onClick={() => act('disk', {
option: 'eject',
})}
/>
</Fragment>
}>
<LabeledList>
<LabeledList.Item label="Scanner">
{scanner ? (
<Box color="good">
Connected
</Box>
) : (
<Box color="bad">
Not connected!
</Box>
)}
</LabeledList.Item>
<LabeledList.Item label="Pods">
{numberofpods ? (
<Box color="good">
{numberofpods} connected
</Box>
) : (
<Box color="bad">
None connected!
</Box>
)}
</LabeledList.Item>
</LabeledList>
</Section>
);
};
+1 -1
View File
@@ -160,7 +160,7 @@ const DNAModifierMain = (props, context) => {
mb="0.5rem"
size="5"
/><br />
No occupant in cell.
No occupant in DNA modifier.
</Flex.Item>
</Flex>
</Section>
@@ -132,8 +132,8 @@ export const ComplexModal = (props, context) => {
return (
<Modal
maxWidth={window.innerWidth / 2 + "px"}
maxHeight={window.innerHeight / 2 + "px"}
maxWidth={props.maxWidth || (window.innerWidth / 2 + "px")}
maxHeight={props.maxHeight || (window.innerHeight / 2 + "px")}
mx="auto">
<Box display="inline">
{text}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -54,6 +54,10 @@ $color-separator: colors.$primary !default;
padding: 8px 6px;
}
.Section__content--noTopPadding {
padding-top: 0;
}
.Section__content--stretchContents {
height: 100%;
}