Files
Yogstation/code/game/machinery/limbgrower.dm
SapphicOverload b13ed70f05 Replaces intents with combat mode (#21883)
* it begins

* Update gun.dm

* misc fixes

* Update gun.dm

* more fixes

* Update lightning_flow.dm

* i may be stupid

* Update suicide.dm

* fix mech strafing

* Update mecha.dm

* let there be qol

* ghost stuff

* Update screen_clockwork.dmi

* does the stuff

* stuff

* Update worldbreaker.dm

* moltial arts

* Update worldbreaker.dm

* CRITICAL FIX

* mech stuff

* Update tables_racks.dm

* stuff

* fix seismic arm

* buster/seismic arm fix 2

* saber + lockers

* stuff

* hand tele and pre_attack_secondary

* more right click acts

* Update closets.dm

* who did this

* heck

* Update mob.dm

* Update items.dm

* darkspawn fix

* fixes wound healing

* Update item_attack.dm

* minor qol stuff

* Update kinetic_crusher.dm

* Update kinetic_crusher.dm

* runtime fix

* Update kinetic_crusher.dm

* Update screen_plasmafire.dmi

* stuff

* syringes

* i am very silly

* death to /obj/item/toolset_handler

* Update assembly.dm

* surgery fix + hypo stuff

* mantis fix

* gas harpoon

* atmos machines

---------

Co-authored-by: Molti <gamingjoelouis@gmail.com>
2024-05-09 13:50:24 -05:00

316 lines
12 KiB
Plaintext

/// 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."
icon = 'icons/obj/machines/limbgrower.dmi'
icon_state = "limbgrower_idleoff"
density = TRUE
use_power = IDLE_POWER_USE
idle_power_usage = 10
active_power_usage = 100
circuit = /obj/item/circuitboard/machine/limbgrower
/// The category of limbs we're browing in our UI.
var/selected_category = "human"
/// If we're currently printing something.
var/busy = FALSE
/// 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
/// All the categories of organs we can print.
var/list/categories = list("human", "lizard", "moth", "plasmaman", "ethereal", "polysmorph", "other")
//yogs grower a little different because we're going to allow meats to be converted to synthflesh because hugbox
var/list/accepted_biomass = list(
/obj/item/reagent_containers/food/snacks/meat/slab/monkey = 25,
/obj/item/reagent_containers/food/snacks/meat/slab/synthmeat = 34,
/obj/item/reagent_containers/food/snacks/meat/slab/human = 50,
/obj/item/stack/sheet/animalhide/human = 50
)
var/biomass_per_slab = 20
/obj/machinery/limbgrower/Initialize(mapload)
create_reagents(100, OPENCONTAINER)
stored_research = new /datum/techweb/specialized/autounlocking/limbgrower
. = ..()
/obj/machinery/limbgrower/ui_interact(mob/user, datum/tgui/ui)
. = ..()
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Limbgrower")
ui.open()
/obj/machinery/limbgrower/ui_state(mob/user)
return GLOB.physical_state
/obj/machinery/limbgrower/ui_data(mob/user)
var/list/data = list()
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/our_beaker in component_parts)
reagents.trans_to(our_beaker, our_beaker.reagents.maximum_volume)
..()
//start yog
/obj/machinery/limbgrower/proc/handle_biomass(user_item, biomass, user) // updates the value
if(reagents.total_volume >= reagents.maximum_volume)
to_chat(user, span_notice("[src]'s reagent containers are full!.</span>"))
busy = FALSE
return // if reagent container is already past the max, stop this from working
else
to_chat(user, span_notice("You insert [user_item] into [src].</span>")) // feel free to fill it.
playsound(loc, 'sound/machines/blender.ogg', 50, TRUE)
qdel(user_item)
use_power(biomass * production_coefficient * 10)
sleep(min(10 SECONDS, biomass * production_coefficient))
reagents.add_reagent(/datum/reagent/medicine/synthflesh, biomass)
busy = FALSE
return
//end yog (please)
/obj/machinery/limbgrower/attackby(obj/item/user_item, mob/living/user, params)
if (busy)
to_chat(user, span_alert("The Limb Grower is busy. Please wait for completion of previous operation."))
return
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, 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
//yogs start hugbox code
var/biomass = 0
if(user_item.type in accepted_biomass)
busy = TRUE
if(istype(user_item, /obj/item/stack/sheet))
var/obj/item/stack/S = user_item
biomass += S.amount * accepted_biomass[user_item.type] //we need special code because stacks are cringe
handle_biomass(user_item, biomass, user)
else
biomass += accepted_biomass[user_item.type] // changes biomass to whatever slab it picked
handle_biomass(user_item, biomass, user)
else if(istype(user_item, /obj/item/reagent_containers/food/snacks/meat/slab)) // If no special slab was picked it reverts to var/biomass_per_slab
busy = TRUE
biomass += biomass_per_slab
handle_biomass(user_item, biomass, user)
//end yog hugbox code
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/ui_act(action, list/params)
. = ..()
if(.)
return
if (busy)
to_chat(usr, "<span class='danger'>The limb grower is busy. Please wait for completion of previous operation.</span>")
return
switch(action)
if("empty_reagent")
reagents.del_reagent(text2path(params["reagent_type"]))
. = TRUE
if("make_limb")
being_built = stored_research.isDesignResearchedID(params["design_id"])
if(!being_built)
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
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
power = max(2000, (power + consumed_reagents_list[reagent_id]))
busy = TRUE
use_power(power)
flick("limbgrower_fill",src)
icon_state = "limbgrower_idleon"
selected_category = params["active_tab"]
addtimer(CALLBACK(src, PROC_REF(build_item), consumed_reagents_list), production_speed * production_coefficient)
. = TRUE
return
/*
* 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)
/// 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 specias name and body zone
limb.icon_state = "[selected_category]_[limb.body_zone]"
limb.name = "synthetic [selected_category] [parse_zone(limb.body_zone)]"
limb.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]."
limb.species_id = selected_category
limb.update_icon_dropped()
limb.original_owner = "limb grower" //prevents updating the icon, so a lizard arm on a human stays a lizard arm etc.
/obj/machinery/limbgrower/RefreshParts()
reagents.maximum_volume = 0
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 reagents.<br>Reagent consumption rate at <b>[production_coefficient * 100]%</b>.</span>"
/*
* 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, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
return FALSE
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_warning("A warning flashes onto the screen, stating that safety overrides have been deactivated!"))
obj_flags |= EMAGGED
update_static_data(user)
return TRUE