mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-29 16:18:01 +01:00
TGUI Limbgrower + Limbgrower refactoring and design expansion (#57955)
Refactors the limbgrower to modernize the code. Now, the limbgrower can accept any type of reagent in limbgrower designs. Adds simple plumbing demand to the limbgrower, so you can pipe synthflesh into it. Adds monkey tails, felinid ears and tails, lizard digitigrade legs, lizard tongues, fake lizard tails (unusable in lizard-wine and similar recipes), plasmaman organs, and ethereal organs (minus the heart) to the limbgrower via limbgrower design disks. These disks can be printed from the medical lathe once the required technology has been researched. Adds a technology node to unlock the limbgrower design disks after advanced biotech, xenoorgan biology. In the future, this could have an experiment requirement - maybe to scan multiple types of species. Co-authored-by: Aleksej Komarov <stylemistake@gmail.com>
This commit is contained in:
co-authored by
Aleksej Komarov
parent
8c1d6118e5
commit
b46b586d7b
@@ -138,6 +138,7 @@
|
||||
result = /obj/item/tailclub
|
||||
reqs = list(/obj/item/organ/tail/lizard = 1,
|
||||
/obj/item/stack/sheet/iron = 1)
|
||||
blacklist = list(/obj/item/organ/tail/lizard/fake)
|
||||
time = 40
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
@@ -147,6 +148,7 @@
|
||||
result = /obj/item/melee/chainofcommand/tailwhip
|
||||
reqs = list(/obj/item/organ/tail/lizard = 1,
|
||||
/obj/item/stack/cable_coil = 1)
|
||||
blacklist = list(/obj/item/organ/tail/lizard/fake)
|
||||
time = 40
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
+194
-154
@@ -1,9 +1,5 @@
|
||||
#define LIMBGROWER_MAIN_MENU 1
|
||||
#define LIMBGROWER_CATEGORY_MENU 2
|
||||
#define LIMBGROWER_CHEMICAL_MENU 3
|
||||
//use these for the menu system
|
||||
|
||||
|
||||
/// The limbgrower. Makes organd and limbs with synthflesh and chems.
|
||||
/// See [limbgrower_designs.dm] for everything we can make.
|
||||
/obj/machinery/limbgrower
|
||||
name = "limb grower"
|
||||
desc = "It grows new limbs using Synthflesh."
|
||||
@@ -15,135 +11,222 @@
|
||||
active_power_usage = 100
|
||||
circuit = /obj/item/circuitboard/machine/limbgrower
|
||||
|
||||
var/operating = FALSE
|
||||
var/disabled = FALSE
|
||||
/// The category of limbs we're browing in our UI.
|
||||
var/selected_category = "human"
|
||||
/// If we're currently printing something.
|
||||
var/busy = FALSE
|
||||
var/prod_coeff = 1
|
||||
/// How efficient our machine is. Better parts = less chemicals used and less power used. Range of 1 to 0.25.
|
||||
var/production_coefficient = 1
|
||||
/// How long it takes for us to print a limb. Affected by production_coefficient.
|
||||
var/production_speed = 3 SECONDS
|
||||
/// The design we're printing currently.
|
||||
var/datum/design/being_built
|
||||
/// Our internal techweb for limbgrower designs.
|
||||
var/datum/techweb/stored_research
|
||||
var/selected_category
|
||||
var/screen = 1
|
||||
var/list/categories = list(
|
||||
"human",
|
||||
"lizard",
|
||||
"moth",
|
||||
"plasmaman",
|
||||
"ethereal",
|
||||
"other"
|
||||
)
|
||||
/// All the categories of organs we can print.
|
||||
var/list/categories = list("human", "lizard", "moth", "plasmaman", "ethereal", "other")
|
||||
|
||||
/obj/machinery/limbgrower/Initialize()
|
||||
create_reagents(100, OPENCONTAINER)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/limbgrower
|
||||
. = ..()
|
||||
AddComponent(/datum/component/plumbing/simple_demand)
|
||||
|
||||
/obj/machinery/limbgrower/ui_interact(mob/user)
|
||||
/obj/machinery/limbgrower/ui_interact(mob/user, datum/tgui/ui)
|
||||
. = ..()
|
||||
if(!is_operational)
|
||||
return
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "Limbgrower")
|
||||
ui.open()
|
||||
|
||||
var/dat = main_win(user)
|
||||
/obj/machinery/limbgrower/ui_state(mob/user)
|
||||
return GLOB.physical_state
|
||||
|
||||
switch(screen)
|
||||
if(LIMBGROWER_MAIN_MENU)
|
||||
dat = main_win(user)
|
||||
if(LIMBGROWER_CATEGORY_MENU)
|
||||
dat = category_win(user,selected_category)
|
||||
if(LIMBGROWER_CHEMICAL_MENU)
|
||||
dat = chemical_win(user)
|
||||
/obj/machinery/limbgrower/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
var/datum/browser/popup = new(user, "Limb Grower", name, 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
for(var/datum/reagent/reagent_id in reagents.reagent_list)
|
||||
var/list/reagent_data = list(
|
||||
reagent_name = reagent_id.name,
|
||||
reagent_amount = reagent_id.volume,
|
||||
reagent_type = reagent_id.type
|
||||
)
|
||||
data["reagents"] += list(reagent_data)
|
||||
|
||||
data["total_reagents"] = reagents.total_volume
|
||||
data["max_reagents"] = reagents.maximum_volume
|
||||
data["busy"] = busy
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/limbgrower/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["categories"] = list()
|
||||
|
||||
var/species_categories = categories.Copy()
|
||||
for(var/species in species_categories)
|
||||
species_categories[species] = list()
|
||||
for(var/design_id in stored_research.researched_designs)
|
||||
var/datum/design/limb_design = SSresearch.techweb_design_by_id(design_id)
|
||||
for(var/found_category in species_categories)
|
||||
if(found_category in limb_design.category)
|
||||
species_categories[found_category] += limb_design
|
||||
|
||||
for(var/category in species_categories)
|
||||
var/list/category_data = list(
|
||||
name = category,
|
||||
designs = list(),
|
||||
)
|
||||
for(var/datum/design/found_design in species_categories[category])
|
||||
var/list/all_reagents = list()
|
||||
for(var/reagent_typepath in found_design.reagents_list)
|
||||
var/datum/reagent/reagent_id = find_reagent_object_from_type(reagent_typepath)
|
||||
var/list/reagent_data = list(
|
||||
name = reagent_id.name,
|
||||
amount = (found_design.reagents_list[reagent_typepath] * production_coefficient),
|
||||
)
|
||||
all_reagents += list(reagent_data)
|
||||
|
||||
category_data["designs"] += list(list(
|
||||
parent_category = category,
|
||||
name = found_design.name,
|
||||
id = found_design.id,
|
||||
needed_reagents = all_reagents,
|
||||
))
|
||||
|
||||
data["categories"] += list(category_data)
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/limbgrower/on_deconstruction()
|
||||
for(var/obj/item/reagent_containers/glass/G in component_parts)
|
||||
reagents.trans_to(G, G.reagents.maximum_volume)
|
||||
for(var/obj/item/reagent_containers/glass/our_beaker in component_parts)
|
||||
reagents.trans_to(our_beaker, our_beaker.reagents.maximum_volume)
|
||||
..()
|
||||
|
||||
/obj/machinery/limbgrower/attackby(obj/item/O, mob/living/user, params)
|
||||
/obj/machinery/limbgrower/attackby(obj/item/user_item, mob/living/user, params)
|
||||
if (busy)
|
||||
to_chat(user, "<span class=\"alert\">The Limb Grower is busy. Please wait for completion of previous operation.</span>")
|
||||
return
|
||||
|
||||
if(default_deconstruction_screwdriver(user, "limbgrower_panelopen", "limbgrower_idleoff", O))
|
||||
updateUsrDialog()
|
||||
if(istype(user_item, /obj/item/disk/design_disk/limbs))
|
||||
user.visible_message("<span class='notice'>[user] begins to load \the [user_item] in \the [src]...</span>",
|
||||
"<span class='notice'>You begin to load designs from \the [user_item]...</span>",
|
||||
"<span class='hear'>You hear the clatter of a floppy drive.</span>")
|
||||
busy = TRUE
|
||||
var/obj/item/disk/design_disk/limbs/limb_design_disk = user_item
|
||||
if(do_after(user, 2 SECONDS, target = src))
|
||||
for(var/datum/design/found_design in limb_design_disk.blueprints)
|
||||
stored_research.add_design(found_design)
|
||||
update_static_data(user)
|
||||
busy = FALSE
|
||||
return
|
||||
|
||||
if(panel_open && default_deconstruction_crowbar(O))
|
||||
if(default_deconstruction_screwdriver(user, "limbgrower_panelopen", "limbgrower_idleoff", user_item))
|
||||
ui_close(user)
|
||||
return
|
||||
|
||||
if(panel_open && default_deconstruction_crowbar(user_item))
|
||||
return
|
||||
|
||||
if(user.combat_mode) //so we can hit the machine
|
||||
return ..()
|
||||
|
||||
/obj/machinery/limbgrower/Topic(href, href_list)
|
||||
if(..())
|
||||
/obj/machinery/limbgrower/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if (!busy)
|
||||
if(href_list["menu"])
|
||||
screen = text2num(href_list["menu"])
|
||||
|
||||
if(href_list["category"] in categories) //Don't let people send invalid categories, selected_category is displayed to anyone who looks at the machine in several places
|
||||
selected_category = href_list["category"]
|
||||
if (busy)
|
||||
to_chat(usr, "<span class='danger'>The limb grower is busy. Please wait for completion of previous operation.</span>")
|
||||
return
|
||||
|
||||
if(href_list["disposeI"]) //Get rid of a reagent incase you add the wrong one by mistake
|
||||
reagents.del_reagent(text2path(href_list["disposeI"]))
|
||||
switch(action)
|
||||
|
||||
if(href_list["make"])
|
||||
if("empty_reagent")
|
||||
reagents.del_reagent(text2path(params["reagent_type"]))
|
||||
. = TRUE
|
||||
|
||||
/////////////////
|
||||
//href protection
|
||||
being_built = stored_research.isDesignResearchedID(href_list["make"]) //check if it's a valid design
|
||||
if("make_limb")
|
||||
being_built = stored_research.isDesignResearchedID(params["design_id"])
|
||||
if(!being_built)
|
||||
return
|
||||
CRASH("[src] was passed an invalid design id!")
|
||||
|
||||
/// All the reagents we're using to make our organ.
|
||||
var/list/consumed_reagents_list = being_built.reagents_list.Copy()
|
||||
/// The amount of power we're going to use, based on how much reagent we use.
|
||||
var/power = 0
|
||||
|
||||
var/synth_cost = being_built.reagents_list[/datum/reagent/medicine/c2/synthflesh]*prod_coeff
|
||||
var/power = max(2000, synth_cost/5)
|
||||
for(var/reagent_id in consumed_reagents_list)
|
||||
consumed_reagents_list[reagent_id] *= production_coefficient
|
||||
if(!reagents.has_reagent(reagent_id, consumed_reagents_list[reagent_id]))
|
||||
audible_message("<span class='notice'>The [src] buzzes.</span>")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
|
||||
return
|
||||
|
||||
if(reagents.has_reagent(/datum/reagent/medicine/c2/synthflesh, being_built.reagents_list[/datum/reagent/medicine/c2/synthflesh]*prod_coeff))
|
||||
busy = TRUE
|
||||
use_power(power)
|
||||
flick("limbgrower_fill",src)
|
||||
icon_state = "limbgrower_idleon"
|
||||
addtimer(CALLBACK(src, .proc/build_item),32*prod_coeff)
|
||||
power = max(2000, (power + consumed_reagents_list[reagent_id]))
|
||||
|
||||
else
|
||||
to_chat(usr, "<span class=\"alert\">The limb grower is busy. Please wait for completion of previous operation.</span>")
|
||||
busy = TRUE
|
||||
use_power(power)
|
||||
flick("limbgrower_fill",src)
|
||||
icon_state = "limbgrower_idleon"
|
||||
selected_category = params["active_tab"]
|
||||
addtimer(CALLBACK(src, .proc/build_item, consumed_reagents_list), production_speed * production_coefficient)
|
||||
. = TRUE
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/limbgrower/proc/build_item()
|
||||
if(reagents.has_reagent(/datum/reagent/medicine/c2/synthflesh, being_built.reagents_list[/datum/reagent/medicine/c2/synthflesh]*prod_coeff)) //sanity check, if this happens we are in big trouble
|
||||
reagents.remove_reagent(/datum/reagent/medicine/c2/synthflesh,being_built.reagents_list[/datum/reagent/medicine/c2/synthflesh]*prod_coeff)
|
||||
var/buildpath = being_built.build_path
|
||||
if(ispath(buildpath, /obj/item/bodypart)) //This feels like spatgheti code, but i need to initilise a limb somehow
|
||||
build_limb(buildpath)
|
||||
else
|
||||
//Just build whatever it is
|
||||
new buildpath(loc)
|
||||
else
|
||||
src.visible_message("<span class='warning'>Something went very wrong, there isn't enough synthflesh anymore!</span>")
|
||||
busy = FALSE
|
||||
flick("limbgrower_unfill",src)
|
||||
icon_state = "limbgrower_idleoff"
|
||||
updateUsrDialog()
|
||||
/*
|
||||
* The process of beginning to build a limb or organ.
|
||||
* Goes through and sanity checks that we actually have enough reagent to build our item.
|
||||
* Then, remove those reagents from our reagents datum.
|
||||
*
|
||||
* After the reagents are handled, we can proceede with making the limb or organ. (Limbs are handled in a separate proc)
|
||||
*
|
||||
* modified_consumed_reagents_list - the list of reagents we will consume on build, modified by the production coefficient.
|
||||
*/
|
||||
/obj/machinery/limbgrower/proc/build_item(list/modified_consumed_reagents_list)
|
||||
for(var/reagent_id in modified_consumed_reagents_list)
|
||||
if(!reagents.has_reagent(reagent_id, modified_consumed_reagents_list[reagent_id]))
|
||||
audible_message("<span class='notice'>The [src] buzzes.</span>")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
|
||||
break
|
||||
|
||||
reagents.remove_reagent(reagent_id, modified_consumed_reagents_list[reagent_id])
|
||||
|
||||
var/built_typepath = being_built.build_path
|
||||
// If we have a bodypart, we need to initialize the limb on its own. Otherwise we can build it here.
|
||||
if(ispath(built_typepath, /obj/item/bodypart))
|
||||
build_limb(built_typepath)
|
||||
else
|
||||
new built_typepath(loc)
|
||||
|
||||
busy = FALSE
|
||||
flick("limbgrower_unfill", src)
|
||||
icon_state = "limbgrower_idleoff"
|
||||
|
||||
/*
|
||||
* The process of putting together a limb.
|
||||
* This is called from after we remove the reagents, so this proc is just initializing the limb type.
|
||||
*
|
||||
* This proc handles skin / mutant color, greyscaling, names and descriptions, and various other limb creation steps.
|
||||
*
|
||||
* buildpath - the path of the bodypart we're building.
|
||||
*/
|
||||
/obj/machinery/limbgrower/proc/build_limb(buildpath)
|
||||
//i need to create a body part manually using a set icon (otherwise it doesnt appear)
|
||||
var/obj/item/bodypart/limb
|
||||
limb = new buildpath(loc)
|
||||
if(selected_category=="human" || selected_category=="lizard" || selected_category=="ethereal") //Species with greyscale parts should be included here
|
||||
if(selected_category=="human") //humans don't use the full colour spectrum, they use random_skin_tone
|
||||
/// The limb we're making with our buildpath, so we can edit it.
|
||||
var/obj/item/bodypart/limb = new buildpath(loc)
|
||||
/// Species with greyscale limbs.
|
||||
var/list/greyscale_species = list("human", "lizard", "ethereal")
|
||||
if(selected_category in greyscale_species) //Species with greyscale parts should be included here
|
||||
if(selected_category == "human") //humans don't use the full colour spectrum, they use random_skin_tone
|
||||
limb.skin_tone = random_skin_tone()
|
||||
else
|
||||
limb.species_color = random_short_color()
|
||||
|
||||
limb.icon = 'icons/mob/human_parts_greyscale.dmi'
|
||||
limb.should_draw_greyscale = TRUE
|
||||
else
|
||||
limb.icon = 'icons/mob/human_parts.dmi'
|
||||
|
||||
// Set this limb up using the species name and body zone
|
||||
limb.icon_state = "[selected_category]_[limb.body_zone]"
|
||||
limb.name = "\improper biosynthetic [selected_category] [parse_zone(limb.body_zone)]"
|
||||
@@ -154,83 +237,40 @@
|
||||
|
||||
/obj/machinery/limbgrower/RefreshParts()
|
||||
reagents.maximum_volume = 0
|
||||
for(var/obj/item/reagent_containers/glass/G in component_parts)
|
||||
reagents.maximum_volume += G.volume
|
||||
G.reagents.trans_to(src, G.reagents.total_volume)
|
||||
var/T=1.2
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
T -= M.rating*0.2
|
||||
prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
|
||||
for(var/obj/item/reagent_containers/glass/our_beaker in component_parts)
|
||||
reagents.maximum_volume += our_beaker.volume
|
||||
our_beaker.reagents.trans_to(src, our_beaker.reagents.total_volume)
|
||||
production_coefficient = 1.25
|
||||
for(var/obj/item/stock_parts/manipulator/our_manipulator in component_parts)
|
||||
production_coefficient -= our_manipulator.rating * 0.25
|
||||
production_coefficient = clamp(production_coefficient, 0, 1) // coefficient goes from 1 -> 0.75 -> 0.5 -> 0.25
|
||||
|
||||
/obj/machinery/limbgrower/examine(mob/user)
|
||||
. = ..()
|
||||
if(in_range(user, src) || isobserver(user))
|
||||
. += "<span class='notice'>The status display reads: Storing up to <b>[reagents.maximum_volume]u</b> of synthflesh.<br>Synthflesh consumption at <b>[prod_coeff*100]%</b>.</span>"
|
||||
. += "<span class='notice'>The status display reads: Storing up to <b>[reagents.maximum_volume]u</b> of reagents.<br>Reagent consumption rate at <b>[production_coefficient * 100]%</b>.</span>"
|
||||
|
||||
/obj/machinery/limbgrower/proc/main_win(mob/user)
|
||||
var/dat = "<div class='statusDisplay'><h3>Limb Grower Menu:</h3><br>"
|
||||
dat += "<A href='?src=[REF(src)];menu=[LIMBGROWER_CHEMICAL_MENU]'>Chemical Storage</A>"
|
||||
dat += materials_printout()
|
||||
dat += "<table style='width:100%' align='center'><tr>"
|
||||
|
||||
for(var/C in categories)
|
||||
dat += "<td><A href='?src=[REF(src)];category=[C];menu=[LIMBGROWER_CATEGORY_MENU]'>[C]</A></td>"
|
||||
dat += "</tr><tr>"
|
||||
//one category per line
|
||||
|
||||
dat += "</tr></table></div>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/limbgrower/proc/category_win(mob/user,selected_category)
|
||||
var/dat = "<A href='?src=[REF(src)];menu=[LIMBGROWER_MAIN_MENU]'>Return to main menu</A>"
|
||||
dat += "<div class='statusDisplay'><h3>Browsing [selected_category]:</h3><br>"
|
||||
dat += materials_printout()
|
||||
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if(!(selected_category in D.category))
|
||||
continue
|
||||
if(disabled || !can_build(D))
|
||||
dat += "<span class='linkOff'>[D.name]</span>"
|
||||
else
|
||||
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
|
||||
dat += "[get_design_cost(D)]<br>"
|
||||
|
||||
dat += "</div>"
|
||||
return dat
|
||||
|
||||
|
||||
/obj/machinery/limbgrower/proc/chemical_win(mob/user)
|
||||
var/dat = "<A href='?src=[REF(src)];menu=[LIMBGROWER_MAIN_MENU]'>Return to main menu</A>"
|
||||
dat += "<div class='statusDisplay'><h3>Browsing Chemical Storage:</h3><br>"
|
||||
dat += materials_printout()
|
||||
|
||||
for(var/datum/reagent/R in reagents.reagent_list)
|
||||
dat += "[R.name]: [R.volume]"
|
||||
dat += "<A href='?src=[REF(src)];disposeI=[R]'>Purge</A><BR>"
|
||||
|
||||
dat += "</div>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/limbgrower/proc/materials_printout()
|
||||
var/dat = "<b>Total amount:></b> [reagents.total_volume] / [reagents.maximum_volume] cm<sup>3</sup><br>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/limbgrower/proc/can_build(datum/design/D)
|
||||
return (reagents.has_reagent(/datum/reagent/medicine/c2/synthflesh, D.reagents_list[/datum/reagent/medicine/c2/synthflesh]*prod_coeff)) //Return whether the machine has enough synthflesh to produce the design
|
||||
|
||||
/obj/machinery/limbgrower/proc/get_design_cost(datum/design/D)
|
||||
var/dat
|
||||
if(D.reagents_list[/datum/reagent/medicine/c2/synthflesh])
|
||||
dat += "[D.reagents_list[/datum/reagent/medicine/c2/synthflesh] * prod_coeff] SynthFlesh"
|
||||
return dat
|
||||
/*
|
||||
* Checks our reagent list to see if a design can be built.
|
||||
*
|
||||
* limb_design - the design we're checking for buildability.
|
||||
*
|
||||
* returns TRUE if we have enough reagent to build it. Returns FALSE if we do not.
|
||||
*/
|
||||
/obj/machinery/limbgrower/proc/can_build(datum/design/limb_design)
|
||||
for(var/datum/reagent/reagent_id in limb_design.reagents_list)
|
||||
if(!reagents.has_reagent(reagent_id, limb_design.reagents_list[reagent_id] * production_coefficient))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/// Emagging a limbgrower allows you to build synthetic armblades.
|
||||
/obj/machinery/limbgrower/emag_act(mob/user)
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
for(var/id in SSresearch.techweb_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(id)
|
||||
if((D.build_type & LIMBGROWER) && ("emagged" in D.category))
|
||||
stored_research.add_design(D)
|
||||
for(var/design_id in SSresearch.techweb_designs)
|
||||
var/datum/design/found_design = SSresearch.techweb_design_by_id(design_id)
|
||||
if((found_design.build_type & LIMBGROWER) && ("emagged" in found_design.category))
|
||||
stored_research.add_design(found_design)
|
||||
to_chat(user, "<span class='warning'>A warning flashes onto the screen, stating that safety overrides have been deactivated!</span>")
|
||||
obj_flags |= EMAGGED
|
||||
update_static_data(user)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
/obj/item/organ/tail/lizard = 1,
|
||||
/datum/reagent/consumable/ethanol = 100
|
||||
)
|
||||
blacklist = list(/obj/item/organ/tail/lizard/fake)
|
||||
result = /obj/item/reagent_containers/food/drinks/bottle/lizardwine
|
||||
category = CAT_DRINK
|
||||
|
||||
|
||||
@@ -34,6 +34,22 @@
|
||||
build_path = /obj/item/bodypart/r_leg
|
||||
category = list("initial","human","lizard","moth","plasmaman","ethereal")
|
||||
|
||||
/datum/design/digi_leftleg
|
||||
name = "Digitigrade Left Leg"
|
||||
id = "digi_leftleg"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 30)
|
||||
build_path = /obj/item/bodypart/l_leg/digitigrade
|
||||
category = list("lizard")
|
||||
|
||||
/datum/design/digi_rightleg
|
||||
name = "Digitigrade Right Leg"
|
||||
id = "digi_rightleg"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 30)
|
||||
build_path = /obj/item/bodypart/r_leg/digitigrade
|
||||
category = list("lizard")
|
||||
|
||||
//Non-limb limb designs
|
||||
|
||||
/datum/design/heart
|
||||
@@ -42,7 +58,7 @@
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 30)
|
||||
build_path = /obj/item/organ/heart
|
||||
category = list("other","initial")
|
||||
category = list("human","initial")
|
||||
|
||||
/datum/design/lungs
|
||||
name = "Lungs"
|
||||
@@ -50,7 +66,7 @@
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 20)
|
||||
build_path = /obj/item/organ/lungs
|
||||
category = list("other","initial")
|
||||
category = list("human","initial")
|
||||
|
||||
/datum/design/liver
|
||||
name = "Liver"
|
||||
@@ -58,7 +74,7 @@
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 20)
|
||||
build_path = /obj/item/organ/liver
|
||||
category = list("other","initial")
|
||||
category = list("human","initial")
|
||||
|
||||
/datum/design/stomach
|
||||
name = "Stomach"
|
||||
@@ -66,7 +82,7 @@
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 15)
|
||||
build_path = /obj/item/organ/stomach
|
||||
category = list("other","initial")
|
||||
category = list("human","initial")
|
||||
|
||||
/datum/design/appendix
|
||||
name = "Appendix"
|
||||
@@ -74,7 +90,7 @@
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 5) //why would you need this
|
||||
build_path = /obj/item/organ/appendix
|
||||
category = list("other","initial")
|
||||
category = list("human","initial")
|
||||
|
||||
/datum/design/eyes
|
||||
name = "Eyes"
|
||||
@@ -82,7 +98,7 @@
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10)
|
||||
build_path = /obj/item/organ/eyes
|
||||
category = list("other","initial")
|
||||
category = list("human","initial")
|
||||
|
||||
/datum/design/ears
|
||||
name = "Ears"
|
||||
@@ -90,7 +106,7 @@
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10)
|
||||
build_path = /obj/item/organ/ears
|
||||
category = list("other","initial")
|
||||
category = list("human","initial")
|
||||
|
||||
/datum/design/tongue
|
||||
name = "Tongue"
|
||||
@@ -98,8 +114,106 @@
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10)
|
||||
build_path = /obj/item/organ/tongue
|
||||
category = list("human","initial")
|
||||
|
||||
// Grows a fake lizard tail - not usable in lizard wine and other similar recipes.
|
||||
/datum/design/lizard_tail
|
||||
name = "Lizard Tail"
|
||||
id = "liztail"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 20)
|
||||
build_path = /obj/item/organ/tail/lizard/fake
|
||||
category = list("lizard")
|
||||
|
||||
/datum/design/lizard_tongue
|
||||
name = "Forked Tongue"
|
||||
id = "liztongue"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 20)
|
||||
build_path = /obj/item/organ/tongue/lizard
|
||||
category = list("lizard")
|
||||
|
||||
/datum/design/monkey_tail
|
||||
name = "Monkey Tail"
|
||||
id = "monkeytail"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 20)
|
||||
build_path = /obj/item/organ/tail/monkey
|
||||
category = list("other","initial")
|
||||
|
||||
/datum/design/cat_tail
|
||||
name = "Cat Tail"
|
||||
id = "cattail"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 20)
|
||||
build_path = /obj/item/organ/tail/cat
|
||||
category = list("human")
|
||||
|
||||
/datum/design/cat_ears
|
||||
name = "Cat Ears"
|
||||
id = "catears"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10)
|
||||
build_path = /obj/item/organ/ears/cat
|
||||
category = list("human")
|
||||
|
||||
/datum/design/plasmaman_lungs
|
||||
name = "Plasma Filter"
|
||||
id = "plasmamanlungs"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10, /datum/reagent/toxin/plasma = 20)
|
||||
build_path = /obj/item/organ/lungs/plasmaman
|
||||
category = list("plasmaman")
|
||||
|
||||
/datum/design/plasmaman_tongue
|
||||
name = "Plasma Bone Tongue"
|
||||
id = "plasmamantongue"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10, /datum/reagent/toxin/plasma = 20)
|
||||
build_path = /obj/item/organ/tongue/bone/plasmaman
|
||||
category = list("plasmaman")
|
||||
|
||||
/datum/design/plasmaman_liver
|
||||
name = "Reagent Processing Crystal"
|
||||
id = "plasmamanliver"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10, /datum/reagent/toxin/plasma = 20)
|
||||
build_path = /obj/item/organ/liver/plasmaman
|
||||
category = list("plasmaman")
|
||||
|
||||
/datum/design/plasmaman_stomach
|
||||
name = "Digestive Crystal"
|
||||
id = "plasmamanstomach"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10, /datum/reagent/toxin/plasma = 20)
|
||||
build_path = /obj/item/organ/stomach/bone/plasmaman
|
||||
category = list("plasmaman")
|
||||
|
||||
/datum/design/ethereal_stomach
|
||||
name = "Biological Battery"
|
||||
id = "etherealstomach"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10, /datum/reagent/consumable/liquidelectricity = 20)
|
||||
build_path = /obj/item/organ/stomach/ethereal
|
||||
category = list("ethereal")
|
||||
|
||||
/datum/design/ethereal_tongue
|
||||
name = "Electrical Discharger"
|
||||
id = "etherealtongue"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10, /datum/reagent/consumable/liquidelectricity = 20)
|
||||
build_path = /obj/item/organ/tongue/ethereal
|
||||
category = list("ethereal")
|
||||
|
||||
// Intentionally not growable by normal means - for balance conerns.
|
||||
/datum/design/ethereal_heart
|
||||
name = "Crystal Core"
|
||||
id = "etherealheart"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10, /datum/reagent/consumable/liquidelectricity = 20)
|
||||
build_path = /obj/item/organ/heart/ethereal
|
||||
category = list("ethereal")
|
||||
|
||||
/datum/design/armblade
|
||||
name = "Arm Blade"
|
||||
id = "armblade"
|
||||
@@ -107,3 +221,68 @@
|
||||
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 75)
|
||||
build_path = /obj/item/melee/synthetic_arm_blade
|
||||
category = list("other","emagged")
|
||||
|
||||
/// Design disks and designs - for adding limbs and organs to the limbgrower.
|
||||
/obj/item/disk/design_disk/limbs
|
||||
name = "Limb Design Disk"
|
||||
desc = "A disk containing limb and organ designs for a limbgrower."
|
||||
icon_state = "datadisk1"
|
||||
/// List of all limb designs this disk contains.
|
||||
var/list/limb_designs = list()
|
||||
|
||||
/obj/item/disk/design_disk/limbs/Initialize()
|
||||
. = ..()
|
||||
max_blueprints = limb_designs.len
|
||||
for(var/design in limb_designs)
|
||||
var/datum/design/new_design = design
|
||||
blueprints += new new_design
|
||||
|
||||
/datum/design/limb_disk
|
||||
name = "Limb Design Disk"
|
||||
desc = "Contains designs for various limbs."
|
||||
id = "limbdesign_parent"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(/datum/material/iron = 300, /datum/material/glass = 100)
|
||||
build_path = /obj/item/disk/design_disk/limbs
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
|
||||
|
||||
/obj/item/disk/design_disk/limbs/felinid
|
||||
name = "Felinid Limb Design Disk"
|
||||
limb_designs = list(/datum/design/cat_tail, /datum/design/cat_ears)
|
||||
|
||||
/datum/design/limb_disk/felinid
|
||||
name = "Felinid Limb Design Disk"
|
||||
desc = "Contains designs for felinid bodyparts for the limbgrower - Felinid ears and tail."
|
||||
id = "limbdesign_felinid"
|
||||
build_path = /obj/item/disk/design_disk/limbs/felinid
|
||||
|
||||
/obj/item/disk/design_disk/limbs/lizard
|
||||
name = "Lizard Limb Design Disk"
|
||||
limb_designs = list(/datum/design/lizard_tail, /datum/design/lizard_tongue, /datum/design/digi_leftleg, /datum/design/digi_rightleg)
|
||||
|
||||
/datum/design/limb_disk/lizard
|
||||
name = "Lizard Limb Design Disk"
|
||||
desc = "Contains designs for lizard bodyparts for the limbgrower - Lizard tongue, tail, and digitigrade legs."
|
||||
id = "limbdesign_lizard"
|
||||
build_path = /obj/item/disk/design_disk/limbs/lizard
|
||||
|
||||
/obj/item/disk/design_disk/limbs/plasmaman
|
||||
name = "Plasmaman Limb Design Disk"
|
||||
limb_designs = list(/datum/design/plasmaman_stomach, /datum/design/plasmaman_liver, /datum/design/plasmaman_lungs, /datum/design/plasmaman_tongue)
|
||||
|
||||
/datum/design/limb_disk/plasmaman
|
||||
name = "Plasmaman Limb Design Disk"
|
||||
desc = "Contains designs for plasmaman organs for the limbgrower - Plasmaman tongue, liver, stomach, and lungs."
|
||||
id = "limbdesign_plasmaman"
|
||||
build_path = /obj/item/disk/design_disk/limbs/plasmaman
|
||||
|
||||
/obj/item/disk/design_disk/limbs/ethereal
|
||||
name = "Ethereal Limb Design Disk"
|
||||
limb_designs = list(/datum/design/ethereal_stomach, /datum/design/ethereal_tongue)
|
||||
|
||||
/datum/design/limb_disk/ethereal
|
||||
name = "Ethereal Limb Design Disk"
|
||||
desc = "Contains designs for ethereal organs for the limbgrower - Ethereal tongue and stomach."
|
||||
id = "limbdesign_ethereal"
|
||||
build_path = /obj/item/disk/design_disk/limbs/ethereal
|
||||
|
||||
@@ -82,6 +82,15 @@
|
||||
required_experiments = list(/datum/experiment/scanning/points/slime/easy)
|
||||
discount_experiments = list(/datum/experiment/scanning/random/material/meat = 4000) //Big discount to reinforce doing it.
|
||||
|
||||
/datum/techweb_node/xenoorgan_biotech
|
||||
id = "xenoorgan_bio"
|
||||
display_name = "Xeno-organ Biology"
|
||||
description = "Plasmaman, Ethereals, Lizardpeople... What makes our non-human crewmembers tick?"
|
||||
prereq_ids = list("adv_biotech")
|
||||
design_ids = list("limbdesign_felinid", "limbdesign_lizard", "limbdesign_plasmaman", "limbdesign_ethereal")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 6500)
|
||||
discount_experiments = list(/datum/experiment/scanning/random/cytology/easy = 1000, /datum/experiment/scanning/points/slime/expert = 5000)
|
||||
|
||||
/datum/techweb_node/bio_process
|
||||
id = "bio_process"
|
||||
display_name = "Biological Processing"
|
||||
|
||||
@@ -81,6 +81,10 @@
|
||||
new_tail.tail_type = tail_type
|
||||
new_tail.spines = spines
|
||||
|
||||
/obj/item/organ/tail/lizard/fake
|
||||
name = "fabricated lizard tail"
|
||||
desc = "A fabricated severed lizard tail. This one's made of synthflesh. Probably not usable for lizard wine."
|
||||
|
||||
/obj/item/organ/tail/monkey
|
||||
name = "monkey tail"
|
||||
desc = "A severed monkey tail. Does not look like a banana."
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import { useBackend, useSharedState } from '../backend';
|
||||
import { Box, Button, Dimmer, Icon, LabeledList, Section, Tabs } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const Limbgrower = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
reagents = [],
|
||||
total_reagents,
|
||||
max_reagents,
|
||||
categories = [],
|
||||
busy,
|
||||
} = data;
|
||||
const [tab, setTab] = useSharedState(
|
||||
context, 'category', categories[0]?.name);
|
||||
const designList = categories
|
||||
.find(category => category.name === tab)
|
||||
?.designs;
|
||||
|
||||
return (
|
||||
<Window
|
||||
title="Limb Grower"
|
||||
width={400}
|
||||
height={550}>
|
||||
{!!busy && (
|
||||
<Dimmer fontSize="32px">
|
||||
<Icon name="cog" spin={1} />
|
||||
{' Building...'}
|
||||
</Dimmer>
|
||||
)}
|
||||
<Window.Content scrollable>
|
||||
<Section title="Reagents">
|
||||
<Box mb={1}>
|
||||
{total_reagents} / {max_reagents} reagent capacity used.
|
||||
</Box>
|
||||
<LabeledList>
|
||||
{reagents.map(reagent => (
|
||||
<LabeledList.Item
|
||||
key={reagent.reagent_name}
|
||||
label={reagent.reagent_name}
|
||||
buttons={(
|
||||
<Button.Confirm
|
||||
textAlign="center"
|
||||
width="120px"
|
||||
content="Remove Reagent"
|
||||
color="bad"
|
||||
onClick={() => act('empty_reagent', {
|
||||
reagent_type: reagent.reagent_type,
|
||||
})} />
|
||||
)}>
|
||||
{reagent.reagent_amount}u
|
||||
</LabeledList.Item>
|
||||
))}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section title="Designs">
|
||||
<Tabs>
|
||||
{categories.map(category => (
|
||||
<Tabs.Tab
|
||||
fluid
|
||||
key={category.name}
|
||||
selected={tab === category.name}
|
||||
onClick={() => setTab(category.name)}>
|
||||
{category.name}
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
</Tabs>
|
||||
<LabeledList>
|
||||
{designList.map(design => (
|
||||
<LabeledList.Item
|
||||
key={design.name}
|
||||
label={design.name}
|
||||
buttons={(
|
||||
<Button
|
||||
content="Make"
|
||||
color="good"
|
||||
onClick={() => act('make_limb', {
|
||||
design_id: design.id,
|
||||
active_tab: design.parent_category,
|
||||
})} />
|
||||
)}>
|
||||
{design.needed_reagents.map(reagent => (
|
||||
<Box key={reagent.name}>
|
||||
{reagent.name}: {reagent.amount}u
|
||||
</Box>
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
))}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user