Research & Development Console Restructure (#25653)

* RnD console

* Undefine local defines

* [ci skip]

* Build and update /tg/ui

* Reformat /tg/ui

* Apply suggestions from code review

Co-authored-by: Ryan <80364400+Sirryan2002@users.noreply.github.com>
Signed-off-by: Arthri <41360489+Arthri@users.noreply.github.com>

* Snake casing

[ci skip]

* If statement over ternary

* Document menu variables

* Replace user with ui.user

* Add documentation to copied variables

[ci skip]

* Rename icon to ui_icon

* Factor out wait message box

* Reorganize settings menu

* Refactor technology row

* [ci skip]

* Build and update /tg/ui

* Fix errors

* [ci skip]

* Build and update /tg/ui

---------

Signed-off-by: Arthri <41360489+Arthri@users.noreply.github.com>
Co-authored-by: Arthri <41360489+a@users.noreply.github.com>
Co-authored-by: /tg/ui Builder <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Ryan <80364400+Sirryan2002@users.noreply.github.com>
Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
This commit is contained in:
Arthri
2024-07-30 14:27:53 +00:00
committed by GitHub
co-authored by Ryan Arthri /tg/ui Builder <41898282+github-actions[bot]@users.noreply.github.com> Burzah
parent efb735af1e
commit a96e634a8e
28 changed files with 793 additions and 830 deletions
@@ -90,6 +90,7 @@ Note: Must be placed within 3 tiles of the R&D Console
loaded_item = O
O.loc = src
to_chat(user, "<span class='notice'>You add [O] to [src]!</span>")
SStgui.update_uis(linked_console)
flick("d_analyzer_la", src)
spawn(10)
icon_state = "d_analyzer_l"
+209 -189
View File
@@ -41,21 +41,20 @@ won't update every console in existence) but it's more of a hassle to do. Also,
#define RESET_RESEARCH_DELAY 20
#define IMPRINTER_DELAY 16
// SUBMENU_MAIN also used by other menus
// MENU_LEVELS is not accessible normally
#define MENU_MAIN 0
#define MENU_LEVELS 1
#define MENU_DISK 2
#define MENU_DESTROY 3
#define MENU_LATHE 4
#define MENU_IMPRINTER 5
#define MENU_SETTINGS 6
#define SUBMENU_MAIN 0
#define SUBMENU_DISK_COPY 1
#define SUBMENU_LATHE_CATEGORY 1
#define SUBMENU_LATHE_MAT_STORAGE 2
#define SUBMENU_LATHE_CHEM_STORAGE 3
#define SUBMENU_SETTINGS_DEVICES 1
#define MIN_MENU MENU_MAIN
#define MAX_MENU MENU_SETTINGS
#define SUBMENU_PRINTER_MAIN 0
#define SUBMENU_PRINTER_SEARCH 1
#define SUBMENU_PRINTER_MATERIALS 2
#define SUBMENU_PRINTER_CHEMICALS 3
#define MIN_SUBMENU_PRINTER SUBMENU_PRINTER_MAIN
#define MAX_SUBMENU_PRINTER SUBMENU_PRINTER_CHEMICALS
#define BUILD_POWER 2000
#define DECONSTRUCT_POWER 250
@@ -74,8 +73,12 @@ won't update every console in existence) but it's more of a hassle to do. Also,
var/obj/machinery/r_n_d/protolathe/linked_lathe = null //Linked Protolathe
var/obj/machinery/r_n_d/circuit_imprinter/linked_imprinter = null //Linked Circuit Imprinter
/// The ID of the top-level menu, such as protolathe, analyzer, etc.
var/menu = MENU_MAIN
var/submenu = SUBMENU_MAIN
/// The ID of the protolathe submenu, such as materials, chemicals, crafting etc.
var/submenu_protolathe = SUBMENU_PRINTER_MAIN
/// The ID of the circuit imprinter submenu. Shares the same submenus as the protolathe.
var/submenu_imprinter = SUBMENU_PRINTER_MAIN
var/wait_message = 0
var/wait_message_timer = 0
@@ -205,18 +208,6 @@ won't update every console in existence) but it's more of a hassle to do. Also,
to_chat(user, "<span class='notice'>You disable the security protocols</span>")
return TRUE
/obj/machinery/computer/rdconsole/proc/valid_nav(next_menu, next_submenu)
switch(next_menu)
if(MENU_MAIN, MENU_LEVELS, MENU_DESTROY)
return next_submenu in list(SUBMENU_MAIN)
if(MENU_DISK)
return next_submenu in list(SUBMENU_MAIN, SUBMENU_DISK_COPY)
if(MENU_LATHE, MENU_IMPRINTER)
return next_submenu in list(SUBMENU_MAIN, SUBMENU_LATHE_CATEGORY, SUBMENU_LATHE_MAT_STORAGE, SUBMENU_LATHE_CHEM_STORAGE)
if(MENU_SETTINGS)
return next_submenu in list(SUBMENU_MAIN, SUBMENU_SETTINGS_DEVICES)
return FALSE
/obj/machinery/computer/rdconsole/proc/prompt_eject_sheets(obj/machinery/r_n_d/machine, material_id, amount)
if(!machine)
return
@@ -241,8 +232,10 @@ won't update every console in existence) but it's more of a hassle to do. Also,
clear_wait_message()
if(d_disk && d_disk.blueprint)
files.AddDesign2Known(d_disk.blueprint)
else if(t_disk && t_disk.stored)
files.AddTech2Known(t_disk.stored)
else if(t_disk && t_disk.tech_id)
var/datum/tech/tech = files.find_possible_tech_with_id(t_disk.tech_id)
if(!isnull(tech))
tech.level = t_disk.tech_level
SStgui.update_uis(src)
griefProtection() //Update centcom too
@@ -355,7 +348,6 @@ won't update every console in existence) but it's more of a hassle to do. Also,
linked_destroy.busy = FALSE
use_power(DECONSTRUCT_POWER)
menu = MENU_DESTROY
submenu = SUBMENU_MAIN
SStgui.update_uis(src)
@@ -467,31 +459,39 @@ won't update every console in existence) but it's more of a hassle to do. Also,
clear_wait_message()
SStgui.update_uis(src)
/obj/machinery/computer/rdconsole/ui_act(action, list/params)
/obj/machinery/computer/rdconsole/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
if(!allowed(usr) && !isobserver(usr))
if(!allowed(ui.user) && !isobserver(ui.user))
return
add_fingerprint(usr)
add_fingerprint(ui.user)
switch(action)
if("nav") //Switches menu screens. Converts a sent text string into a number. Saves a LOT of code.
var/next_menu = text2num(params["menu"])
var/next_submenu = text2num(params["submenu"])
if(valid_nav(next_menu, next_submenu))
menu = next_menu
submenu = next_submenu
if(isnull(next_menu) || !ISINTEGER(next_menu) || !ISINRANGE(next_menu, MIN_MENU, MAX_MENU))
return
menu = next_menu
if("nav_protolathe")
var/new_menu = text2num(params["menu"])
if(isnull(new_menu) || !ISINTEGER(new_menu) || !ISINRANGE(new_menu, MIN_SUBMENU_PRINTER, MAX_SUBMENU_PRINTER))
return
submenu_protolathe = new_menu
if("nav_imprinter")
var/new_menu = text2num(params["menu"])
if(isnull(new_menu) || !ISINTEGER(new_menu) || !ISINRANGE(new_menu, MIN_SUBMENU_PRINTER, MAX_SUBMENU_PRINTER))
return
submenu_imprinter = new_menu
if("setCategory")
var/next_category = params["category"]
var/compare
if(submenu != SUBMENU_MAIN)
return FALSE
if(menu == MENU_LATHE)
compare = PROTOLATHE
if(!linked_lathe || !(next_category in linked_lathe.categories))
@@ -511,7 +511,14 @@ won't update every console in existence) but it's more of a hassle to do. Also,
continue
if(next_category in D.category)
matching_designs.Add(D)
submenu = SUBMENU_LATHE_CATEGORY
if(menu == MENU_LATHE)
submenu_protolathe = SUBMENU_PRINTER_SEARCH
if(submenu_imprinter == SUBMENU_PRINTER_SEARCH)
submenu_imprinter = SUBMENU_PRINTER_MAIN
else if(menu == MENU_IMPRINTER)
submenu_imprinter = SUBMENU_PRINTER_SEARCH
if(submenu_protolathe == SUBMENU_PRINTER_SEARCH)
submenu_protolathe = SUBMENU_PRINTER_MAIN
selected_category = "Viewing Category [next_category]"
@@ -519,79 +526,69 @@ won't update every console in existence) but it's more of a hassle to do. Also,
add_wait_message("Updating Database...", TECH_UPDATE_DELAY)
addtimer(CALLBACK(src, PROC_REF(update_from_disk)), TECH_UPDATE_DELAY)
if("clear_tech") //Erase data on the technology disk.
if(t_disk)
t_disk.wipe_tech()
if("eject_tech") //Eject the technology disk.
if("eject_disk")
if(t_disk)
t_disk.forceMove(loc)
if(Adjacent(usr) && !issilicon(usr))
usr.put_in_hands(t_disk)
if(Adjacent(ui.user) && !issilicon(ui.user))
ui.user.put_in_hands(t_disk)
t_disk = null
menu = MENU_MAIN
submenu = SUBMENU_MAIN
if(d_disk)
d_disk.forceMove(loc)
if(Adjacent(ui.user) && !issilicon(ui.user))
ui.user.put_in_hands(d_disk)
d_disk = null
if("erase_disk")
if(t_disk && d_disk)
to_chat(ui.user, "<span class='warning'>Can not simultaneously wipe tech disk and design disk.</span>")
return FALSE
if(t_disk)
t_disk.wipe_tech()
if(d_disk)
d_disk.wipe_blueprint()
if("copy_tech") //Copy some technology data from the research holder to the disk.
// Somehow this href makes me very nervous
var/datum/tech/known = files.known_tech[params["id"]]
if(t_disk && known)
t_disk.load_tech(known)
menu = MENU_DISK
submenu = SUBMENU_MAIN
if("updt_design") //Updates the research holder with design data from the design disk.
add_wait_message("Updating Database...", DESIGN_UPDATE_DELAY)
addtimer(CALLBACK(src, PROC_REF(update_from_disk)), DESIGN_UPDATE_DELAY)
if("clear_design") //Erases data on the design disk.
if(d_disk)
d_disk.wipe_blueprint()
if("eject_design") //Eject the design disk.
if(d_disk)
d_disk.forceMove(loc)
if(Adjacent(usr) && !issilicon(usr))
usr.put_in_hands(d_disk)
d_disk = null
menu = MENU_MAIN
submenu = SUBMENU_MAIN
if("copy_design") //Copy design data from the research holder to the design disk.
// This href ALSO makes me very nervous
var/datum/design/design = files.known_designs[params["id"]]
if(design && d_disk && can_copy_design(design))
d_disk.blueprint = design
menu = MENU_DISK
submenu = SUBMENU_MAIN
if("eject_item") //Eject the item inside the destructive analyzer.
if(linked_destroy)
if(linked_destroy.busy)
to_chat(usr, "<span class='danger'>[linked_destroy] is busy at the moment.</span>")
to_chat(ui.user, "<span class='danger'>[linked_destroy] is busy at the moment.</span>")
else if(linked_destroy.loaded_item)
linked_destroy.loaded_item.forceMove(linked_destroy.loc)
linked_destroy.loaded_item = null
linked_destroy.icon_state = "d_analyzer"
menu = MENU_DESTROY
if("maxresearch")
if(!check_rights(R_ADMIN))
return
if(tgui_alert(usr, "Are you sure you want to maximize research levels?", "Confirmation", list("Yes", "No")) != "Yes")
if(tgui_alert(ui.user, "Are you sure you want to maximize research levels?", "Confirmation", list("Yes", "No")) != "Yes")
return
log_admin("[key_name(usr)] has maximized the research levels.")
message_admins("[key_name_admin(usr)] has maximized the research levels.")
log_admin("[key_name(ui.user)] has maximized the research levels.")
message_admins("[key_name_admin(ui.user)] has maximized the research levels.")
Maximize()
griefProtection() //Update centcomm too
if("deconstruct") //Deconstruct the item in the destructive analyzer and update the research holder.
start_destroyer(usr)
start_destroyer(ui.user)
if("sync") //Sync the research holder with all the R&D consoles in the game that aren't sync protected.
if(!sync)
to_chat(usr, "<span class='danger'>You must connect to the network first!</span>")
to_chat(ui.user, "<span class='danger'>You must connect to the network first!</span>")
else
add_wait_message("Syncing Database...", SYNC_RESEARCH_DELAY)
addtimer(CALLBACK(src, PROC_REF(sync_research)), SYNC_RESEARCH_DELAY)
@@ -641,14 +638,16 @@ won't update every console in existence) but it's more of a hassle to do. Also,
if(linked_lathe)
linked_lathe.linked_console = null
linked_lathe = null
submenu_protolathe = SUBMENU_PRINTER_MAIN
if("imprinter")
if(linked_imprinter)
linked_imprinter.linked_console = null
linked_imprinter = null
submenu_imprinter = SUBMENU_PRINTER_MAIN
if("reset") //Reset the R&D console's database.
griefProtection()
var/choice = tgui_alert(usr, "Are you sure you want to reset the R&D console's database? Data lost cannot be recovered.", "R&D Console Database Reset", list("Continue", "Cancel"))
var/choice = tgui_alert(ui.user, "Are you sure you want to reset the R&D console's database? Data lost cannot be recovered.", "R&D Console Database Reset", list("Continue", "Cancel"))
if(choice == "Continue")
add_wait_message("Resetting Database...", RESET_RESEARCH_DELAY)
addtimer(CALLBACK(src, PROC_REF(reset_research)), RESET_RESEARCH_DELAY)
@@ -673,7 +672,14 @@ won't update every console in existence) but it's more of a hassle to do. Also,
continue
if(findtext(D.name, query))
matching_designs.Add(D)
submenu = SUBMENU_LATHE_CATEGORY
if(menu == MENU_LATHE)
submenu_protolathe = SUBMENU_PRINTER_SEARCH
if(submenu_imprinter == SUBMENU_PRINTER_SEARCH)
submenu_imprinter = SUBMENU_PRINTER_MAIN
else if(menu == MENU_IMPRINTER)
submenu_imprinter = SUBMENU_PRINTER_SEARCH
if(submenu_protolathe == SUBMENU_PRINTER_SEARCH)
submenu_protolathe = SUBMENU_PRINTER_MAIN
selected_category = "Search Results for '[query]'"
@@ -722,56 +728,58 @@ won't update every console in existence) but it's more of a hassle to do. Also,
var/coeff = machine.efficiency_coeff
if(submenu == SUBMENU_LATHE_CATEGORY)
for(var/datum/design/D in matching_designs)
var/list/design_list = list()
designs_list[++designs_list.len] = design_list
var/list/design_materials_list = list()
design_list["materials"] = design_materials_list
design_list["id"] = D.id
design_list["name"] = D.name
var/can_build = is_imprinter ? 1 : 50
if(menu == MENU_LATHE || menu == MENU_IMPRINTER)
var/submenu = menu == MENU_LATHE ? submenu_protolathe : submenu_imprinter
if(submenu == SUBMENU_PRINTER_SEARCH)
for(var/datum/design/D in matching_designs)
var/list/design_list = list()
designs_list[++designs_list.len] = design_list
var/list/design_materials_list = list()
design_list["materials"] = design_materials_list
design_list["id"] = D.id
design_list["name"] = D.name
var/can_build = is_imprinter ? 1 : 50
for(var/M in D.materials)
var/list/material_list = list()
design_materials_list[++design_materials_list.len] = material_list
material_list["name"] = CallMaterialName(M)
material_list["amount"] = D.materials[M] * coeff
var/t = machine.check_mat(D, M)
material_list["is_red"] = t < 1
can_build = min(can_build, t)
for(var/M in D.materials)
var/list/material_list = list()
design_materials_list[++design_materials_list.len] = material_list
material_list["name"] = CallMaterialName(M)
material_list["amount"] = D.materials[M] * coeff
var/t = machine.check_mat(D, M)
material_list["is_red"] = t < 1
can_build = min(can_build, t)
for(var/R in D.reagents_list)
var/list/material_list = list()
design_materials_list[++design_materials_list.len] = material_list
material_list["name"] = CallMaterialName(R)
material_list["amount"] = D.reagents_list[R] * coeff
var/t = machine.check_mat(D, R)
material_list["is_red"] = t < 1
can_build = min(can_build, t)
for(var/R in D.reagents_list)
var/list/material_list = list()
design_materials_list[++design_materials_list.len] = material_list
material_list["name"] = CallMaterialName(R)
material_list["amount"] = D.reagents_list[R] * coeff
var/t = machine.check_mat(D, R)
material_list["is_red"] = t < 1
can_build = min(can_build, t)
design_list["can_build"] = can_build
design_list["can_build"] = can_build
else if(submenu == SUBMENU_LATHE_MAT_STORAGE)
materials_list[++materials_list.len] = list("name" = "Metal", "id" = MAT_METAL, "amount" = machine.materials.amount(MAT_METAL))
materials_list[++materials_list.len] = list("name" = "Glass", "id" = MAT_GLASS, "amount" = machine.materials.amount(MAT_GLASS))
materials_list[++materials_list.len] = list("name" = "Gold", "id" = MAT_GOLD, "amount" = machine.materials.amount(MAT_GOLD))
materials_list[++materials_list.len] = list("name" = "Silver", "id" = MAT_SILVER, "amount" = machine.materials.amount(MAT_SILVER))
materials_list[++materials_list.len] = list("name" = "Solid Plasma", "id" = MAT_PLASMA, "amount" = machine.materials.amount(MAT_PLASMA))
materials_list[++materials_list.len] = list("name" = "Uranium", "id" = MAT_URANIUM, "amount" = machine.materials.amount(MAT_URANIUM))
materials_list[++materials_list.len] = list("name" = "Diamond", "id" = MAT_DIAMOND, "amount" = machine.materials.amount(MAT_DIAMOND))
materials_list[++materials_list.len] = list("name" = "Bananium", "id" = MAT_BANANIUM, "amount" = machine.materials.amount(MAT_BANANIUM))
materials_list[++materials_list.len] = list("name" = "Tranquillite", "id" = MAT_TRANQUILLITE, "amount" = machine.materials.amount(MAT_TRANQUILLITE))
materials_list[++materials_list.len] = list("name" = "Titanium", "id" = MAT_TITANIUM, "amount" = machine.materials.amount(MAT_TITANIUM))
materials_list[++materials_list.len] = list("name" = "Plastic", "id" = MAT_PLASTIC, "amount" = machine.materials.amount(MAT_PLASTIC))
materials_list[++materials_list.len] = list("name" = "Bluespace Mesh", "id" = MAT_BLUESPACE, "amount" = machine.materials.amount(MAT_BLUESPACE))
else if(submenu == SUBMENU_LATHE_CHEM_STORAGE)
for(var/datum/reagent/R in machine.reagents.reagent_list)
var/list/loaded_chemical = list()
loaded_chemicals[++loaded_chemicals.len] = loaded_chemical
loaded_chemical["name"] = R.name
loaded_chemical["volume"] = R.volume
loaded_chemical["id"] = R.id
else if(submenu == SUBMENU_PRINTER_MATERIALS)
materials_list[++materials_list.len] = list("name" = "Metal", "id" = MAT_METAL, "amount" = machine.materials.amount(MAT_METAL))
materials_list[++materials_list.len] = list("name" = "Glass", "id" = MAT_GLASS, "amount" = machine.materials.amount(MAT_GLASS))
materials_list[++materials_list.len] = list("name" = "Gold", "id" = MAT_GOLD, "amount" = machine.materials.amount(MAT_GOLD))
materials_list[++materials_list.len] = list("name" = "Silver", "id" = MAT_SILVER, "amount" = machine.materials.amount(MAT_SILVER))
materials_list[++materials_list.len] = list("name" = "Solid Plasma", "id" = MAT_PLASMA, "amount" = machine.materials.amount(MAT_PLASMA))
materials_list[++materials_list.len] = list("name" = "Uranium", "id" = MAT_URANIUM, "amount" = machine.materials.amount(MAT_URANIUM))
materials_list[++materials_list.len] = list("name" = "Diamond", "id" = MAT_DIAMOND, "amount" = machine.materials.amount(MAT_DIAMOND))
materials_list[++materials_list.len] = list("name" = "Bananium", "id" = MAT_BANANIUM, "amount" = machine.materials.amount(MAT_BANANIUM))
materials_list[++materials_list.len] = list("name" = "Tranquillite", "id" = MAT_TRANQUILLITE, "amount" = machine.materials.amount(MAT_TRANQUILLITE))
materials_list[++materials_list.len] = list("name" = "Titanium", "id" = MAT_TITANIUM, "amount" = machine.materials.amount(MAT_TITANIUM))
materials_list[++materials_list.len] = list("name" = "Plastic", "id" = MAT_PLASTIC, "amount" = machine.materials.amount(MAT_PLASTIC))
materials_list[++materials_list.len] = list("name" = "Bluespace Mesh", "id" = MAT_BLUESPACE, "amount" = machine.materials.amount(MAT_BLUESPACE))
else if(submenu == SUBMENU_PRINTER_CHEMICALS)
for(var/datum/reagent/R in machine.reagents.reagent_list)
var/list/loaded_chemical = list()
loaded_chemicals[++loaded_chemicals.len] = loaded_chemical
loaded_chemical["name"] = R.name
loaded_chemical["volume"] = R.volume
loaded_chemical["id"] = R.id
/obj/machinery/computer/rdconsole/proc/can_copy_design(datum/design/D)
@@ -793,7 +801,8 @@ won't update every console in existence) but it's more of a hassle to do. Also,
files.RefreshResearch()
data["menu"] = menu
data["submenu"] = submenu
data["submenu_protolathe"] = submenu_protolathe
data["submenu_imprinter"] = submenu_imprinter
data["wait_message"] = wait_message
data["src_ref"] = UID()
@@ -807,7 +816,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
data["loaded_item"] = null
data["category"] = selected_category
if(menu == MENU_MAIN || menu == MENU_LEVELS)
if(menu == MENU_MAIN)
var/list/tech_levels = list()
data["tech_levels"] = tech_levels
for(var/v in files.known_tech)
@@ -815,83 +824,93 @@ won't update every console in existence) but it's more of a hassle to do. Also,
if(T.level <= 0)
continue
var/list/this_tech_list = list()
this_tech_list["id"] = T.id
this_tech_list["name"] = T.name
this_tech_list["level"] = T.level
this_tech_list["desc"] = T.desc
this_tech_list["ui_icon"] = T.ui_icon
tech_levels[++tech_levels.len] = this_tech_list
else if(menu == MENU_DISK)
if(t_disk != null && t_disk.stored != null && submenu == SUBMENU_MAIN)
var/list/disk_data = list()
data["disk_data"] = disk_data
disk_data["name"] = t_disk.stored.name
disk_data["level"] = t_disk.stored.level
disk_data["desc"] = t_disk.stored.desc
if(t_disk != null)
if(t_disk.tech_id == null)
var/list/to_copy = list()
data["to_copy"] = to_copy
for(var/v in files.known_tech)
var/datum/tech/T = files.known_tech[v]
if(T.level <= 0)
continue
var/list/item = list()
to_copy[++to_copy.len] = item
item["name"] = T.name
item["id"] = T.id
else
var/datum/tech/stored_tech = files.find_possible_tech_with_id(t_disk.tech_id)
var/list/disk_data = list()
data["disk_data"] = disk_data
if(isnull(stored_tech))
disk_data["name"] = "Unknown"
disk_data["level"] = 0
disk_data["desc"] = "Unrecognized technology detected in disk."
else
disk_data["name"] = stored_tech.name
disk_data["level"] = stored_tech.level
disk_data["desc"] = stored_tech.desc
else if(t_disk != null && submenu == SUBMENU_DISK_COPY)
var/list/to_copy = list()
data["to_copy"] = to_copy
for(var/v in files.known_tech)
var/datum/tech/T = files.known_tech[v]
if(T.level <= 0)
continue
var/list/item = list()
to_copy[++to_copy.len] = item
item["name"] = T.name
item["id"] = T.id
else if(d_disk != null && d_disk.blueprint != null && submenu == SUBMENU_MAIN)
var/list/disk_data = list()
data["disk_data"] = disk_data
disk_data["name"] = d_disk.blueprint.name
var/b_type = d_disk.blueprint.build_type
var/list/lathe_types = list()
disk_data["lathe_types"] = lathe_types
if(b_type)
if(b_type & IMPRINTER) lathe_types += "Circuit Imprinter"
if(b_type & PROTOLATHE) lathe_types += "Protolathe"
if(b_type & AUTOLATHE) lathe_types += "Autolathe"
if(b_type & MECHFAB) lathe_types += "Mech Fabricator"
if(b_type & BIOGENERATOR) lathe_types += "Biogenerator"
if(b_type & SMELTER) lathe_types += "Smelter"
var/list/materials = list()
disk_data["materials"] = materials
for(var/M in d_disk.blueprint.materials)
var/list/material = list()
materials[++materials.len] = material
material["name"] = CallMaterialName(M)
material["amount"] = d_disk.blueprint.materials[M]
else if(d_disk != null && submenu == SUBMENU_DISK_COPY)
var/list/to_copy = list()
data["to_copy"] = to_copy
for(var/v in files.known_designs)
var/datum/design/D = files.known_designs[v]
if(!can_copy_design(D))
continue
var/list/item = list()
to_copy[++to_copy.len] = item
item["name"] = D.name
item["id"] = D.id
else if(d_disk != null)
if(d_disk.blueprint == null)
var/list/to_copy = list()
data["to_copy"] = to_copy
for(var/v in files.known_designs)
var/datum/design/D = files.known_designs[v]
if(!can_copy_design(D))
continue
var/list/item = list()
to_copy[++to_copy.len] = item
item["name"] = D.name
item["id"] = D.id
else
var/list/disk_data = list()
data["disk_data"] = disk_data
disk_data["name"] = d_disk.blueprint.name
var/b_type = d_disk.blueprint.build_type
var/list/lathe_types = list()
disk_data["lathe_types"] = lathe_types
if(b_type)
if(b_type & IMPRINTER) lathe_types += "Circuit Imprinter"
if(b_type & PROTOLATHE) lathe_types += "Protolathe"
if(b_type & AUTOLATHE) lathe_types += "Autolathe"
if(b_type & MECHFAB) lathe_types += "Mech Fabricator"
if(b_type & BIOGENERATOR) lathe_types += "Biogenerator"
if(b_type & SMELTER) lathe_types += "Smelter"
var/list/materials = list()
disk_data["materials"] = materials
for(var/M in d_disk.blueprint.materials)
var/list/material = list()
materials[++materials.len] = material
material["name"] = CallMaterialName(M)
material["amount"] = d_disk.blueprint.materials[M]
else if(menu == MENU_DESTROY && linked_destroy && linked_destroy.loaded_item)
var/list/loaded_item_list = list()
data["loaded_item"] = loaded_item_list
loaded_item_list["name"] = linked_destroy.loaded_item.name
var/list/temp_tech = linked_destroy.ConvertReqString2List(linked_destroy.loaded_item.origin_tech)
var/list/tech_list = list()
loaded_item_list["origin_tech"] = tech_list
for(var/T in temp_tech)
var/list/tech_item = list()
tech_list[++tech_list.len] = tech_item
tech_item["name"] = CallTechName(T)
tech_item["object_level"] = temp_tech[T]
for(var/v in files.known_tech)
var/datum/tech/F = files.known_tech[v]
if(F.name == CallTechName(T))
tech_item["current_level"] = F.level
break
var/list/tech_levels = list()
data["tech_levels"] = tech_levels
for(var/v in files.known_tech)
var/datum/tech/T = files.known_tech[v]
if(T.level <= 0)
continue
var/list/this_tech_list = list()
this_tech_list["id"] = T.id
this_tech_list["name"] = T.name
this_tech_list["level"] = T.level
this_tech_list["desc"] = T.desc
this_tech_list["ui_icon"] = T.ui_icon
this_tech_list["object_level"] = temp_tech[T.id]
tech_levels[++tech_levels.len] = this_tech_list
else if(menu == MENU_LATHE && linked_lathe)
ui_machine_data(linked_lathe, data)
@@ -956,17 +975,18 @@ won't update every console in existence) but it's more of a hassle to do. Also,
#undef RESET_RESEARCH_DELAY
#undef IMPRINTER_DELAY
#undef MENU_MAIN
#undef MENU_LEVELS
#undef MENU_DISK
#undef MENU_DESTROY
#undef MENU_LATHE
#undef MENU_IMPRINTER
#undef MENU_SETTINGS
#undef SUBMENU_MAIN
#undef SUBMENU_DISK_COPY
#undef SUBMENU_LATHE_CATEGORY
#undef SUBMENU_LATHE_MAT_STORAGE
#undef SUBMENU_LATHE_CHEM_STORAGE
#undef SUBMENU_SETTINGS_DEVICES
#undef MIN_MENU
#undef MAX_MENU
#undef SUBMENU_PRINTER_MAIN
#undef SUBMENU_PRINTER_SEARCH
#undef SUBMENU_PRINTER_MATERIALS
#undef SUBMENU_PRINTER_CHEMICALS
#undef MIN_SUBMENU_PRINTER
#undef MAX_SUBMENU_PRINTER
#undef BUILD_POWER
#undef DECONSTRUCT_POWER
+35 -19
View File
@@ -110,6 +110,11 @@ research holder datum.
return
known_tech[T.id] = T
/datum/research/proc/find_possible_tech_with_id(id)
for(var/datum/tech/T in possible_tech)
if(T.id == id)
return T
/datum/research/proc/CanAddDesign2Known(datum/design/D)
if(D.id in known_designs)
return FALSE
@@ -258,6 +263,8 @@ research holder datum.
var/level = 1 //A simple number scale of the research level. Level 0 = Secret tech.
var/max_level = 1 // Maximum level this can be at (for job objectives)
var/rare = 1 //How much CentCom wants to get that tech. Used in supply shuttle tech cost calculation.
/// Name of the FontAwesome icon to represent the tech
var/ui_icon = null
var/list/req_tech = list() //List of ids associated values of techs required to research this tech. "id" = #
@@ -268,12 +275,14 @@ research holder datum.
desc = "Development of new and improved materials."
id = "materials"
max_level = 7
ui_icon = "layer-group"
/datum/tech/engineering
name = "Engineering Research"
desc = "Development of new and improved engineering parts and methods."
id = "engineering"
max_level = 7
ui_icon = "tools"
/datum/tech/plasmatech
name = "Plasma Research"
@@ -281,12 +290,14 @@ research holder datum.
id = "plasmatech"
max_level = 7
rare = 3
ui_icon = "fire"
/datum/tech/powerstorage
name = "Power Manipulation Technology"
desc = "The various technologies behind the storage and generation of electicity."
id = "powerstorage"
max_level = 7
ui_icon = "bolt"
/datum/tech/bluespace
name = "'Bluespace' Research"
@@ -294,30 +305,35 @@ research holder datum.
id = "bluespace"
max_level = 7
rare = 2
ui_icon = "gem"
/datum/tech/biotech
name = "Biological Technology"
desc = "Research into the deeper mysteries of life and organic substances."
id = "biotech"
max_level = 7
ui_icon = "seedling"
/datum/tech/combat
name = "Combat Systems Research"
desc = "The development of offensive and defensive systems."
id = "combat"
max_level = 7
ui_icon = "shield-alt"
/datum/tech/magnets
name = "Electromagnetic Spectrum Research"
desc = "Research into the electromagnetic spectrum. No clue how they actually work, though."
id = "magnets"
max_level = 7
ui_icon = "magnet"
/datum/tech/programming
name = "Data Theory Research"
desc = "The development of new computer and artificial intelligence and data storage systems."
id = "programming"
max_level = 7
ui_icon = "server"
/// not meant to be raised by deconstruction, do not give objects toxins as an origin_tech
/datum/tech/toxins
@@ -326,6 +342,7 @@ research holder datum.
id = "toxins"
max_level = 7
rare = 2
ui_icon = "explosion"
/datum/tech/syndicate
name = "Illegal Technologies Research"
@@ -333,6 +350,7 @@ research holder datum.
id = "syndicate"
max_level = 0 // Don't count towards maxed research, since it's illegal.
rare = 4
ui_icon = "user-astronaut"
/datum/tech/abductor
name = "Alien Technologies Research"
@@ -340,6 +358,7 @@ research holder datum.
id = "abductor"
rare = 5
level = 0
ui_icon = "satellite"
/*
datum/tech/arcane
@@ -368,28 +387,19 @@ datum/tech/robotics
req_tech = list("materials" = 3, "programming" = 3)
*/
/datum/tech/proc/getCost(current_level = null)
// Calculates tech disk's supply points sell cost
if(!current_level)
current_level = initial(level)
if(current_level >= level)
return 0
var/cost = 0
for(var/i = current_level + 1, i <= level, i++)
if(i == initial(level))
continue
cost += i*5*rare
return cost
/obj/item/disk/tech_disk
name = "\improper Technology Disk"
desc = "A disk for storing technology data for further research."
icon_state = "datadisk2"
materials = list(MAT_METAL=30, MAT_GLASS=10)
var/datum/tech/stored
var/tech_id = null
var/tech_name = null
// These variables are copied from /datum/tech. They must be copied and cached
// to prevent retroactively updating all disks when a new research level is unlocked
/// The level of the copied technology. Please see /datum/tech.level
var/tech_level = 0
/// The rarity of the copied technology. Affects sell price. Please see /datum/tech.rare
var/tech_rarity = 0
var/default_name = "\improper Technology Disk"
var/default_desc = "A disk for storing technology data for further research."
@@ -398,12 +408,18 @@ datum/tech/robotics
desc = T.desc + "\n <span class='notice'>Level: [T.level]</span>"
// NOTE: This is just a reference to the tech on the system it grabbed it from
// This seems highly fragile
stored = T
tech_id = T.id
tech_name = T.name
tech_level = T.level
tech_rarity = T.rare
/obj/item/disk/tech_disk/proc/wipe_tech()
name = default_name
desc = default_desc
stored = null
tech_id = null
tech_name = null
tech_level = 0
tech_rarity = 0
/obj/item/disk/design_disk
name = "\improper Component Design Disk"
+25 -14
View File
@@ -538,16 +538,29 @@
/datum/economy/simple_seller/tech_levels/begin_sell(obj/docking_port/mobile/supply/S)
temp_tech_levels = SSeconomy.tech_levels.Copy()
/datum/economy/simple_seller/tech_levels/proc/get_price(tech_rarity, tech_level, sold_level = null)
// Calculates tech disk's supply points sell cost
if(!sold_level)
sold_level = 1
if(sold_level >= tech_level)
return 0
var/cost = 0
for(var/i in (sold_level + 1) to tech_level)
cost += i * 5 * tech_rarity
return cost
/datum/economy/simple_seller/tech_levels/check_sell(obj/docking_port/mobile/supply/S, atom/movable/AM)
if(istype(AM, /obj/item/disk/tech_disk))
var/obj/item/disk/tech_disk/disk = AM
if(!disk.stored)
if(!disk.tech_id)
return COMSIG_CARGO_SELL_WRONG
var/datum/tech/tech = disk.stored
var/cost = tech.getCost(temp_tech_levels[tech.id])
var/cost = get_price(disk.tech_rarity, disk.tech_level, temp_tech_levels[disk.tech_id])
if(cost)
temp_tech_levels[tech.id] = tech.level
temp_tech_levels[disk.tech_id] = disk.tech_level
return COMSIG_CARGO_SELL_NORMAL
return COMSIG_CARGO_SELL_WRONG
@@ -556,28 +569,27 @@
return
var/obj/item/disk/tech_disk/disk = AM
if(!disk.stored)
if(!disk.tech_id)
return
var/datum/tech/tech = disk.stored
var/cost = tech.getCost(SSeconomy.tech_levels[tech.id])
var/cost = get_price(disk.tech_rarity, disk.tech_level, SSeconomy.tech_levels[disk.tech_id])
if(!cost)
return
SSeconomy.tech_levels[tech.id] = tech.level
SSeconomy.tech_levels[disk.tech_id] = disk.tech_level
SSblackbox.record_feedback("tally", "cargo tech disks sold", 1, "amount")
SSblackbox.record_feedback("tally", "cargo tech disks sold", cost, "credits")
var/datum/economy/line_item/cargo_item = new
cargo_item.account = SSeconomy.cargo_account
cargo_item.credits = cost / 2
cargo_item.reason = "[tech.name] - new data."
cargo_item.reason = "[disk.tech_name] - new data."
manifest.line_items += cargo_item
var/datum/economy/line_item/science_item = new
science_item.account = GLOB.station_money_database.get_account_by_department(DEPARTMENT_SCIENCE)
science_item.credits = cost / 2
science_item.reason = "[tech.name] - new data."
science_item.reason = "[disk.tech_name] - new data."
manifest.line_items += science_item
/datum/economy/simple_seller/tech_levels/sell_wrong(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
@@ -589,16 +601,15 @@
item.credits = 0
var/obj/item/disk/tech_disk/disk = AM
if(!disk.stored)
if(!disk.tech_id)
item.reason = "Blank tech disk."
manifest.line_items += item
SSblackbox.record_feedback("tally", "cargo tech disks sold", 1, "blank")
return
var/datum/tech/tech = disk.stored
var/cost = tech.getCost(SSeconomy.tech_levels[tech.id])
var/cost = get_price(disk.tech_rarity, disk.tech_level, SSeconomy.tech_levels[disk.tech_id])
if(!cost)
item.reason = "[tech.name] - no new data."
item.reason = "[disk.tech_name] - no new data."
manifest.line_items += item
SSblackbox.record_feedback("tally", "cargo tech disks sold", 1, "repeat")
@@ -1,60 +0,0 @@
import { useBackend } from '../backend';
import { Window } from '../layouts';
import { Box, NoticeBox } from '../components';
import {
SettingsMenu,
RndRoute,
DeconstructionMenu,
MainMenu,
RndNavbar,
CurrentLevels,
DataDiskMenu,
LatheMenu,
} from './RndConsoleComponents';
export const MENU = {
MAIN: 0,
LEVELS: 1,
DISK: 2,
DESTROY: 3,
LATHE: 4,
IMPRINTER: 5,
SETTINGS: 6,
};
export const SUBMENU = {
MAIN: 0,
DISK_COPY: 1,
LATHE_CATEGORY: 1,
LATHE_MAT_STORAGE: 2,
LATHE_CHEM_STORAGE: 3,
SETTINGS_DEVICES: 1,
};
export const RndConsole = (properties, context) => {
const { data } = useBackend(context);
const { wait_message } = data;
return (
<Window width={800} height={550}>
<Window.Content>
<Box className="RndConsole">
<RndNavbar />
<RndRoute menu={MENU.MAIN} render={() => <MainMenu />} />
<RndRoute menu={MENU.LEVELS} render={() => <CurrentLevels />} />
<RndRoute menu={MENU.DISK} render={() => <DataDiskMenu />} />
<RndRoute menu={MENU.DESTROY} render={() => <DeconstructionMenu />} />
<RndRoute menu={(n) => n === MENU.LATHE || n === MENU.IMPRINTER} render={() => <LatheMenu />} />
<RndRoute menu={MENU.SETTINGS} render={() => <SettingsMenu />} />
{wait_message ? (
<Box className="RndConsole__Overlay">
<Box className="RndConsole__Overlay__Wrapper">
<NoticeBox color="black">{wait_message}</NoticeBox>
</Box>
</Box>
) : null}
</Box>
</Window.Content>
</Window>
);
};
@@ -1,12 +1,10 @@
import { useBackend } from '../../backend';
import { Button, LabeledList, Section, Box } from '../../components';
import { RndNavButton, RndRoute } from './index';
import { SUBMENU } from '../RndConsole';
const DISK_TYPE_DESIGN = 'design';
const DISK_TYPE_TECH = 'tech';
const TechSummary = (properties, context) => {
const TechSummary = (props, context) => {
const { data, act } = useBackend(context);
const { disk_data } = data;
@@ -23,15 +21,13 @@ const TechSummary = (properties, context) => {
</LabeledList>
<Box mt="10px">
<Button content="Upload to Database" icon="arrow-up" onClick={() => act('updt_tech')} />
<Button content="Clear Disk" icon="trash" onClick={() => act('clear_tech')} />
<EjectDisk />
</Box>
</Box>
);
};
// summarize a design disk contents from d_disk
const LatheSummary = (properties, context) => {
const LatheSummary = (props, context) => {
const { data, act } = useBackend(context);
const { disk_data } = data;
if (!disk_data) {
@@ -63,79 +59,40 @@ const LatheSummary = (properties, context) => {
<Box mt="10px">
<Button content="Upload to Database" icon="arrow-up" onClick={() => act('updt_design')} />
<Button content="Clear Disk" icon="trash" onClick={() => act('clear_design')} />
<EjectDisk />
</Box>
</Box>
);
};
const EmptyDisk = (properties, context) => {
const { data } = useBackend(context);
const { disk_type } = data;
const DiskSection = (props, context) => {
const { act, data } = useBackend(context);
const { disk_data } = data;
return (
<Box>
<Box>This disk is empty.</Box>
<Box mt="10px">
<RndNavButton
submenu={SUBMENU.DISK_COPY}
icon="arrow-down"
content={disk_type === DISK_TYPE_TECH ? 'Load Tech to Disk' : 'Load Design to Disk'}
/>
<EjectDisk />
</Box>
</Box>
);
};
const EjectDisk = (properties, context) => {
const { data, act } = useBackend(context);
const { disk_type } = data;
if (!disk_type) {
return null;
}
return (
<Button
content="Eject Disk"
icon="eject"
onClick={() => {
const action = disk_type === DISK_TYPE_TECH ? 'eject_tech' : 'eject_design';
act(action);
}}
<Section
buttons={
<>
<Button.Confirm content="Erase" icon="eraser" disabled={!disk_data} onClick={() => act('erase_disk')} />
<Button
content="Eject"
icon="eject"
onClick={() => {
act('eject_disk');
}}
/>
</>
}
{...props}
/>
);
};
const ContentsSubmenu = (properties, context) => {
const {
data: { disk_data, disk_type },
} = useBackend(context);
const body = () => {
if (!disk_data) {
return <EmptyDisk />;
}
switch (disk_type) {
case DISK_TYPE_DESIGN:
return <LatheSummary />;
case DISK_TYPE_TECH:
return <TechSummary />;
default:
return null;
}
};
return <Section title="Data Disk Contents">{body()}</Section>;
};
const CopySubmenu = (properties, context) => {
const CopySubmenu = (props, context) => {
const { data, act } = useBackend(context);
const { disk_type, to_copy } = data;
const { title } = props;
return (
<Section>
<DiskSection title={title}>
<Box overflowY="auto" overflowX="hidden" maxHeight="450px">
<LabeledList>
{to_copy
@@ -157,22 +114,38 @@ const CopySubmenu = (properties, context) => {
))}
</LabeledList>
</Box>
</Section>
</DiskSection>
);
};
export const DataDiskMenu = (properties, context) => {
export const DataDiskMenu = (props, context) => {
const { data } = useBackend(context);
const { disk_type } = data;
const { disk_type, disk_data } = data;
if (!disk_type) {
return null; // can't access menu without a disk
return <Section title="Data Disk">No disk loaded.</Section>;
}
return (
<>
<RndRoute submenu={SUBMENU.MAIN} render={() => <ContentsSubmenu />} />
<RndRoute submenu={SUBMENU.DISK_COPY} render={() => <CopySubmenu />} />
</>
);
switch (disk_type) {
case DISK_TYPE_DESIGN:
return disk_data ? (
<DiskSection title="Design Disk">
<LatheSummary />
</DiskSection>
) : (
<CopySubmenu title="Design Disk" />
);
case DISK_TYPE_TECH:
if (disk_data) {
return (
<DiskSection title="Technology Disk">
<TechSummary />
</DiskSection>
);
} else {
return <CopySubmenu title="Technology Disk" />;
}
default:
return <>UNRECOGNIZED DISK TYPE</>;
}
};
@@ -0,0 +1,86 @@
import { classes } from 'common/react';
import { useBackend } from '../../backend';
import { Button, Icon, LabeledList, Section, Table } from '../../components';
export const DeconstructionMenu = (props, context) => {
const { data, act } = useBackend(context);
const { tech_levels, loaded_item, linked_destroy } = data;
if (!linked_destroy) {
return <Section title="Deconstruction Menu">NO DESTRUCTIVE ANALYZER LINKED TO CONSOLE</Section>;
}
if (!loaded_item) {
return <Section title="Deconstruction Menu">No item loaded. Standing by...</Section>;
}
return (
<>
<Section
title="Object Analysis"
buttons={
<>
<Button
content="Deconstruct"
icon="microscope"
onClick={() => {
act('deconstruct');
}}
/>
<Button
content="Eject"
icon="eject"
onClick={() => {
act('eject_item');
}}
/>
</>
}
>
<LabeledList>
<LabeledList.Item label="Name">{loaded_item.name}</LabeledList.Item>
</LabeledList>
</Section>
<Section>
<Table id="research-levels">
<Table.Row>
<Table.Cell />
<Table.Cell header>Research Field</Table.Cell>
<Table.Cell header>Current Level</Table.Cell>
<Table.Cell header>Object Level</Table.Cell>
<Table.Cell header>New Level</Table.Cell>
</Table.Row>
{tech_levels.map((techLevel) => (
<TechnologyRow key={techLevel.id} techLevel={techLevel} />
))}
</Table>
</Section>
</>
);
};
const TechnologyRow = (props, context) => {
const {
techLevel: { name, desc, level, object_level, ui_icon },
} = props;
const objectLevelDefined = object_level !== undefined && object_level !== null;
const newLevel = objectLevelDefined ? (object_level >= level ? Math.max(object_level, level + 1) : level) : level;
return (
<Table.Row>
<Table.Cell>
<Button icon="circle-info" tooltip={desc} />
</Table.Cell>
<Table.Cell>
<Icon name={ui_icon} /> {name}
</Table.Cell>
<Table.Cell>{level}</Table.Cell>
{objectLevelDefined ? (
<Table.Cell>{object_level}</Table.Cell>
) : (
<Table.Cell className="research-level-no-effect">-</Table.Cell>
)}
<Table.Cell className={classes([newLevel !== level && 'upgraded-level'])}>{newLevel}</Table.Cell>
</Table.Row>
);
};
@@ -1,6 +1,6 @@
import { useBackend } from '../../backend';
import { Button, Section, Table } from '../../components';
import { LatheMaterials } from './index';
import { LatheMaterials } from './LatheMaterials';
// Also handles search results
export const LatheCategory = (properties, context) => {
@@ -1,6 +1,7 @@
import { useBackend } from '../../backend';
import { Button, Divider, Flex, Section } from '../../components';
import { LatheMaterials, LatheSearch } from './index';
import { LatheMaterials } from './LatheMaterials';
import { LatheSearch } from './LatheSearch';
export const LatheMainMenu = (properties, context) => {
const { data, act } = useBackend(context);
@@ -0,0 +1,61 @@
import { useBackend } from '../../backend';
import { Box, Tabs } from '../../components';
import { MENU, PRINTER_MENU } from '.';
import { LatheMainMenu } from './LatheMainMenu';
import { LatheCategory } from './LatheCategory';
import { LatheMaterialStorage } from './LatheMaterialStorage';
import { LatheChemicalStorage } from './LatheChemicalStorage';
const Tab = Tabs.Tab;
const PrinterTab = (props, context) => {
const { act, data } = useBackend(context);
const [act_id, currentMenu] =
data.menu === MENU.LATHE ? ['nav_protolathe', data.submenu_protolathe] : ['nav_imprinter', data.submenu_imprinter];
const { menu, ...rest } = props;
return <Tab selected={currentMenu === menu} onClick={() => act(act_id, { menu })} {...rest} />;
};
const decideTab = (tab) => {
switch (tab) {
case PRINTER_MENU.MAIN:
return <LatheMainMenu />;
case PRINTER_MENU.SEARCH:
return <LatheCategory />;
case PRINTER_MENU.MATERIALS:
return <LatheMaterialStorage />;
case PRINTER_MENU.CHEMICALS:
return <LatheChemicalStorage />;
}
};
export const LatheMenu = (properties, context) => {
const { data } = useBackend(context);
const { menu, linked_lathe, linked_imprinter } = data;
if (menu === MENU.LATHE && !linked_lathe) {
return <Box>NO PROTOLATHE LINKED TO CONSOLE</Box>;
}
if (menu === MENU.IMPRINTER && !linked_imprinter) {
return <Box>NO CIRCUIT IMPRITER LINKED TO CONSOLE</Box>;
}
return (
<Box>
<Tabs>
<PrinterTab menu={PRINTER_MENU.MAIN} icon="bars">
Main Menu
</PrinterTab>
<PrinterTab menu={PRINTER_MENU.MATERIALS} icon="layer-group">
Materials
</PrinterTab>
<PrinterTab menu={PRINTER_MENU.CHEMICALS} icon="flask-vial">
Chemicals
</PrinterTab>
</Tabs>
{decideTab(data.menu === MENU.LATHE ? data.submenu_protolathe : data.submenu_imprinter)}
</Box>
);
};
@@ -0,0 +1,92 @@
import { useBackend } from '../../backend';
import { Box, Button, Flex, LabeledList, Section } from '../../components';
export const SettingsMenu = (props, context) => (
<Box>
<MainSettings />
<DeviceSettings />
</Box>
);
const MainSettings = (props, context) => {
const { act, data } = useBackend(context);
const { sync, admin } = data;
return (
<Section title="Settings">
<Flex direction="column" align="flex-start">
<Button
content="Sync Database with Network"
icon="sync"
disabled={!sync}
onClick={() => {
act('sync');
}}
/>
<Button
content="Connect to Research Network"
icon="plug"
disabled={sync}
onClick={() => {
act('togglesync');
}}
/>
<Button
disabled={!sync}
icon="unlink"
content="Disconnect from Research Network"
onClick={() => {
act('togglesync');
}}
/>
{admin === 1 ? (
<Button icon="exclamation" content="[ADMIN] Maximize Research Levels" onClick={() => act('maxresearch')} />
) : null}
</Flex>
</Section>
);
};
const DeviceSettings = (props, context) => {
const { data, act } = useBackend(context);
const { linked_destroy, linked_lathe, linked_imprinter } = data;
return (
<Section
title="Linked Devices"
buttons={<Button icon="link" content="Re-sync with Nearby Devices" onClick={() => act('find_device')} />}
>
<LabeledList>
<LabeledList.Item label="Destructive Analyzer">
<Button
icon="unlink"
disabled={!linked_destroy}
content={linked_destroy ? 'Unlink' : 'Undetected'}
onClick={() => act('disconnect', { item: 'destroy' })}
/>
</LabeledList.Item>
<LabeledList.Item label="Protolathe">
<Button
icon="unlink"
disabled={!linked_lathe}
content={linked_lathe ? 'Unlink' : 'Undetected'}
onClick={() => {
act('disconnect', { item: 'lathe' });
}}
/>
</LabeledList.Item>
<LabeledList.Item label="Circuit Imprinter">
<Button
icon="unlink"
disabled={!linked_imprinter}
content={linked_imprinter ? 'Unlink' : 'Undetected'}
onClick={() => act('disconnect', { item: 'imprinter' })}
/>
</LabeledList.Item>
</LabeledList>
</Section>
);
};
@@ -0,0 +1,138 @@
import { useBackend } from '../../backend';
import { Window } from '../../layouts';
import { Box, Button, Icon, LabeledList, NoticeBox, Section, Table, Tabs } from '../../components';
import { classes } from 'common/react';
import { DataDiskMenu } from './DataDiskMenu';
import { LatheMenu } from './LatheMenu';
import { SettingsMenu } from './SettingsMenu';
import { DeconstructionMenu } from './DeconstructionMenu';
const Tab = Tabs.Tab;
export const MENU = {
MAIN: 0,
DISK: 2,
DESTROY: 3,
LATHE: 4,
IMPRINTER: 5,
SETTINGS: 6,
};
export const PRINTER_MENU = {
MAIN: 0,
SEARCH: 1,
MATERIALS: 2,
CHEMICALS: 3,
};
const decideTab = (tab) => {
switch (tab) {
case MENU.MAIN:
return <MainMenu />;
case MENU.DISK:
return <DataDiskMenu />;
case MENU.DESTROY:
return <DeconstructionMenu />;
case MENU.LATHE:
case MENU.IMPRINTER:
return <LatheMenu />;
case MENU.SETTINGS:
return <SettingsMenu />;
default:
return 'UNKNOWN MENU';
}
};
const ConsoleTab = (props, context) => {
const { act, data } = useBackend(context);
const { menu: currentMenu } = data;
const { menu, ...rest } = props;
return <Tab selected={currentMenu === menu} onClick={() => act('nav', { menu })} {...rest} />;
};
export const RndConsole = (properties, context) => {
const { act, data } = useBackend(context);
const { menu, linked_destroy, linked_lathe, linked_imprinter, wait_message } = data;
return (
<Window width={800} height={550}>
<Window.Content>
<Box className="RndConsole">
<Tabs>
<ConsoleTab icon="flask" menu={MENU.MAIN}>
Research
</ConsoleTab>
{!!linked_destroy && (
<ConsoleTab icon="microscope" menu={MENU.DESTROY}>
Analyze
</ConsoleTab>
)}
{!!linked_lathe && (
<ConsoleTab icon="print" menu={MENU.LATHE}>
Protolathe
</ConsoleTab>
)}
{!!linked_imprinter && (
<ConsoleTab icon="memory" menu={MENU.IMPRINTER}>
Imprinter
</ConsoleTab>
)}
<ConsoleTab icon="floppy-disk" menu={MENU.DISK}>
Disk
</ConsoleTab>
<ConsoleTab icon="cog" menu={MENU.SETTINGS}>
Settings
</ConsoleTab>
</Tabs>
{decideTab(menu)}
<WaitNotice />
</Box>
</Window.Content>
</Window>
);
};
const WaitNotice = (props, context) => {
const { data } = useBackend(context);
const { wait_message } = data;
if (!wait_message) {
return null;
}
return (
<Box className="RndConsole__Overlay">
<Box className="RndConsole__Overlay__Wrapper">
<NoticeBox color="black">{wait_message}</NoticeBox>
</Box>
</Box>
);
};
const MainMenu = (props, context) => {
const { data } = useBackend(context);
const { tech_levels } = data;
return (
<Section>
<Table id="research-levels">
<Table.Row>
<Table.Cell />
<Table.Cell header>Research Field</Table.Cell>
<Table.Cell header>Level</Table.Cell>
</Table.Row>
{tech_levels.map(({ id, name, desc, level, ui_icon }) => (
<Table.Row key={id}>
<Table.Cell>
<Button icon="circle-info" tooltip={desc} />
</Table.Cell>
<Table.Cell>
<Icon name={ui_icon} /> {name}
</Table.Cell>
<Table.Cell>{level}</Table.Cell>
</Table.Row>
))}
</Table>
</Section>
);
};
@@ -1,25 +0,0 @@
import { useBackend } from '../../backend';
import { Box, Divider } from '../../components';
export const CurrentLevels = (properties, context) => {
const { data } = useBackend(context);
const { tech_levels } = data;
return (
<Box>
<h3>Current Research Levels:</h3>
{tech_levels.map((techLevel, i) => {
const { name, level, desc } = techLevel;
return (
<Box key={name}>
{i > 0 ? <Divider /> : null}
<Box>{name}</Box>
<Box>* Level: {level}</Box>
<Box>* Summary: {desc}</Box>
</Box>
);
})}
</Box>
);
};
@@ -1,51 +0,0 @@
import { useBackend } from '../../backend';
import { Box, Button, LabeledList, Section } from '../../components';
export const DeconstructionMenu = (properties, context) => {
const { data, act } = useBackend(context);
const { loaded_item, linked_destroy } = data;
if (!linked_destroy) {
return <Box>NO DESTRUCTIVE ANALYZER LINKED TO CONSOLE</Box>;
}
if (!loaded_item) {
return <Section title="Deconstruction Menu">No item loaded. Standing by...</Section>;
}
return (
<Section noTopPadding title="Deconstruction Menu">
<Box mt="10px">Name: {loaded_item.name}</Box>
<Box mt="10px">
<h3>Origin Tech:</h3>
</Box>
<LabeledList>
{loaded_item.origin_tech.map((item) => {
return (
<LabeledList.Item label={'* ' + item.name} key={item.name}>
{item.object_level} {item.current_level ? <>(Current: {item.current_level})</> : null}
</LabeledList.Item>
);
})}
</LabeledList>
<Box mt="10px">
<h3>Options:</h3>
</Box>
<Button
content="Deconstruct Item"
icon="unlink"
onClick={() => {
act('deconstruct');
}}
/>
<Button
content="Eject Item"
icon="eject"
onClick={() => {
act('eject_item');
}}
/>
</Section>
);
};
@@ -1,28 +0,0 @@
import { useBackend } from '../../backend';
import { RndRoute } from './RndRoute';
import { LatheMainMenu, LatheCategory, LatheMaterialStorage, LatheChemicalStorage } from './index';
import { Box } from '../../components';
import { SUBMENU } from '../RndConsole';
export const LatheMenu = (properties, context) => {
const { data } = useBackend(context);
const { menu, linked_lathe, linked_imprinter } = data;
if (menu === 4 && !linked_lathe) {
return <Box>NO PROTOLATHE LINKED TO CONSOLE</Box>;
}
if (menu === 5 && !linked_imprinter) {
return <Box>NO CIRCUIT IMPRITER LINKED TO CONSOLE</Box>;
}
return (
<Box>
<RndRoute submenu={SUBMENU.MAIN} render={() => <LatheMainMenu />} />
<RndRoute submenu={SUBMENU.LATHE_CATEGORY} render={() => <LatheCategory />} />
<RndRoute submenu={SUBMENU.LATHE_MAT_STORAGE} render={() => <LatheMaterialStorage />} />
<RndRoute submenu={SUBMENU.LATHE_CHEM_STORAGE} render={() => <LatheChemicalStorage />} />
</Box>
);
};
@@ -1,56 +0,0 @@
import { useBackend } from '../../backend';
import { Box, Flex, LabeledList, Section } from '../../components';
import { RndNavButton } from './index';
import { MENU, SUBMENU } from '../RndConsole';
export const MainMenu = (properties, context) => {
const { data } = useBackend(context);
const { disk_type, linked_destroy, linked_lathe, linked_imprinter, tech_levels } = data;
return (
<Section title="Main Menu">
<Flex className="RndConsole__MainMenu__Buttons" direction="column" align="flex-start">
<RndNavButton
disabled={!disk_type}
menu={MENU.DISK}
submenu={SUBMENU.MAIN}
icon="save"
content="Disk Operations"
/>
<RndNavButton
disabled={!linked_destroy}
menu={MENU.DESTROY}
submenu={SUBMENU.MAIN}
icon="unlink"
content="Destructive Analyzer Menu"
/>
<RndNavButton
disabled={!linked_lathe}
menu={MENU.LATHE}
submenu={SUBMENU.MAIN}
icon="print"
content="Protolathe Menu"
/>
<RndNavButton
disabled={!linked_imprinter}
menu={MENU.IMPRINTER}
submenu={SUBMENU.MAIN}
icon="print"
content="Circuit Imprinter Menu"
/>
<RndNavButton menu={MENU.SETTINGS} submenu={SUBMENU.MAIN} icon="cog" content="Settings" />
</Flex>
<Box mt="12px" />
<h3>Current Research Levels:</h3>
<LabeledList>
{tech_levels.map(({ name, level }) => (
<LabeledList.Item label={name} key={name}>
{level}
</LabeledList.Item>
))}
</LabeledList>
</Section>
);
};
@@ -1,33 +0,0 @@
import { useBackend } from '../../backend';
import { Button } from '../../components';
export const RndNavButton = (properties, context) => {
const { icon, children, disabled, content } = properties;
const { data, act } = useBackend(context);
const { menu, submenu } = data;
let nextMenu = menu;
let nextSubmenu = submenu;
if (properties.menu !== null && properties.menu !== undefined) {
nextMenu = properties.menu;
}
if (properties.submenu !== null && properties.submenu !== undefined) {
nextSubmenu = properties.submenu;
}
// const active = data.menu === menu && data.submenu === submenu;
return (
<Button
content={content}
icon={icon}
disabled={disabled}
onClick={() => {
act('nav', { menu: nextMenu, submenu: nextSubmenu });
}}
>
{children}
</Button>
);
};
@@ -1,51 +0,0 @@
import { RndRoute, RndNavButton } from './index';
import { Box } from '../../components';
import { MENU, SUBMENU } from '../RndConsole';
export const RndNavbar = () => (
<Box className="RndConsole__RndNavbar">
<RndRoute
menu={(n) => n !== MENU.MAIN}
render={() => <RndNavButton menu={MENU.MAIN} submenu={SUBMENU.MAIN} icon="reply" content="Main Menu" />}
/>
{/* Links to return to submenu 0 for each menu other than main menu */}
<RndRoute
submenu={(n) => n !== SUBMENU.MAIN}
render={() => (
<Box>
<RndRoute
menu={MENU.DISK}
render={() => <RndNavButton submenu={SUBMENU.MAIN} icon="reply" content="Disk Operations Menu" />}
/>
<RndRoute
menu={MENU.LATHE}
render={() => <RndNavButton submenu={SUBMENU.MAIN} icon="reply" content="Protolathe Menu" />}
/>
<RndRoute
menu={MENU.IMPRINTER}
render={() => <RndNavButton submenu={SUBMENU.MAIN} icon="reply" content="Circuit Imprinter Menu" />}
/>
<RndRoute
menu={MENU.SETTINGS}
render={() => <RndNavButton submenu={SUBMENU.MAIN} icon="reply" content="Settings Menu" />}
/>
</Box>
)}
/>
<RndRoute
menu={(n) => n === MENU.LATHE || n === MENU.IMPRINTER}
submenu={SUBMENU.MAIN}
render={() => (
<Box>
<RndNavButton submenu={SUBMENU.LATHE_MAT_STORAGE} icon="arrow-up" content="Material Storage" />
<RndNavButton submenu={SUBMENU.LATHE_CHEM_STORAGE} icon="arrow-up" content="Chemical Storage" />
</Box>
)}
/>
</Box>
);
@@ -1,25 +0,0 @@
import { useBackend } from '../../backend';
export const RndRoute = (properties, context) => {
const { render } = properties;
const { data } = useBackend(context);
const { menu, submenu } = data;
const compare = (comparator, item) => {
if (comparator === null || comparator === undefined) {
return true;
} // unspecified, match all
if (typeof comparator === 'function') {
return comparator(item);
}
return comparator === item; // strings or ints?
};
let match = compare(properties.menu, menu) && compare(properties.submenu, submenu);
if (!match) {
return null;
}
return render();
};
@@ -1,110 +0,0 @@
import { useBackend } from '../../backend';
import { Box, Button, Flex, LabeledList, Section } from '../../components';
import { RndRoute, RndNavButton } from './index';
import { MENU, SUBMENU } from '../RndConsole';
export const SettingsMenu = (properties, context) => {
const { data, act } = useBackend(context);
const { sync, admin, linked_destroy, linked_lathe, linked_imprinter } = data;
return (
<Box>
<RndRoute
submenu={SUBMENU.MAIN}
render={() => (
<Section title="Settings">
<Flex direction="column" align="flex-start">
<Button
content="Sync Database with Network"
icon="sync"
disabled={!sync}
onClick={() => {
act('sync');
}}
/>
<Button
content="Connect to Research Network"
icon="plug"
disabled={sync}
onClick={() => {
act('togglesync');
}}
/>
<Button
disabled={!sync}
icon="unlink"
content="Disconnect from Research Network"
onClick={() => {
act('togglesync');
}}
/>
<RndNavButton
disabled={!sync}
content="Device Linkage Menu"
icon="link"
menu={MENU.SETTINGS}
submenu={SUBMENU.SETTINGS_DEVICES}
/>
{admin === 1 ? (
<Button
icon="exclamation"
content="[ADMIN] Maximize Research Levels"
onClick={() => act('maxresearch')}
/>
) : null}
</Flex>
</Section>
)}
/>
<RndRoute
submenu={SUBMENU.SETTINGS_DEVICES}
render={() => (
<Section title="Device Linkage Menu">
<Button icon="link" content="Re-sync with Nearby Devices" onClick={() => act('find_device')} />
<Box mt="5px">
<h3>Linked Devices:</h3>
</Box>
<LabeledList>
{linked_destroy ? (
<LabeledList.Item label="* Destructive Analyzer">
<Button icon="unlink" content="Unlink" onClick={() => act('disconnect', { item: 'destroy' })} />
</LabeledList.Item>
) : (
<LabeledList.Item noColon label="* No Destructive Analyzer Linked" />
)}
{linked_lathe ? (
<LabeledList.Item label="* Protolathe">
<Button
icon="unlink"
content="Unlink"
onClick={() => {
act('disconnect', { item: 'lathe' });
}}
/>
</LabeledList.Item>
) : (
<LabeledList.Item noColon label="* No Protolathe Linked" />
)}
{linked_imprinter ? (
<LabeledList.Item label="* Circuit Imprinter">
<Button icon="unlink" content="Unlink" onClick={() => act('disconnect', { item: 'imprinter' })} />
</LabeledList.Item>
) : (
<LabeledList.Item noColon label="* No Circuit Imprinter Linked" />
)}
</LabeledList>
</Section>
)}
/>
</Box>
);
};
@@ -1,15 +0,0 @@
export { CurrentLevels } from './CurrentLevels';
export { DataDiskMenu } from './DataDiskMenu';
export { DeconstructionMenu } from './DeconstructionMenu';
export { LatheCategory } from './LatheCategory';
export { LatheChemicalStorage } from './LatheChemicalStorage';
export { LatheMainMenu } from './LatheMainMenu';
export { LatheMaterials } from './LatheMaterials';
export { LatheMaterialStorage } from './LatheMaterialStorage';
export { LatheMenu } from './LatheMenu';
export { LatheSearch } from './LatheSearch';
export { MainMenu } from './MainMenu';
export { RndNavbar } from './RndNavbar';
export { RndNavButton } from './RndNavButton';
export { RndRoute } from './RndRoute';
export { SettingsMenu } from './SettingsMenu';
@@ -20,12 +20,6 @@
padding-bottom: 4px;
}
.RndConsole__MainMenu__Buttons {
.Button:not(:last-child) {
margin-bottom: 4px;
}
}
.RndConsole__LatheMaterials {
.Table__cell:nth-child(2) {
padding-left: 16px;
@@ -62,3 +56,27 @@
margin-bottom: 10px;
}
}
#research-levels tr {
& > *:first-child {
width: 2em;
}
& > *:nth-child(3),
& > *:nth-child(4),
& > *:nth-child(5) {
text-align: center;
}
}
#research-levels tr:not(:first-child) > *:first-child {
height: 2em;
}
.upgraded-level {
color: #55d355;
}
.research-level-no-effect {
color: #888888;
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long