mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-24 12:37:26 +01:00
TGUI Medical: DNA Modifier
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
// TGUI defines
|
||||
#define TGUI_MODAL_INPUT_MAX_LENGTH 1024
|
||||
#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
|
||||
|
||||
+327
-403
@@ -163,6 +163,7 @@
|
||||
occupant = usr
|
||||
icon_state = "scanner_occupied"
|
||||
add_fingerprint(usr)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/dna_scannernew/MouseDrop_T(atom/movable/O, mob/user)
|
||||
if(!istype(O))
|
||||
@@ -216,6 +217,7 @@
|
||||
return
|
||||
|
||||
beaker = I
|
||||
SStgui.update_uis(src)
|
||||
I.forceMove(src)
|
||||
user.visible_message("[user] adds \a [I] to \the [src]!", "You add \a [I] to \the [src]!")
|
||||
return
|
||||
@@ -262,6 +264,7 @@
|
||||
M.forceMove(src)
|
||||
occupant = M
|
||||
icon_state = "scanner_occupied"
|
||||
SStgui.update_uis(src)
|
||||
|
||||
// search for ghosts, if the corpse is empty and the scanner is connected to a cloner
|
||||
if(locate(/obj/machinery/computer/cloning, get_step(src, NORTH)) \
|
||||
@@ -283,6 +286,7 @@
|
||||
occupant.forceMove(loc)
|
||||
occupant = null
|
||||
icon_state = "scanner_open"
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/dna_scannernew/ex_act(severity)
|
||||
if(occupant)
|
||||
@@ -295,6 +299,7 @@
|
||||
occupant = null
|
||||
updateUsrDialog()
|
||||
update_icon()
|
||||
SStgui.update_uis(src)
|
||||
|
||||
// Checks if occupants can be irradiated/mutated - prevents exploits where wearing full rad protection would still let you gain mutations
|
||||
/obj/machinery/dna_scannernew/proc/radiation_check()
|
||||
@@ -332,12 +337,11 @@
|
||||
var/injector_ready = FALSE //Quick fix for issue 286 (screwdriver the screen twice to restore injector) -Pete
|
||||
var/obj/machinery/dna_scannernew/connected = null
|
||||
var/obj/item/disk/data/disk = null
|
||||
var/selected_menu_key = null
|
||||
var/selected_menu_key = "ui"
|
||||
anchored = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
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, mob/user, params)
|
||||
if(istype(I, /obj/item/disk/data)) //INSERT SOME diskS
|
||||
@@ -346,7 +350,7 @@
|
||||
I.forceMove(src)
|
||||
disk = I
|
||||
to_chat(user, "You insert [I].")
|
||||
SSnanoui.update_uis(src) // update all UIs attached to src()
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
@@ -398,35 +402,19 @@
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
tgui_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
|
||||
*
|
||||
* @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", datum/nanoui/ui = null, force_open = 1)
|
||||
/obj/machinery/computer/scan_consolenew/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(user == connected.occupant)
|
||||
return
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, 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)
|
||||
// open the new ui window
|
||||
ui = new(user, src, ui_key, "DNAModifier", name, 660, 700, master_ui, state)
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
ui.set_autoupdate(TRUE)
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/ui_data(mob/user, datum/topic_state/state)
|
||||
/obj/machinery/computer/scan_consolenew/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
data["selectedMenuKey"] = selected_menu_key
|
||||
data["locked"] = connected.locked
|
||||
@@ -500,9 +488,12 @@
|
||||
for(var/datum/reagent/R in connected.beaker.reagents.reagent_list)
|
||||
data["beakerVolume"] += R.volume
|
||||
|
||||
// Transfer modal information if there is one
|
||||
data["modal"] = tgui_modal_data(src)
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/Topic(href, href_list)
|
||||
/obj/machinery/computer/scan_consolenew/tgui_act(action, params)
|
||||
if(..())
|
||||
return FALSE // don't update uis
|
||||
if(!istype(usr.loc, /turf))
|
||||
@@ -514,402 +505,335 @@
|
||||
|
||||
add_fingerprint(usr)
|
||||
|
||||
if(href_list["selectMenuKey"])
|
||||
selected_menu_key = href_list["selectMenuKey"]
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["toggleLock"])
|
||||
if((connected && connected.occupant))
|
||||
connected.locked = !(connected.locked)
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["pulseRadiation"])
|
||||
irradiating = radiation_duration
|
||||
var/lock_state = connected.locked
|
||||
connected.locked = TRUE //lock it
|
||||
SSnanoui.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)
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
var/radiation = (((radiation_intensity * 3) + radiation_duration * 3) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
if(connected.radiation_check())
|
||||
return TRUE
|
||||
|
||||
if(prob(95))
|
||||
if(prob(75))
|
||||
randmutb(connected.occupant)
|
||||
else
|
||||
randmuti(connected.occupant)
|
||||
else
|
||||
if(prob(95))
|
||||
randmutg(connected.occupant)
|
||||
else
|
||||
randmuti(connected.occupant)
|
||||
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["radiationDuration"])
|
||||
if(text2num(href_list["radiationDuration"]) > 0)
|
||||
if(radiation_duration < 20)
|
||||
radiation_duration += 2
|
||||
else
|
||||
if(radiation_duration > 2)
|
||||
radiation_duration -= 2
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["radiationIntensity"])
|
||||
if(text2num(href_list["radiationIntensity"]) > 0)
|
||||
if(radiation_intensity < 10)
|
||||
radiation_intensity++
|
||||
else
|
||||
if(radiation_intensity > 1)
|
||||
radiation_intensity--
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
if(href_list["changeUITarget"] && text2num(href_list["changeUITarget"]) > 0)
|
||||
if(selected_ui_target < 15)
|
||||
selected_ui_target++
|
||||
selected_ui_target_hex = selected_ui_target
|
||||
switch(selected_ui_target)
|
||||
if(10)
|
||||
selected_ui_target_hex = "A"
|
||||
if(11)
|
||||
selected_ui_target_hex = "B"
|
||||
if(12)
|
||||
selected_ui_target_hex = "C"
|
||||
if(13)
|
||||
selected_ui_target_hex = "D"
|
||||
if(14)
|
||||
selected_ui_target_hex = "E"
|
||||
if(15)
|
||||
selected_ui_target_hex = "F"
|
||||
else
|
||||
selected_ui_target = 0
|
||||
selected_ui_target_hex = 0
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["changeUITarget"] && text2num(href_list["changeUITarget"]) < 1)
|
||||
if(selected_ui_target > 0)
|
||||
selected_ui_target--
|
||||
selected_ui_target_hex = selected_ui_target
|
||||
switch(selected_ui_target)
|
||||
if(10)
|
||||
selected_ui_target_hex = "A"
|
||||
if(11)
|
||||
selected_ui_target_hex = "B"
|
||||
if(12)
|
||||
selected_ui_target_hex = "C"
|
||||
if(13)
|
||||
selected_ui_target_hex = "D"
|
||||
if(14)
|
||||
selected_ui_target_hex = "E"
|
||||
else
|
||||
selected_ui_target = 15
|
||||
selected_ui_target_hex = "F"
|
||||
return TRUE // 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))
|
||||
selected_ui_block = select_block
|
||||
if((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1))
|
||||
selected_ui_subblock = select_subblock
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["pulseUIRadiation"])
|
||||
var/block = connected.occupant.dna.GetUISubBlock(selected_ui_block, selected_ui_subblock)
|
||||
|
||||
irradiating = radiation_duration
|
||||
var/lock_state = connected.locked
|
||||
connected.locked = TRUE //lock it
|
||||
SSnanoui.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)
|
||||
return TRUE
|
||||
|
||||
if(prob((80 + (radiation_duration / 2))))
|
||||
var/radiation = (radiation_intensity + radiation_duration)
|
||||
connected.occupant.apply_effect(radiation,IRRADIATE,0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return TRUE
|
||||
|
||||
block = miniscrambletarget(num2text(selected_ui_target), radiation_intensity, radiation_duration)
|
||||
connected.occupant.dna.SetUISubBlock(selected_ui_block, selected_ui_subblock, block)
|
||||
connected.occupant.UpdateAppearance()
|
||||
else
|
||||
var/radiation = ((radiation_intensity * 2) + radiation_duration)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
if(connected.radiation_check())
|
||||
return TRUE
|
||||
|
||||
if(prob(20 + radiation_intensity))
|
||||
randmutb(connected.occupant)
|
||||
domutcheck(connected.occupant, connected)
|
||||
else
|
||||
randmuti(connected.occupant)
|
||||
connected.occupant.UpdateAppearance()
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
if(href_list["injectRejuvenators"])
|
||||
if(!connected.occupant)
|
||||
return FALSE
|
||||
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(connected.occupant, inject_amount)
|
||||
connected.beaker.reagents.reaction(connected.occupant)
|
||||
return TRUE // 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))
|
||||
selected_se_block = select_block
|
||||
if((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1))
|
||||
selected_se_subblock = select_subblock
|
||||
//testing("User selected block [selected_se_block] (sent [select_block]), subblock [selected_se_subblock] (sent [select_block]).")
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["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
|
||||
SSnanoui.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) + (connected.precision_coeff ** 3)))))
|
||||
var/radiation = ((radiation_intensity + radiation_duration) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return 1
|
||||
|
||||
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)
|
||||
domutcheck(connected.occupant, connected)
|
||||
else
|
||||
var/radiation = (((radiation_intensity * 2) + radiation_duration) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return 1
|
||||
|
||||
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()
|
||||
return TRUE // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["ejectBeaker"])
|
||||
if(connected.beaker)
|
||||
var/obj/item/reagent_containers/glass/B = connected.beaker
|
||||
B.forceMove(connected.loc)
|
||||
connected.beaker = null
|
||||
if(tgui_act_modal(action, params))
|
||||
return TRUE
|
||||
|
||||
if(href_list["ejectOccupant"])
|
||||
connected.eject_occupant()
|
||||
return TRUE
|
||||
|
||||
// Transfer Buffer Management
|
||||
if(href_list["bufferOption"])
|
||||
var/bufferOption = href_list["bufferOption"]
|
||||
|
||||
// These bufferOptions do not require a bufferId
|
||||
if(bufferOption == "wipeDisk")
|
||||
if((isnull(disk)) || (disk.read_only))
|
||||
//temphtml = "Invalid disk. Please try again."
|
||||
return FALSE
|
||||
|
||||
disk.buf = null
|
||||
//temphtml = "Data saved."
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "ejectDisk")
|
||||
if(!disk)
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("selectMenuKey")
|
||||
var/key = params["key"]
|
||||
if(!(key in list("ui", "se", "buffer", "rejuvenators")))
|
||||
return
|
||||
disk.forceMove(get_turf(src))
|
||||
disk = null
|
||||
return TRUE
|
||||
|
||||
// All bufferOptions from here on require a bufferId
|
||||
if(!href_list["bufferId"])
|
||||
return FALSE
|
||||
|
||||
var/bufferId = text2num(href_list["bufferId"])
|
||||
|
||||
if(bufferId < 1 || bufferId > 3)
|
||||
return FALSE // Not a valid buffer id
|
||||
|
||||
if(bufferOption == "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))
|
||||
databuf.dna.real_name=connected.occupant.name
|
||||
databuf.name = "Unique Identifier"
|
||||
buffers[bufferId] = databuf
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "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))
|
||||
databuf.dna.real_name=connected.occupant.dna.real_name
|
||||
databuf.name = "Unique Identifier + Unique Enzymes"
|
||||
buffers[bufferId] = databuf
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "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))
|
||||
databuf.dna.real_name = connected.occupant.dna.real_name
|
||||
databuf.name = "Structural Enzymes"
|
||||
buffers[bufferId] = databuf
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "clear")
|
||||
buffers[bufferId] = new /datum/dna2/record()
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "changeLabel")
|
||||
var/datum/dna2/record/buf = buffers[bufferId]
|
||||
var/text = sanitize(input(usr, "New Label:", "Edit Label", buf.name) as text|null)
|
||||
buf.name = text
|
||||
buffers[bufferId] = buf
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "transfer")
|
||||
if(!connected.occupant || (NOCLONE in connected.occupant.mutations && connected.scan_level < 3) || !connected.occupant.dna)
|
||||
return TRUE
|
||||
|
||||
irradiating = 2
|
||||
selected_menu_key = key
|
||||
if("toggleLock")
|
||||
if(connected && connected.occupant)
|
||||
connected.locked = !(connected.locked)
|
||||
if("pulseRadiation")
|
||||
irradiating = radiation_duration
|
||||
var/lock_state = connected.locked
|
||||
connected.locked = TRUE //lock it
|
||||
SSnanoui.update_uis(src) // update all UIs attached to src
|
||||
|
||||
sleep(2 SECONDS)
|
||||
SStgui.update_uis(src)
|
||||
sleep(10 * radiation_duration) // sleep for radiation_duration seconds
|
||||
|
||||
irradiating = 0
|
||||
connected.locked = lock_state
|
||||
|
||||
var/radiation = (rand(20,50) / connected.damage_coeff)
|
||||
if(!connected.occupant)
|
||||
return
|
||||
|
||||
var/radiation = (((radiation_intensity * 3) + radiation_duration * 3) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return TRUE
|
||||
return
|
||||
|
||||
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
|
||||
connected.occupant.UpdateAppearance(buf.dna.UI.Copy())
|
||||
else if(buf.types & DNA2_BUF_SE)
|
||||
connected.occupant.dna.SE = buf.dna.SE.Copy()
|
||||
connected.occupant.dna.UpdateSE()
|
||||
domutcheck(connected.occupant, connected)
|
||||
return TRUE
|
||||
|
||||
if(bufferOption == "createInjector")
|
||||
if(injector_ready && !waiting_for_user_input)
|
||||
|
||||
var/success = 1
|
||||
var/obj/item/dnainjector/I = new /obj/item/dnainjector
|
||||
var/datum/dna2/record/buf = buffers[bufferId]
|
||||
buf = buf.copy()
|
||||
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") as null|anything 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.forceMove(loc)
|
||||
I.name += " ([buf.name])"
|
||||
if(connected)
|
||||
I.damage_coeff = connected.damage_coeff
|
||||
injector_ready = FALSE
|
||||
spawn(300)
|
||||
injector_ready = TRUE
|
||||
return TRUE
|
||||
randmuti(connected.occupant)
|
||||
else
|
||||
if(prob(95))
|
||||
randmutg(connected.occupant)
|
||||
else
|
||||
randmuti(connected.occupant)
|
||||
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
|
||||
|
||||
if(bufferOption == "loadDisk")
|
||||
if((isnull(disk)) || (!disk.buf))
|
||||
//temphtml = "Invalid disk. Please try again."
|
||||
return FALSE
|
||||
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)
|
||||
|
||||
buffers[bufferId] = disk.buf.copy()
|
||||
//temphtml = "Data loaded."
|
||||
return TRUE
|
||||
irradiating = radiation_duration
|
||||
var/lock_state = connected.locked
|
||||
connected.locked = TRUE //lock it
|
||||
|
||||
if(bufferOption == "saveDisk")
|
||||
if((isnull(disk)) || (disk.read_only))
|
||||
//temphtml = "Invalid disk. Please try again."
|
||||
return FALSE
|
||||
SStgui.update_uis(src)
|
||||
sleep(10 * radiation_duration) // sleep for radiation_duration seconds
|
||||
|
||||
var/datum/dna2/record/buf = buffers[bufferId]
|
||||
irradiating = 0
|
||||
connected.locked = lock_state
|
||||
|
||||
disk.buf = buf.copy()
|
||||
disk.name = "data disk - '[buf.dna.real_name]'"
|
||||
//temphtml = "Data saved."
|
||||
return TRUE
|
||||
if(!connected.occupant)
|
||||
return
|
||||
|
||||
if(prob((80 + (radiation_duration / 2))))
|
||||
var/radiation = (radiation_intensity + radiation_duration)
|
||||
connected.occupant.apply_effect(radiation,IRRADIATE,0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return
|
||||
|
||||
block = miniscrambletarget(num2text(selected_ui_target), radiation_intensity, radiation_duration)
|
||||
connected.occupant.dna.SetUISubBlock(selected_ui_block, selected_ui_subblock, block)
|
||||
connected.occupant.UpdateAppearance()
|
||||
else
|
||||
var/radiation = ((radiation_intensity * 2) + radiation_duration)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
if(connected.radiation_check())
|
||||
return
|
||||
|
||||
if(prob(20 + radiation_intensity))
|
||||
randmutb(connected.occupant)
|
||||
domutcheck(connected.occupant, connected)
|
||||
else
|
||||
randmuti(connected.occupant)
|
||||
connected.occupant.UpdateAppearance()
|
||||
////////////////////////////////////////////////////////
|
||||
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(connected.occupant, inject_amount)
|
||||
connected.beaker.reagents.reaction(connected.occupant)
|
||||
////////////////////////////////////////////////////////
|
||||
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)
|
||||
sleep(10 * radiation_duration) // sleep for radiation_duration seconds
|
||||
|
||||
irradiating = 0
|
||||
connected.locked = lock_state
|
||||
|
||||
if(connected.occupant)
|
||||
if(prob((80 + ((radiation_duration / 2) + (connected.precision_coeff ** 3)))))
|
||||
var/radiation = ((radiation_intensity + radiation_duration) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return 1
|
||||
|
||||
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)
|
||||
domutcheck(connected.occupant, connected)
|
||||
else
|
||||
var/radiation = (((radiation_intensity * 2) + radiation_duration) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return
|
||||
|
||||
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/reagent_containers/glass/B = connected.beaker
|
||||
B.forceMove(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))
|
||||
databuf.dna.real_name=connected.occupant.name
|
||||
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))
|
||||
databuf.dna.real_name=connected.occupant.dna.real_name
|
||||
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))
|
||||
databuf.dna.real_name = connected.occupant.dna.real_name
|
||||
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.scan_level < 3) || !connected.occupant.dna)
|
||||
return
|
||||
|
||||
irradiating = 2
|
||||
var/lock_state = connected.locked
|
||||
connected.locked = TRUE //lock it
|
||||
|
||||
SStgui.update_uis(src)
|
||||
sleep(2 SECONDS)
|
||||
|
||||
irradiating = 0
|
||||
connected.locked = lock_state
|
||||
|
||||
var/radiation = (rand(20,50) / connected.damage_coeff)
|
||||
connected.occupant.apply_effect(radiation, IRRADIATE, 0)
|
||||
|
||||
if(connected.radiation_check())
|
||||
return
|
||||
|
||||
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
|
||||
connected.occupant.UpdateAppearance(buf.dna.UI.Copy())
|
||||
else if(buf.types & DNA2_BUF_SE)
|
||||
connected.occupant.dna.SE = buf.dna.SE.Copy()
|
||||
connected.occupant.dna.UpdateSE()
|
||||
domutcheck(connected.occupant, connected)
|
||||
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)
|
||||
set waitfor = FALSE
|
||||
if(buffer_id < 1 || buffer_id > length(buffers))
|
||||
return
|
||||
|
||||
// Cooldown
|
||||
injector_ready = FALSE
|
||||
spawn(30 SECONDS)
|
||||
injector_ready = TRUE
|
||||
|
||||
// Create it
|
||||
var/datum/dna2/record/buf = buffers[buffer_id]
|
||||
var/obj/item/dnainjector/I = new()
|
||||
I.forceMove(loc)
|
||||
I.name += " ([buf.name])"
|
||||
if(copy_buffer)
|
||||
I.buf = buf.copy()
|
||||
if(connected)
|
||||
I.damage_coeff = connected.damage_coeff
|
||||
return I
|
||||
|
||||
/**
|
||||
* 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/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
|
||||
|
||||
@@ -1,313 +0,0 @@
|
||||
<!--
|
||||
Title: DNA Modifier UI
|
||||
Used In File(s): D:\Development\SS13-BS12\code\game\dna\dna_modifier.dm
|
||||
-->
|
||||
<h3>Status</h3>
|
||||
|
||||
<div class="statusDisplay">
|
||||
{{if !data.hasOccupant}}
|
||||
<div class="line">Cell Unoccupied</div>
|
||||
{{else}}
|
||||
<div class="line">
|
||||
{{:data.occupant.name}} =>
|
||||
{{if data.occupant.stat == 0}}
|
||||
<span class="good">Conscious</span>
|
||||
{{else data.occupant.stat == 1}}
|
||||
<span class="average">Unconscious</span>
|
||||
{{else}}
|
||||
<span class="bad">DEAD</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{if !data.occupant.isViableSubject || !data.occupant.uniqueIdentity || !data.occupant.structuralEnzymes}}
|
||||
<div class="notice">
|
||||
The occupant's DNA structure is ruined beyond recognition, please insert a subject with an intact DNA structure.
|
||||
</div>
|
||||
{{else data.occupant.stat < 2}}
|
||||
<div class="line">
|
||||
<div class="statusLabel">Health:</div>
|
||||
{{if data.occupant.health >= 0}}
|
||||
{{:helper.displayBar(data.occupant.health, 0, data.occupant.maxHealth, 'good')}}
|
||||
{{else}}
|
||||
{{:helper.displayBar(data.occupant.health, 0, data.occupant.minHealth, 'average alignRight')}}
|
||||
{{/if}}
|
||||
<div class="statusValue">{{:helper.smoothRound(data.occupant.health)}}</div>
|
||||
</div>
|
||||
|
||||
<div class="line">
|
||||
<div class="statusLabel">Radiation:</div>
|
||||
{{:helper.displayBar(data.occupant.radiationLevel, 0, 100, 'average')}}
|
||||
<div class="statusValue">{{:helper.smoothRound(data.occupant.radiationLevel)}}</div>
|
||||
</div>
|
||||
|
||||
<div class="line">
|
||||
<div class="statusLabel">Unique Enzymes:</div>
|
||||
<div class="statusValue">{{:data.occupant.uniqueEnzymes ? data.occupant.uniqueEnzymes : '<span class="bad">Unknown</span>'}}</div>
|
||||
</div>
|
||||
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<div class="clearBoth"></div>
|
||||
</div>
|
||||
|
||||
<h3>Operations</h3>
|
||||
{{if !data.occupant.isViableSubject || !data.occupant.uniqueIdentity || !data.occupant.structuralEnzymes}}
|
||||
<div class="notice">
|
||||
No operation possible on this subject
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="item">
|
||||
{{:helper.link('Modify U.I.', 'link', {'selectMenuKey' : 'ui'}, data.selectedMenuKey == 'ui' ? 'selected' : null)}}
|
||||
{{:helper.link('Modify S.E.', 'link', {'selectMenuKey' : 'se'}, data.selectedMenuKey == 'se' ? 'selected' : null)}}
|
||||
{{:helper.link('Transfer Buffers', 'floppy-o', {'selectMenuKey' : 'buffer'}, data.selectedMenuKey == 'buffer' ? 'selected' : null)}}
|
||||
{{:helper.link('Rejuvenators', 'plus', {'selectMenuKey' : 'rejuvenators'}, data.selectedMenuKey == 'rejuvenators' ? 'selected' : null)}}
|
||||
</div>
|
||||
|
||||
<div class="item"> </div>
|
||||
|
||||
{{if !data.selectedMenuKey || data.selectedMenuKey == 'ui'}}
|
||||
<h3>Modify Unique Identifier</h3>
|
||||
{{:helper.displayDNABlocks(data.occupant.uniqueIdentity, data.selectedUIBlock, data.selectedUISubBlock, data.dnaBlockSize, 'UI')}}
|
||||
<div class="clearBoth"></div>
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Target:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:helper.link('-', null, {'changeUITarget' : 0}, (data.selectedUITarget > 0) ? null : 'disabled')}}
|
||||
<div class="statusValue"> {{:data.selectedUITargetHex}} </div>
|
||||
{{:helper.link('+', null, {'changeUITarget' : 1}, (data.selectedUITarget < 15) ? null : 'disabled')}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="itemContentWide">
|
||||
{{:helper.link('Irradiate Block', 'exclamation-circle', {'pulseUIRadiation' : 1}, !data.occupant.isViableSubject ? 'disabled' : null)}}
|
||||
</div>
|
||||
</div>
|
||||
{{else data.selectedMenuKey == 'se'}}
|
||||
<h3>Modify Structural Enzymes</h3>
|
||||
{{:helper.displayDNABlocks(data.occupant.structuralEnzymes, data.selectedSEBlock, data.selectedSESubBlock, data.dnaBlockSize, 'SE')}}
|
||||
<div class="clearBoth"></div>
|
||||
<div class="item">
|
||||
<div class="itemContentWide">
|
||||
{{:helper.link('Irradiate Block', 'exclamation-circle', {'pulseSERadiation' : 1}, !data.occupant.isViableSubject ? 'disabled' : null)}}
|
||||
</div>
|
||||
</div>
|
||||
{{else data.selectedMenuKey == 'buffer'}}
|
||||
<h3>Transfer Buffers</h3>
|
||||
{{for data.buffers}}
|
||||
<h4>Buffer {{:(index + 1)}}</h4>
|
||||
<div class="itemGroup">
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Load Data:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:helper.link('Subject U.I.', 'link', {'bufferOption' : 'saveUI', 'bufferId' : (index + 1)}, !data.hasOccupant ? 'disabled' : null)}}
|
||||
{{:helper.link('Subject U.I. + U.E.', 'link', {'bufferOption' : 'saveUIAndUE', 'bufferId' : (index + 1)}, !data.hasOccupant ? 'disabled' : null)}}
|
||||
{{:helper.link('Subject S.E.', 'link', {'bufferOption' : 'saveSE', 'bufferId' : (index + 1)}, !data.hasOccupant ? 'disabled' : null)}}
|
||||
{{:helper.link('From Disk', 'floppy-o', {'bufferOption' : 'loadDisk', 'bufferId' : (index + 1)}, (!data.hasDisk || !data.disk.data) ? 'disabled' : null)}}
|
||||
</div>
|
||||
</div>
|
||||
{{if value.data}}
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Label:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:helper.link(value.label, 'file', {'bufferOption' : 'changeLabel', 'bufferId' : (index + 1)})}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Subject:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:value.owner ? value.owner : '<span class="average">Unknown</span>'}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Stored Data:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:value.data == 'ui' ? 'Unique Identifiers' : 'Structural Enzymes'}}
|
||||
{{:value.ue ? ' + Unique Enzymes' : ''}}
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="item">
|
||||
<div class="itemContentWide">
|
||||
<span class="highlight">This buffer is empty.</span>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Options:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:helper.link('Clear', 'trash', {'bufferOption' : 'clear', 'bufferId' : (index + 1)}, !value.data ? 'disabled' : null)}}
|
||||
{{:helper.link('Injector', data.isInjectorReady ? 'pencil' : 'clock-o', {'bufferOption' : 'createInjector', 'bufferId' : (index + 1)}, (!data.isInjectorReady || !value.data) ? 'disabled' : null)}}
|
||||
{{:helper.link('Block Injector', data.isInjectorReady ? 'pencil' : 'clock-o', {'bufferOption' : 'createInjector', 'bufferId' : (index + 1), 'createBlockInjector' : 1}, (!data.isInjectorReady || !value.data) ? 'disabled' : null)}}
|
||||
{{:helper.link('Transfer', 'exclamation-circle', {'bufferOption' : 'transfer', 'bufferId' : (index + 1)}, (!data.hasOccupant || !value.data) ? 'disabled' : null)}}
|
||||
{{:helper.link('Save To Disk', 'floppy-o', {'bufferOption' : 'saveDisk', 'bufferId' : (index + 1)}, (!value.data || !data.hasDisk) ? 'disabled' : null)}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/for}}
|
||||
|
||||
<h4>Data Disk</h4>
|
||||
<div class="itemGroup">
|
||||
{{if data.hasDisk}}
|
||||
{{if data.disk.data}}
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Label:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:data.disk.label ? data.disk.label : 'No Label'}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Subject:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:data.disk.owner ? data.disk.owner : '<span class="average">Unknown</span>'}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Stored Data:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:data.disk.data == 'ui' ? 'Unique Identifiers' : 'Structural Enzymes'}}
|
||||
{{:data.disk.ue ? ' + Unique Enzymes' : ''}}
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="item">
|
||||
<div class="itemContentWide">
|
||||
<span class="average">Disk is blank.</span>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<div class="item">
|
||||
<div class="itemContentWide">
|
||||
<span class="highlight">No disk inserted.</span>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Options:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:helper.link('Wipe Disk', 'trash', {'bufferOption' : 'wipeDisk'}, (!data.hasDisk || !data.disk.data) ? 'disabled' : null)}}
|
||||
{{:helper.link('Eject Disk', 'eject', {'bufferOption' : 'ejectDisk'}, !data.hasDisk ? 'disabled' : null)}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else data.selectedMenuKey == 'rejuvenators'}}
|
||||
<h3>Rejuvenators</h3>
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Inject:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:helper.link('5', 'pencil', {'injectRejuvenators' : 5}, (!data.hasOccupant || !data.beakerVolume) ? 'disabled' : null)}}
|
||||
{{:helper.link('10', 'pencil', {'injectRejuvenators' : 10}, (!data.hasOccupant || !data.beakerVolume) ? 'disabled' : null)}}
|
||||
{{:helper.link('20', 'pencil', {'injectRejuvenators' : 20}, (!data.hasOccupant || !data.beakerVolume) ? 'disabled' : null)}}
|
||||
{{:helper.link('30', 'pencil', {'injectRejuvenators' : 30}, (!data.hasOccupant || !data.beakerVolume) ? 'disabled' : null)}}
|
||||
{{:helper.link('50', 'pencil', {'injectRejuvenators' : 50}, (!data.hasOccupant || !data.beakerVolume) ? 'disabled' : null)}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item"> </div>
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Beaker:
|
||||
</div>
|
||||
<div class="itemContentWide" style="width: 40%;">
|
||||
{{if data.isBeakerLoaded}}
|
||||
{{:data.beakerLabel ? data.beakerLabel : '<span class="average">No label</span>'}}<br>
|
||||
{{if data.beakerVolume}}
|
||||
<span class="highlight">{{:data.beakerVolume}} units remaining</span><br>
|
||||
{{else}}
|
||||
<span class="bad">Beaker is empty</span>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<span class="average"><i>No beaker loaded</i></span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="itemContentWide" style="width: 26%;">
|
||||
{{:helper.link('Eject Beaker', 'eject', {'ejectBeaker' : 1}, data.isBeakerLoaded ? null : 'disabled')}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="item"> </div>
|
||||
|
||||
{{if !data.selectedMenuKey || data.selectedMenuKey == 'ui' || data.selectedMenuKey == 'se'}}
|
||||
<h3>Radiation Emitter Settings</h3>
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Intensity:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:helper.link('-', null, {'radiationIntensity' : 0}, (data.radiationIntensity > 1) ? null : 'disabled')}}
|
||||
<div class="statusValue"> {{:data.radiationIntensity}} </div>
|
||||
{{:helper.link('+', null, {'radiationIntensity' : 1}, (data.radiationIntensity < 10) ? null : 'disabled')}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Duration:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:helper.link('-', null, {'radiationDuration' : 0}, (data.radiationDuration > 2) ? null : 'disabled')}}
|
||||
<div class="statusValue"> {{:data.radiationDuration}} </div>
|
||||
{{:helper.link('+', null, {'radiationDuration' : 1}, (data.radiationDuration < 20) ? null : 'disabled')}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:helper.link('Pulse Radiation', 'exclamation-circle', {'pulseRadiation' : 1}, !data.hasOccupant ? 'disabled' : null)}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<div class="item"> </div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Occupant:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:helper.link('Eject Occupant', 'eject', {'ejectOccupant' : 1}, data.locked || !data.hasOccupant || data.irradiating ? 'disabled' : null)}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="itemLabelNarrow">
|
||||
Door Lock:
|
||||
</div>
|
||||
<div class="itemContentWide">
|
||||
{{:helper.link('Engaged', 'lock', {'toggleLock' : 1}, data.locked ? 'selected' : !data.hasOccupant ? 'disabled' : null)}}
|
||||
{{:helper.link('Disengaged', 'unlock', {'toggleLock' : 1}, !data.locked ? 'selected' : data.irradiating ? 'disabled' : null)}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if data.irradiating}}
|
||||
<div class="mask">
|
||||
<div class="maskContent">
|
||||
<h1>Irradiating Subject</h1>
|
||||
<h3>For {{:data.irradiating}} seconds.</h3>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
+1
-1
@@ -2470,10 +2470,10 @@
|
||||
#include "code\modules\telesci\bscrystal.dm"
|
||||
#include "code\modules\telesci\gps.dm"
|
||||
#include "code\modules\telesci\rcs.dm"
|
||||
#include "code\modules\tgui\modal.dm"
|
||||
#include "code\modules\telesci\telepad.dm"
|
||||
#include "code\modules\telesci\telesci_computer.dm"
|
||||
#include "code\modules\tgui\external.dm"
|
||||
#include "code\modules\tgui\modal.dm"
|
||||
#include "code\modules\tgui\states.dm"
|
||||
#include "code\modules\tgui\tgui.dm"
|
||||
#include "code\modules\tgui\modules\_base.dm"
|
||||
|
||||
@@ -0,0 +1,711 @@
|
||||
import { round, toFixed } from 'common/math';
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from "../backend";
|
||||
import { Window } from "../layouts";
|
||||
import { AnimatedNumber, Box, Button, Dimmer, Flex, Icon, Knob, LabeledList, ProgressBar, Section, Tabs } from "../components";
|
||||
import { ComplexModal } from './common/ComplexModal';
|
||||
|
||||
const stats = [
|
||||
['good', 'Alive'],
|
||||
['average', 'Critical'],
|
||||
['bad', 'DEAD'],
|
||||
];
|
||||
|
||||
const operations = [
|
||||
['ui', 'Modify U.I.', 'dna'],
|
||||
['se', 'Modify S.E.', 'dna'],
|
||||
['buffer', 'Transfer Buffers', 'syringe'],
|
||||
['rejuvenators', 'Rejuvenators', 'flask'],
|
||||
];
|
||||
|
||||
const rejuvenatorsDoses = [5, 10, 20, 30, 50];
|
||||
|
||||
export const DNAModifier = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
irradiating,
|
||||
dnaBlockSize,
|
||||
occupant,
|
||||
} = data;
|
||||
context.dnaBlockSize = dnaBlockSize;
|
||||
context.isDNAInvalid = !occupant.isViableSubject
|
||||
|| !occupant.uniqueIdentity
|
||||
|| !occupant.structuralEnzymes;
|
||||
let radiatingModal;
|
||||
if (irradiating) {
|
||||
radiatingModal = <DNAModifierIrradiating duration={irradiating} />;
|
||||
}
|
||||
return (
|
||||
<Window resizable>
|
||||
<ComplexModal />
|
||||
{radiatingModal}
|
||||
<Window.Content className="Layout__content--flexColumn">
|
||||
<DNAModifierOccupant />
|
||||
<DNAModifierMain />
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const DNAModifierOccupant = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
locked,
|
||||
hasOccupant,
|
||||
occupant,
|
||||
} = data;
|
||||
return (
|
||||
<Section
|
||||
title="Occupant"
|
||||
buttons={
|
||||
<Fragment>
|
||||
<Box color="label" display="inline" mr="0.5rem">
|
||||
Door Lock:
|
||||
</Box>
|
||||
<Button
|
||||
disabled={!hasOccupant}
|
||||
selected={locked}
|
||||
icon={locked ? "toggle-on" : "toggle-off"}
|
||||
content={locked ? "Engaged" : "Disengaged"}
|
||||
onClick={() => act('toggleLock')}
|
||||
/>
|
||||
<Button
|
||||
disabled={!hasOccupant || locked}
|
||||
icon="user-slash"
|
||||
content="Eject"
|
||||
onClick={() => act('ejectOccupant')}
|
||||
/>
|
||||
</Fragment>
|
||||
}>
|
||||
{hasOccupant ? (
|
||||
<Fragment>
|
||||
<Box>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Name">
|
||||
{occupant.name}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Health">
|
||||
<ProgressBar
|
||||
min={occupant.minHealth}
|
||||
max={occupant.maxHealth}
|
||||
value={occupant.health / occupant.maxHealth}
|
||||
ranges={{
|
||||
good: [0.5, Infinity],
|
||||
average: [0, 0.5],
|
||||
bad: [-Infinity, 0],
|
||||
}}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Status" color={stats[occupant.stat][0]}>
|
||||
{stats[occupant.stat][1]}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Divider />
|
||||
</LabeledList>
|
||||
</Box>
|
||||
{context.isDNAInvalid ? (
|
||||
<Box color="bad">
|
||||
<Icon name="exclamation-circle" />
|
||||
The occupant's DNA structure is ruined beyond recognition,
|
||||
please insert a subject with an intact DNA structure.
|
||||
</Box>
|
||||
) : (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Radiation">
|
||||
<ProgressBar
|
||||
min="0"
|
||||
max="100"
|
||||
value={occupant.radiationLevel / 100}
|
||||
color="average"
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Unique Enzymes">
|
||||
{data.occupant.uniqueEnzymes
|
||||
? data.occupant.uniqueEnzymes : (
|
||||
<Box color="bad">
|
||||
<Icon name="exclamation-circle" />
|
||||
Unknown
|
||||
</Box>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
)}
|
||||
</Fragment>
|
||||
) : (
|
||||
<Box color="label">
|
||||
Cell unoccupied.
|
||||
</Box>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const DNAModifierMain = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
selectedMenuKey,
|
||||
hasOccupant,
|
||||
occupant,
|
||||
} = data;
|
||||
if (!hasOccupant) {
|
||||
return (
|
||||
<Section flexGrow="1">
|
||||
<Flex height="100%">
|
||||
<Flex.Item
|
||||
grow="1"
|
||||
align="center"
|
||||
textAlign="center"
|
||||
color="label">
|
||||
<Icon
|
||||
name="user-slash"
|
||||
mb="0.5rem"
|
||||
size="5"
|
||||
/><br />
|
||||
No occupant in cell.
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
);
|
||||
} else if (context.isDNAInvalid) {
|
||||
return (
|
||||
<Section flexGrow="1">
|
||||
<Flex height="100%">
|
||||
<Flex.Item
|
||||
grow="1"
|
||||
align="center"
|
||||
textAlign="center"
|
||||
color="label">
|
||||
<Icon
|
||||
name="user-slash"
|
||||
mb="0.5rem"
|
||||
size="5"
|
||||
/><br />
|
||||
No operation possible on this subject.
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
let body;
|
||||
if (selectedMenuKey === "ui") {
|
||||
body = (
|
||||
<Fragment>
|
||||
<DNAModifierMainUI />
|
||||
<DNAModifierMainRadiationEmitter />
|
||||
</Fragment>
|
||||
);
|
||||
} else if (selectedMenuKey === "se") {
|
||||
body = (
|
||||
<Fragment>
|
||||
<DNAModifierMainSE />
|
||||
<DNAModifierMainRadiationEmitter />
|
||||
</Fragment>
|
||||
);
|
||||
} else if (selectedMenuKey === "buffer") {
|
||||
body = <DNAModifierMainBuffers />;
|
||||
} else if (selectedMenuKey === "rejuvenators") {
|
||||
body = <DNAModifierMainRejuvenators />;
|
||||
}
|
||||
return (
|
||||
<Section flexGrow="1">
|
||||
<Tabs>
|
||||
{operations.map((op, i) => (
|
||||
<Tabs.Tab
|
||||
key={i}
|
||||
selected={selectedMenuKey === op[0]}
|
||||
onClick={() => act('selectMenuKey', { key: op[0] })}>
|
||||
<Icon name={op[2]} />
|
||||
{op[1]}
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
</Tabs>
|
||||
{body}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const DNAModifierMainUI = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
selectedUIBlock,
|
||||
selectedUISubBlock,
|
||||
selectedUITarget,
|
||||
selectedUITargetHex,
|
||||
occupant,
|
||||
} = data;
|
||||
return (
|
||||
<Section title="Modify Unique Identifier" level="2">
|
||||
<DNAModifierBlocks
|
||||
dnaString={occupant.uniqueIdentity}
|
||||
selectedBlock={selectedUIBlock}
|
||||
selectedSubblock={selectedUISubBlock}
|
||||
blockSize={context.dnaBlockSize}
|
||||
action="selectUIBlock"
|
||||
/>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Target">
|
||||
<Knob
|
||||
minValue="1"
|
||||
maxValue="15"
|
||||
stepPixelSize="20"
|
||||
value={selectedUITarget}
|
||||
format={value => value.toString(16).toUpperCase()}
|
||||
ml="0"
|
||||
onChange={(e, val) => act('changeUITarget', { value: val })}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
<Button
|
||||
icon="radiation"
|
||||
content="Irradiate Block"
|
||||
mt="0.5rem"
|
||||
onClick={() => act('pulseUIRadiation')}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const DNAModifierMainSE = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
selectedSEBlock,
|
||||
selectedSESubBlock,
|
||||
occupant,
|
||||
} = data;
|
||||
return (
|
||||
<Section title="Modify Structural Enzymes" level="2">
|
||||
<DNAModifierBlocks
|
||||
dnaString={occupant.structuralEnzymes}
|
||||
selectedBlock={selectedSEBlock}
|
||||
selectedSubblock={selectedSESubBlock}
|
||||
blockSize={context.dnaBlockSize}
|
||||
action="selectSEBlock"
|
||||
/>
|
||||
<Button
|
||||
icon="radiation"
|
||||
content="Irradiate Block"
|
||||
onClick={() => act('pulseSERadiation')}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const DNAModifierMainRadiationEmitter = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
radiationIntensity,
|
||||
radiationDuration,
|
||||
} = data;
|
||||
return (
|
||||
<Section title="Radiation Emitter" level="2">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Intensity">
|
||||
<Knob
|
||||
minValue="1"
|
||||
maxValue="10"
|
||||
stepPixelSize="20"
|
||||
value={radiationIntensity}
|
||||
ml="0"
|
||||
onChange={(e, val) => act('radiationIntensity', { value: val })}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Duration">
|
||||
<Knob
|
||||
minValue="1"
|
||||
maxValue="20"
|
||||
stepPixelSize="10"
|
||||
unit="s"
|
||||
value={radiationDuration}
|
||||
ml="0"
|
||||
onChange={(e, val) => act('radiationDuration', { value: val })}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
<Button
|
||||
icon="radiation"
|
||||
content="Pulse Radiation"
|
||||
tooltip="Mutates a random block of either the occupant's UI or SE."
|
||||
tooltipPosition="top-right"
|
||||
mt="0.5rem"
|
||||
onClick={() => act('pulseRadiation')}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const DNAModifierMainBuffers = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
buffers,
|
||||
} = data;
|
||||
let bufferElements = buffers.map((buffer, i) => (
|
||||
<DNAModifierMainBuffersElement
|
||||
key={i}
|
||||
id={i + 1}
|
||||
name={"Buffer " + (i + 1)}
|
||||
buffer={buffer}
|
||||
/>
|
||||
));
|
||||
return (
|
||||
<Fragment>
|
||||
<Section title="Buffers" level="2">
|
||||
{bufferElements}
|
||||
</Section>
|
||||
<DNAModifierMainBuffersDisk />
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const DNAModifierMainBuffersElement = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
id,
|
||||
name,
|
||||
buffer,
|
||||
} = props;
|
||||
const isInjectorReady = data.isInjectorReady;
|
||||
const realName = name + (buffer.data ? ' - ' + buffer.label : '');
|
||||
return (
|
||||
<Box backgroundColor="rgba(0, 0, 0, 0.33)" mb="0.5rem">
|
||||
<Section
|
||||
title={realName}
|
||||
level="3"
|
||||
mx="0"
|
||||
lineHeight="18px"
|
||||
buttons={
|
||||
<Fragment>
|
||||
<Button.Confirm
|
||||
disabled={!buffer.data}
|
||||
icon="trash"
|
||||
content="Clear"
|
||||
onClick={() => act('bufferOption', {
|
||||
option: 'clear',
|
||||
id: id,
|
||||
})}
|
||||
/>
|
||||
<Button
|
||||
disabled={!buffer.data}
|
||||
icon="pen"
|
||||
content="Rename"
|
||||
onClick={() => act('bufferOption', {
|
||||
option: 'changeLabel',
|
||||
id: id,
|
||||
})}
|
||||
/>
|
||||
<Button
|
||||
disabled={!buffer.data || !data.hasDisk}
|
||||
icon="save"
|
||||
content="Export"
|
||||
tooltip="Exports this buffer to the currently loaded data disk."
|
||||
tooltipPosition="bottom-left"
|
||||
onClick={() => act('bufferOption', {
|
||||
option: 'saveDisk',
|
||||
id: id,
|
||||
})}
|
||||
/>
|
||||
</Fragment>
|
||||
}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Write">
|
||||
<Button
|
||||
icon="arrow-circle-down"
|
||||
content="Subject U.I"
|
||||
mb="0"
|
||||
onClick={() => act('bufferOption', {
|
||||
option: 'saveUI',
|
||||
id: id,
|
||||
})}
|
||||
/>
|
||||
<Button
|
||||
icon="arrow-circle-down"
|
||||
content="Subject U.I and U.E."
|
||||
mb="0"
|
||||
onClick={() => act('bufferOption', {
|
||||
option: 'saveUIAndUE',
|
||||
id: id,
|
||||
})}
|
||||
/>
|
||||
<Button
|
||||
icon="arrow-circle-down"
|
||||
content="Subject S.E."
|
||||
mb="0"
|
||||
onClick={() => act('bufferOption', {
|
||||
option: 'saveSE',
|
||||
id: id,
|
||||
})}
|
||||
/>
|
||||
<Button
|
||||
disabled={!data.hasDisk || !data.disk.data}
|
||||
icon="arrow-circle-down"
|
||||
content="From Disk"
|
||||
mb="0"
|
||||
onClick={() => act('bufferOption', {
|
||||
option: 'loadDisk',
|
||||
id: id,
|
||||
})}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
{!!buffer.data && (
|
||||
<Fragment>
|
||||
<LabeledList.Item label="Subject">
|
||||
{buffer.owner || (
|
||||
<Box color="average">
|
||||
Unknown
|
||||
</Box>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Data Type">
|
||||
{buffer.type === "ui"
|
||||
? "Unique Identifiers"
|
||||
: "Structural Enzymes"}
|
||||
{!!buffer.ue && " and Unique Enzymes"}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Transfer to">
|
||||
<Button
|
||||
disabled={!isInjectorReady}
|
||||
icon={isInjectorReady ? "syringe" : "spinner"}
|
||||
iconSpin={!isInjectorReady}
|
||||
content="Injector"
|
||||
mb="0"
|
||||
onClick={() => act('bufferOption', {
|
||||
option: 'createInjector',
|
||||
id: id,
|
||||
})}
|
||||
/>
|
||||
<Button
|
||||
disabled={!isInjectorReady}
|
||||
icon={isInjectorReady ? "syringe" : "spinner"}
|
||||
iconSpin={!isInjectorReady}
|
||||
content="Block Injector"
|
||||
mb="0"
|
||||
onClick={() => act('bufferOption', {
|
||||
option: 'createInjector',
|
||||
id: id,
|
||||
block: 1,
|
||||
})}
|
||||
/>
|
||||
<Button
|
||||
icon="user"
|
||||
content="Subject"
|
||||
mb="0"
|
||||
onClick={() => act('bufferOption', {
|
||||
option: 'transfer',
|
||||
id: id,
|
||||
})}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</Fragment>
|
||||
)}
|
||||
</LabeledList>
|
||||
{!buffer.data && (
|
||||
<Box color="label" mt="0.5rem">
|
||||
This buffer is empty.
|
||||
</Box>
|
||||
)}
|
||||
</Section>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const DNAModifierMainBuffersDisk = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
hasDisk,
|
||||
disk,
|
||||
} = data;
|
||||
return (
|
||||
<Section
|
||||
title="Data Disk"
|
||||
level="2"
|
||||
buttons={
|
||||
<Fragment>
|
||||
<Button.Confirm
|
||||
disabled={!hasDisk || !disk.data}
|
||||
icon="trash"
|
||||
content="Wipe"
|
||||
onClick={() => act('wipeDisk')}
|
||||
/>
|
||||
<Button
|
||||
disabled={!hasDisk}
|
||||
icon="eject"
|
||||
content="Eject"
|
||||
onClick={() => act('ejectDisk')}
|
||||
/>
|
||||
</Fragment>
|
||||
}>
|
||||
{hasDisk ? (
|
||||
disk.data ? (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Label">
|
||||
{disk.label ? disk.label : "No label"}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Subject">
|
||||
{disk.owner
|
||||
? disk.owner : (
|
||||
<Box color="average">
|
||||
Unknown
|
||||
</Box>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Data Type">
|
||||
{disk.type === "ui"
|
||||
? "Unique Identifiers"
|
||||
: "Structural Enzymes"}
|
||||
{!!disk.ue && " and Unique Enzymes"}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
) : (
|
||||
<Box color="label">
|
||||
Disk is blank.
|
||||
</Box>
|
||||
)
|
||||
) : (
|
||||
<Box color="label" textAlign="center" my="1rem">
|
||||
<Icon name="save-o" size="4" /><br />
|
||||
No disk inserted.
|
||||
</Box>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const DNAModifierMainRejuvenators = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
isBeakerLoaded,
|
||||
beakerVolume,
|
||||
beakerLabel,
|
||||
} = data;
|
||||
return (
|
||||
<Section
|
||||
title="Rejuvenators and Beaker"
|
||||
level="2"
|
||||
buttons={
|
||||
<Button
|
||||
disabled={!isBeakerLoaded}
|
||||
icon="eject"
|
||||
content="Eject"
|
||||
onClick={() => act('ejectBeaker')}
|
||||
/>
|
||||
}>
|
||||
{isBeakerLoaded ? (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Inject">
|
||||
{rejuvenatorsDoses.map((a, i) => (
|
||||
<Button
|
||||
key={i}
|
||||
disabled={a > beakerVolume}
|
||||
icon="syringe"
|
||||
content={a}
|
||||
onClick={() => act('injectRejuvenators', {
|
||||
amount: a,
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
<Button
|
||||
disabled={beakerVolume <= 0}
|
||||
icon="syringe"
|
||||
content="All"
|
||||
onClick={() => act('injectRejuvenators', {
|
||||
amount: beakerVolume,
|
||||
})}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Beaker">
|
||||
<Box mb="0.5rem">
|
||||
{beakerLabel ? beakerLabel : "No label"}
|
||||
</Box>
|
||||
{beakerVolume ? (
|
||||
<Box color="good">
|
||||
{beakerVolume} unit{beakerVolume === 1 ? "" : "s"} remaining
|
||||
</Box>
|
||||
) : (
|
||||
<Box color="bad">
|
||||
Empty
|
||||
</Box>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
) : (
|
||||
<Box color="label" textAlign="center" my="25%">
|
||||
<Icon name="exclamation-triangle" size="4" /><br />
|
||||
No beaker loaded.
|
||||
</Box>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const DNAModifierIrradiating = (props, context) => {
|
||||
return (
|
||||
<Dimmer textAlign="center">
|
||||
<Icon name="spinner" size="5" spin /><br />
|
||||
<Box color="average">
|
||||
<h1>
|
||||
<Icon name="radiation" />
|
||||
Irradiating occupant
|
||||
<Icon name="radiation" />
|
||||
</h1>
|
||||
</Box>
|
||||
<Box color="label">
|
||||
<h3>
|
||||
For {props.duration} second{props.duration === 1 ? "" : "s"}
|
||||
</h3>
|
||||
</Box>
|
||||
</Dimmer>
|
||||
);
|
||||
};
|
||||
|
||||
const DNAModifierBlocks = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
dnaString,
|
||||
selectedBlock,
|
||||
selectedSubblock,
|
||||
blockSize,
|
||||
action,
|
||||
} = props;
|
||||
|
||||
const characters = dnaString.split('');
|
||||
let curBlock = 0;
|
||||
let dnaBlocks = [];
|
||||
for (let block = 0; block < characters.length; block += blockSize) {
|
||||
const realBlock = block / blockSize + 1;
|
||||
let subBlocks = [];
|
||||
for (let subblock = 0; subblock < blockSize; subblock++) {
|
||||
const realSubblock = subblock + 1;
|
||||
subBlocks.push(
|
||||
<Button
|
||||
selected={selectedBlock === realBlock
|
||||
&& selectedSubblock === realSubblock}
|
||||
content={characters[block + subblock]}
|
||||
mb="0"
|
||||
onClick={() => act(action, {
|
||||
block: realBlock,
|
||||
subblock: realSubblock,
|
||||
})}
|
||||
/>
|
||||
);
|
||||
}
|
||||
dnaBlocks.push(
|
||||
<Flex.Item flex="0 0 16%" mb="1rem">
|
||||
<Box
|
||||
display="inline-block"
|
||||
width="20px"
|
||||
height="20px"
|
||||
mr="0.5rem"
|
||||
lineHeight="20px"
|
||||
backgroundColor="rgba(0, 0, 0, 0.33)"
|
||||
fontFamily="monospace"
|
||||
textAlign="center">
|
||||
{realBlock}
|
||||
</Box>
|
||||
{subBlocks}
|
||||
</Flex.Item>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Flex wrap="wrap">
|
||||
{dnaBlocks}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -56,6 +56,26 @@ $border-radius: base.$border-radius !default;
|
||||
transform: translateX(-50%) translateY(-8px);
|
||||
}
|
||||
|
||||
.Tooltip--top-left::after {
|
||||
bottom: 100%;
|
||||
right: 50%;
|
||||
transform: translateX(12px) translateY(-8px);
|
||||
}
|
||||
|
||||
.Tooltip--top-left:hover::after {
|
||||
transform: translateX(12px) translateY(8px);
|
||||
}
|
||||
|
||||
.Tooltip--top-right::after {
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-12px) translateY(-8px);
|
||||
}
|
||||
|
||||
.Tooltip--top-right:hover::after {
|
||||
transform: translateX(-12px) translateY(8px);
|
||||
}
|
||||
|
||||
.Tooltip--bottom::after {
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
|
||||
Reference in New Issue
Block a user