TGUI Medical: DNA Modifier

This commit is contained in:
mochi
2020-07-10 21:16:07 +02:00
parent afbff79208
commit 2c78bf0e8a
8 changed files with 1064 additions and 721 deletions
+1
View File
@@ -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
View File
@@ -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
-313
View File
@@ -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}}&nbsp;=>&nbsp;
{{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">&nbsp;</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">&nbsp;{{:data.selectedUITargetHex}}&nbsp;</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">&nbsp;</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">&nbsp;</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">&nbsp;{{:data.radiationIntensity}}&nbsp;</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">&nbsp;{{:data.radiationDuration}}&nbsp;</div>
{{:helper.link('+', null, {'radiationDuration' : 1}, (data.radiationDuration < 20) ? null : 'disabled')}}
</div>
</div>
<div class="item">
<div class="itemLabelNarrow">
&nbsp;
</div>
<div class="itemContentWide">
{{:helper.link('Pulse Radiation', 'exclamation-circle', {'pulseRadiation' : 1}, !data.hasOccupant ? 'disabled' : null)}}
</div>
</div>
{{/if}}
{{/if}}
<div class="item">&nbsp;</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
View File
@@ -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" />&nbsp;
The occupant&apos;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" />&nbsp;
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" />
&nbsp;Irradiating occupant&nbsp;
<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%;