diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm index b56024bfab8..070aaaa2249 100644 --- a/code/__DEFINES/machines.dm +++ b/code/__DEFINES/machines.dm @@ -92,3 +92,8 @@ // Firelock states #define FD_OPEN 1 #define FD_CLOSED 2 + +// Computer login types +#define LOGIN_TYPE_NORMAL 1 +#define LOGIN_TYPE_AI 2 +#define LOGIN_TYPE_ROBOT 3 diff --git a/code/__DEFINES/tgui.dm b/code/__DEFINES/tgui.dm new file mode 100644 index 00000000000..0ef159f11c2 --- /dev/null +++ b/code/__DEFINES/tgui.dm @@ -0,0 +1,8 @@ +// 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 +#define TGUI_MODAL_ANSWER 3 +#define TGUI_MODAL_CLOSE 4 diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index d887153c6d5..3158cf90303 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -7,6 +7,11 @@ #define NEGATE_MUTATION_THRESHOLD 30 // Occupants with over ## percent radiation threshold will not gain mutations +#define PAGE_UI "ui" +#define PAGE_SE "se" +#define PAGE_BUFFER "buffer" +#define PAGE_REJUVENATORS "rejuvenators" + //list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0), /datum/dna2/record var/datum/dna/dna = null @@ -161,6 +166,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)) @@ -214,6 +220,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 @@ -260,6 +267,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)) \ @@ -281,6 +289,7 @@ occupant.forceMove(loc) occupant = null icon_state = "scanner_open" + SStgui.update_uis(src) /obj/machinery/dna_scannernew/force_eject_occupant() go_out(null, TRUE) @@ -296,6 +305,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() @@ -333,12 +343,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 = PAGE_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 @@ -347,7 +356,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 ..() @@ -399,35 +408,18 @@ 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) -/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 @@ -501,9 +493,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)) @@ -512,405 +507,350 @@ return FALSE // don't update uis if(irradiating) // Make sure that it isn't already irradiating someone... return FALSE // don't update uis + if(stat & (NOPOWER|BROKEN)) + return 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(usr) - 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(PAGE_UI, PAGE_SE, PAGE_BUFFER, PAGE_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) + if(buffer_id < 1 || buffer_id > length(buffers)) + return + + // Cooldown + injector_ready = FALSE + addtimer(CALLBACK(src, .proc/injector_cooldown_finish), 30 SECONDS) + + // Create it + var/datum/dna2/record/buf = buffers[buffer_id] + var/obj/item/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 when the injector creation cooldown finishes + */ +/obj/machinery/computer/scan_consolenew/proc/injector_cooldown_finish() + injector_ready = TRUE + +/** + * Called in tgui_act() to process modal actions + * + * Arguments: + * * action - The action passed by tgui + * * params - The params passed by tgui + */ +/obj/machinery/computer/scan_consolenew/proc/tgui_act_modal(action, params) + . = TRUE + var/id = params["id"] // The modal's ID + var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"] + switch(tgui_modal_act(src, action, params)) + if(TGUI_MODAL_ANSWER) + var/answer = params["answer"] + switch(id) + if("createInjectorBlock") + var/buffer_id = text2num(arguments["id"]) + if(buffer_id < 1 || buffer_id > length(buffers)) + return + var/datum/dna2/record/buf = buffers[buffer_id] + var/obj/item/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 + + +#undef PAGE_UI +#undef PAGE_SE +#undef PAGE_BUFFER +#undef PAGE_REJUVENATORS /////////////////////////// DNA MACHINES diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 7c5a03e29e6..d33518be857 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -125,7 +125,7 @@ return attack_hand(user) /obj/machinery/sleeper/attack_ghost(mob/user) - return attack_hand(user) + tgui_interact(user) /obj/machinery/sleeper/attack_hand(mob/user) if(stat & (NOPOWER|BROKEN)) @@ -135,17 +135,17 @@ to_chat(user, "Close the maintenance panel first.") return - ui_interact(user) + tgui_interact(user) -/obj/machinery/sleeper/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/sleeper/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) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "sleeper.tmpl", "Sleeper", 550, 770) + ui = new(user, src, ui_key, "Sleeper", "Sleeper", 550, 775) ui.open() - ui.set_auto_update(1) -/obj/machinery/sleeper/ui_data(mob/user, datum/topic_state/state) +/obj/machinery/sleeper/tgui_data(mob/user) var/data[0] + data["amounts"] = amounts data["hasOccupant"] = occupant ? 1 : 0 var/occupantData[0] var/crisis = 0 @@ -210,9 +210,13 @@ if(beaker) data["isBeakerLoaded"] = 1 if(beaker.reagents) + data["beakerMaxSpace"] = beaker.reagents.maximum_volume data["beakerFreeSpace"] = round(beaker.reagents.maximum_volume - beaker.reagents.total_volume) else + data["beakerMaxSpace"] = 0 data["beakerFreeSpace"] = 0 + else + data["isBeakerLoaded"] = FALSE var/chemicals[0] for(var/re in possible_chems) @@ -234,51 +238,52 @@ if(temp.id in occupant.reagents.overdose_list()) overdosing = 1 - // Because I don't know how to do this on the nano side pretty_amount = round(reagent_amount, 0.05) chemicals.Add(list(list("title" = temp.name, "id" = temp.id, "commands" = list("chemical" = temp.id), "occ_amount" = reagent_amount, "pretty_amount" = pretty_amount, "injectable" = injectable, "overdosing" = overdosing, "od_warning" = caution))) data["chemicals"] = chemicals return data -/obj/machinery/sleeper/Topic(href, href_list) - if(!controls_inside && usr == occupant) - return 0 - +/obj/machinery/sleeper/tgui_act(action, params) if(..()) - return 1 - + return + if(!controls_inside && usr == occupant) + return if(panel_open) to_chat(usr, "Close the maintenance panel first.") - return 0 + return + if(stat & (NOPOWER|BROKEN)) + return - if((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon/ai))) - if(href_list["chemical"]) - if(occupant) - if(occupant.stat == DEAD) - to_chat(usr, "This person has no life for to preserve anymore. Take [occupant.p_them()] to a department capable of reanimating them.") - else if(occupant.health > min_health || (href_list["chemical"] in emergency_chems)) - inject_chemical(usr,href_list["chemical"],text2num(href_list["amount"])) - else - to_chat(usr, "This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!") - - if(href_list["removebeaker"]) + . = TRUE + switch(action) + if("chemical") + if(!occupant) + return + if(occupant.stat == DEAD) + to_chat(usr, "This person has no life to preserve anymore. Take [occupant.p_them()] to a department capable of reanimating them.") + return + var/chemical = params["chemid"] + var/amount = text2num(params["amount"]) + if(!length(chemical) || amount <= 0) + return + if(occupant.health > min_health || (chemical in emergency_chems)) + inject_chemical(usr, chemical, amount) + else + to_chat(usr, "This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!") + if("removebeaker") remove_beaker() - - if(href_list["togglefilter"]) + if("togglefilter") toggle_filter() - - if(href_list["ejectify"]) + if("ejectify") eject() - - if(href_list["auto_eject_dead_on"]) + if("auto_eject_dead_on") auto_eject_dead = TRUE - - if(href_list["auto_eject_dead_off"]) + if("auto_eject_dead_off") auto_eject_dead = FALSE - - add_fingerprint(usr) - return 1 + else + return FALSE + add_fingerprint(usr) /obj/machinery/sleeper/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/reagent_containers/glass)) @@ -290,6 +295,7 @@ beaker = I I.forceMove(src) user.visible_message("[user] adds \a [I] to [src]!", "You add \a [I] to [src]!") + SStgui.update_uis(src) return else @@ -328,6 +334,7 @@ to_chat(M, "You feel cool air surround you. You go numb as your senses turn inward.") add_fingerprint(user) qdel(G) + SStgui.update_uis(src) return return ..() @@ -374,9 +381,11 @@ occupant = null updateUsrDialog() update_icon() + SStgui.update_uis(src) if(A == beaker) beaker = null updateUsrDialog() + SStgui.update_uis(src) /obj/machinery/sleeper/emp_act(severity) if(filtering) @@ -394,7 +403,7 @@ qdel(src) /obj/machinery/sleeper/proc/toggle_filter() - if(filtering) + if(filtering || !beaker) filtering = 0 else filtering = 1 @@ -410,29 +419,28 @@ // eject trash the occupant dropped for(var/atom/movable/A in contents - component_parts - list(beaker)) A.forceMove(loc) + SStgui.update_uis(src) /obj/machinery/sleeper/force_eject_occupant() go_out() -/obj/machinery/sleeper/proc/inject_chemical(mob/living/user as mob, chemical, amount) +/obj/machinery/sleeper/proc/inject_chemical(mob/living/user, chemical, amount) if(!(chemical in possible_chems)) to_chat(user, "The sleeper does not offer that chemical!") return + if(!(amount in amounts)) + return if(occupant) if(occupant.reagents) if(occupant.reagents.get_reagent_amount(chemical) + amount <= max_chem) occupant.reagents.add_reagent(chemical, amount) - return else to_chat(user, "You can not inject any more of this chemical.") - return else to_chat(user, "The patient rejects the chemicals!") - return else to_chat(user, "There's no occupant in the sleeper!") - return /obj/machinery/sleeper/verb/eject() set name = "Eject Sleeper" @@ -459,6 +467,7 @@ filtering = 0 beaker.forceMove(usr.loc) beaker = null + SStgui.update_uis(src) add_fingerprint(usr) return @@ -511,6 +520,7 @@ add_fingerprint(user) if(user.pulling == L) user.stop_pulling() + SStgui.update_uis(src) return return @@ -547,6 +557,7 @@ for(var/obj/O in src) qdel(O) add_fingerprint(usr) + SStgui.update_uis(src) return return diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 3fa78dd02e6..97ab80fc1d7 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -65,6 +65,7 @@ icon_state = "body_scanner_1" add_fingerprint(user) qdel(TYPECAST_YOUR_SHIT) + SStgui.update_uis(src) return return ..() @@ -127,12 +128,13 @@ occupant = H icon_state = "bodyscanner" add_fingerprint(user) + SStgui.update_uis(src) /obj/machinery/bodyscanner/attack_ai(user) return attack_hand(user) /obj/machinery/bodyscanner/attack_ghost(user) - return attack_hand(user) + tgui_interact(user) /obj/machinery/bodyscanner/attack_hand(user) if(stat & (NOPOWER|BROKEN)) @@ -145,7 +147,7 @@ to_chat(user, "Close the maintenance panel first.") return - ui_interact(user) + tgui_interact(user) /obj/machinery/bodyscanner/relaymove(mob/user) if(user.incapacitated()) @@ -171,6 +173,7 @@ // eject trash the occupant dropped for(var/atom/movable/A in contents - component_parts) A.forceMove(loc) + SStgui.update_uis(src) /obj/machinery/bodyscanner/force_eject_occupant() go_out() @@ -192,17 +195,16 @@ new /obj/effect/gibspawner/generic(get_turf(loc)) //I REPLACE YOUR TECHNOLOGY WITH FLESH! qdel(src) -/obj/machinery/bodyscanner/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/bodyscanner/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) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "adv_med.tmpl", "Body Scanner", 690, 600) + ui = new(user, src, ui_key, "BodyScanner", "Body Scanner", 690, 600) ui.open() - ui.set_auto_update(1) -/obj/machinery/bodyscanner/ui_data(mob/user, datum/topic_state/state) +/obj/machinery/bodyscanner/tgui_data(mob/user) var/data[0] - data["occupied"] = occupant ? 1 : 0 + data["occupied"] = occupant ? TRUE : FALSE var/occupantData[0] if(occupant) @@ -236,9 +238,9 @@ occupantData["hasBorer"] = occupant.has_brain_worms() var/bloodData[0] - bloodData["hasBlood"] = 0 + bloodData["hasBlood"] = FALSE if(!(NO_BLOOD in occupant.dna.species.species_traits)) - bloodData["hasBlood"] = 1 + bloodData["hasBlood"] = TRUE bloodData["volume"] = occupant.blood_volume bloodData["percent"] = round(((occupant.blood_volume / BLOOD_VOLUME_NORMAL)*100)) bloodData["pulse"] = occupant.get_pulse(GETPULSE_TOOL) @@ -282,19 +284,19 @@ if(E.status & ORGAN_BROKEN) organStatus["broken"] = E.broken_description if(E.is_robotic()) - organStatus["robotic"] = 1 + organStatus["robotic"] = TRUE if(E.status & ORGAN_SPLINTED) - organStatus["splinted"] = 1 + organStatus["splinted"] = TRUE if(E.status & ORGAN_DEAD) - organStatus["dead"] = 1 + organStatus["dead"] = TRUE organData["status"] = organStatus if(istype(E, /obj/item/organ/external/chest) && occupant.is_lung_ruptured()) - organData["lungRuptured"] = 1 + organData["lungRuptured"] = TRUE if(E.internal_bleeding) - organData["internalBleeding"] = 1 + organData["internalBleeding"] = TRUE extOrganData.Add(list(organData)) @@ -319,27 +321,33 @@ occupantData["blind"] = (BLINDNESS in occupant.mutations) occupantData["colourblind"] = (COLOURBLIND in occupant.mutations) - occupantData["nearsighted"] = (NEARSIGHTED in occupant.mutations) + occupantData["nearsighted"] = (NEARSIGHTED in occupant.mutations) data["occupant"] = occupantData return data -/obj/machinery/bodyscanner/Topic(href, href_list) +/obj/machinery/bodyscanner/tgui_act(action, params) if(..()) - return 1 + return + if(stat & (NOPOWER|BROKEN)) + return - if(href_list["ejectify"]) - eject() - - if(href_list["print_p"]) - visible_message("[src] rattles and prints out a sheet of paper.") - var/obj/item/paper/P = new /obj/item/paper(loc) - playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1) - P.info = "
![]() | "
- if(j == 5)
- dat += "
![]() | "
- if(j == 5)
- dat += "
| Brute Damage: | -Brain Damage: | -
| {{:helper.displayBar(data.occupant.bruteLoss, 0, data.occupant.maxHealth+100, (data.occupant.bruteLoss < 15) ? 'notgood' : (data.occupant.bruteLoss < 40) ? 'average' : 'bad', data.occupant.bruteLoss) }} | -{{:helper.displayBar(data.occupant.brainLoss, 0, data.occupant.maxHealth+100, (data.occupant.brainLoss < 15) ? 'notgood' : (data.occupant.brainLoss < 40) ? 'average' : 'bad', data.occupant.brainLoss)}} | -
| Resp. Damage: | -Radiation Level: | -
| {{:helper.displayBar(data.occupant.oxyLoss, 0, data.occupant.maxHealth+100, (data.occupant.oxyLoss < 15) ? 'notgood' : (data.occupant.oxyLoss < 40) ? 'average' : 'bad', data.occupant.oxyLoss)}} | -{{:helper.displayBar(data.occupant.radLoss, 0, data.occupant.maxHealth+100, (data.occupant.radLoss < 15) ? 'notgood' : (data.occupant.radLoss < 40) ? 'average' : 'bad', data.occupant.radLoss)}} | -
| Toxin Damage: | -Genetic Damage: | -
| {{:helper.displayBar(data.occupant.toxLoss, 0, data.occupant.maxHealth+100, (data.occupant.toxLoss < 15) ? 'notgood' : (data.occupant.toxLoss < 40) ? 'average' : 'bad', data.occupant.toxLoss)}} | -{{:helper.displayBar(data.occupant.cloneLoss, 0, data.occupant.maxHealth+100, (data.occupant.cloneLoss < 15) ? 'notgood' : (data.occupant.cloneLoss < 40) ? 'average' : 'bad', data.occupant.cloneLoss)}} | -
| Burn Severity: | -Paralysis %: ({{:helper.smoothRound(data.occupant.paralysisSeconds)}} seconds left) | -
| {{:helper.displayBar(data.occupant.fireLoss, 0, data.occupant.maxHealth+100, (data.occupant.fireLoss < 15) ? 'notgood' : (data.occupant.fireLoss < 40) ? 'average' : 'bad', data.occupant.fireLoss)}} | -{{:helper.displayBar(data.occupant.paralysis, 0, 100, (data.occupant.paralysis < 25) ? 'notgood' : (data.occupant.paralysis < 50) ? 'average' : 'bad', data.occupant.paralysis)}} | -
| {{:value.name}} |
| Name | -Total damage | -Brute damage | -Burn damage | -Injuries | -
|---|---|---|---|---|
| {{:value.name}} | -{{:helper.displayBar(value.totalLoss, 0, value.maxHealth, (value.totalLoss < value.bruised) ? 'notgood' : (value.totalLoss < value.broken) ? 'average' : 'bad', value.totalLoss) }} | -{{if value.bruteLoss> 0}} {{else}} {{/if}} {{:helper.smoothRound(value.bruteLoss)}} | -{{if value.fireLoss> 0}} {{else}} {{/if}} {{:helper.smoothRound(value.fireLoss)}} | -
-
- {{if value.internalBleeding}} internal bleeding {{/if}} - {{if value.lungRuptured}} lung ruptured {{/if}} - {{if value.status.broken}} {{:value.status.broken}} {{/if}} - {{if value.germ_level > 100}} - {{if value.germ_level < 300}} - mild infection - {{else value.germ_level < 400}} - mild infection+ - {{else value.germ_level < 500}} - mild infection++ - {{else value.germ_level < 700}} - acute infection - {{else value.germ_level < 800}} - acute infection+ - {{else value.germ_level < 900}} - acute infection++ - {{else value.germ_level >= 900}} - septic - {{/if}} - {{/if}} - {{if value.open}} open incision {{/if}} - - {{if value.status.splinted}} splinted {{/if}} - {{if value.status.robotic}} robotic {{/if}} - {{if value.status.dead}} DEAD - {{/for}} - {{/if}} - |
-
| Name | -Brute damage | -Injuries | -
|---|---|---|
| {{:value.name}} |
- {{:helper.displayBar(value.damage, 0, value.maxHealth, (value.damage < value.bruised) ? 'notgood' : (value.damage < value.broken) ? 'average' : 'bad', value.damage) }} | -
-
- {{if value.germ_level > 100}}
- {{if value.germ_level < 300}}
- mild infection - {{else value.germ_level < 400}} - mild infection+ - {{else value.germ_level < 500}} - mild infection++ - {{else value.germ_level < 700}} - acute Infection - {{else value.germ_level < 800}} - acute Infection+ - {{else value.germ_level < 900}} - acute Infection++ - {{else value.germ_level >= 900}} - septic - {{/if}} - {{/if}} - - {{if value.robotic == 1}} robotic {{/if}} - {{if value.robotic == 2}} assisted {{/if}} - {{if value.dead}} DEAD {{/if}} - |
-
| - {{:helper.link('Create pill (100u max)', 'arrow-right', {'createpill': 1})}} - | -- {{:helper.link('Multiple', 'arrow-right', {'createpill_multiple': 1})}} - | -- {{:helper.link('Style', 'pencil', {'change_pill': 1})}} - | -
- |
-
| - {{:helper.link('Create patch (30u max)', 'arrow-right', {'createpatch': 1})}} - | -- {{:helper.link('Multiple', 'arrow-right', {'createpatch_multiple': 1})}} - | -||
| - {{:helper.link('Create bottle (50u max)', 'arrow-right', {'createbottle': 1})}} - | -- {{:helper.link('Style', 'pencil', {'change_bottle': 1})}} - | -
- |
-
| - {{:helper.link('Pill Bottle (' + data.loaded_pill_bottle_contents_len + '/' + data.loaded_pill_bottle_storage_slots + ')', 'eject', {'ejectp': 1})}} - | -- {{:helper.link('Change Wrapper', 'pencil', {'change_pillbottle': 1})}} - | -
| - {{:helper.link('No Pill Bottle', 'eject', {}, 'disabled')}} - | -
|
- {{for data.general.fields}}
-
-
- {{/for}}
- {{:value.field}}
- {{:helper.link(value.value, value.edit ? 'pencil' : 'user-times', {'field' : value.edit}, value.edit ? null : 'disabled')}}
- |
-
- {{if data.general.has_photos}}
- {{for data.general.photos}}
- {{if value.photo}}
- |
-