Cytology without plumbing (#84235)

## About The Pull Request

Makes Growing Vat work as a normal machine akin hydrotray. 
Doesn't need plunger to clear reagents, doesn't need plumbing to input
reagents.
Still has the plumbing port, but can be used without it.
Also made the examine text a bit more compact.

Removed science plumbing RCD from the game.
Removed plumbing tools from cytology equipment, and added a protein
powder jug instead.


![image](https://github.com/tgstation/tgstation/assets/3625094/40d2d33e-f78d-4dc9-96e6-4b0fd231035f)

Automatically fixes #84573

## Why It's Good For The Game

Plumbing was an unnecessary complication for Cytology.

Growing vat is a relatively simple machine that shouldn't require
plumbing knowledge.
Now it works more like hydrotray, and you can pour reagents directly,
and clear them out with a right click.

## Changelog

🆑
refactor: Vat grower is a normal machine now that doesn't need plumbing
qol: Cytology petri dish smartfridge starts with 3 random samples
add: Added protein powder condiment bottle, available in the cytology
supplies locker and the cargo pack
del: Removed science variant of plumbing RCD
fix: Fixed a bug when machines without stock parts didn't spawn frames
on deconstruction
fix: Fixed vat grower not growing
/🆑
This commit is contained in:
Andrew
2024-07-04 12:04:31 -07:00
committed by GitHub
parent 4426a74dcb
commit d4765c0657
32 changed files with 6893 additions and 6884 deletions
@@ -582,6 +582,16 @@
)
departmental_flags = DEPARTMENT_BITFLAG_SERVICE
/datum/design/board/vatgrower
name = "Growing Vat Board"
desc = "The circuit board for a growing vat."
id = "vatgrower"
build_path = /obj/item/circuitboard/machine/vatgrower
category = list(
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_RESEARCH
)
departmental_flags = DEPARTMENT_BITFLAG_SCIENCE
/datum/design/board/monkey_recycler
name = "Monkey Recycler Board"
desc = "The circuit board for a monkey recycler."
@@ -226,17 +226,6 @@
)
departmental_flags = DEPARTMENT_BITFLAG_SERVICE
/datum/design/plumbing_rcd_sci
name = "Research Plumbing Constructor"
id = "plumbing_rcd_sci"
build_type = PROTOLATHE | AWAY_LATHE
materials = list(/datum/material/iron =SHEET_MATERIAL_AMOUNT*37.5, /datum/material/glass =SHEET_MATERIAL_AMOUNT*18.75, /datum/material/plastic =HALF_SHEET_MATERIAL_AMOUNT)
build_path = /obj/item/construction/plumbing/research
category = list(
RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_PLUMBING
)
departmental_flags = DEPARTMENT_BITFLAG_SCIENCE
/datum/design/plumbing_rcd_service
name = "Service Plumbing Constructor"
id = "plumbing_rcd_service"
@@ -23,6 +23,7 @@
design_ids = list(
"limbgrower",
"pandemic",
"vatgrower",
"petri_dish",
"swab",
"biopsy_tool",
@@ -62,7 +62,6 @@
design_ids = list(
"plumbing_rcd",
"plumbing_rcd_service",
"plumbing_rcd_sci",
"plunger",
"fluid_ducts",
"meta_beaker",
@@ -1,7 +1,7 @@
///Tool capable of taking biological samples from mobs
/obj/item/biopsy_tool
name = "biopsy tool"
desc = "Don't worry, it won't sting."
desc = "Used to retrieve cell lines from organisms. Don't worry, it won't sting."
icon = 'icons/obj/science/vatgrowing.dmi'
icon_state = "biopsy"
worn_icon_state = "biopsy"
@@ -128,7 +128,5 @@
reqs = list(
/obj/item/stack/sheet/glass = 1,
/obj/item/stack/sheet/plastic = 1,
/obj/item/stock_parts/scanning_module = 1,
/obj/item/flashlight = 1,
)
category = CAT_CHEMISTRY
@@ -31,7 +31,7 @@
var/resulting_atom_count = 1
///Handles growth of the micro_organism. This only runs if the micro organism is in the growing vat. Reagents is the growing vats reagents
/datum/micro_organism/cell_line/proc/handle_growth(obj/machinery/plumbing/growing_vat/vat)
/datum/micro_organism/cell_line/proc/handle_growth(obj/machinery/vatgrower/vat)
if(!try_eat(vat.reagents))
return FALSE
growth = max(growth, growth + calculate_growth(vat.reagents, vat.biological_sample)) //Prevent you from having minus growth.
@@ -74,7 +74,7 @@
. -= virus_suspectibility
///Called once a cell line reaches 100 growth. Then we check if any cell_line is too far so we can perform an epic fail roll
/datum/micro_organism/cell_line/proc/finish_growing(obj/machinery/plumbing/growing_vat/vat)
/datum/micro_organism/cell_line/proc/finish_growing(obj/machinery/vatgrower/vat)
var/risk = 0 //Penalty for failure, goes up based on how much growth the other cell_lines have
for(var/datum/micro_organism/cell_line/cell_line in vat.biological_sample.micro_organisms)
@@ -90,7 +90,7 @@
succeed_growing(vat)
return TRUE
/datum/micro_organism/cell_line/proc/fuck_up_growing(obj/machinery/plumbing/growing_vat/vat)
/datum/micro_organism/cell_line/proc/fuck_up_growing(obj/machinery/vatgrower/vat)
vat.visible_message(span_warning("The biological sample in [vat] seems to have dissipated!"))
if(prob(50))
new /obj/effect/gibspawner/generic(get_turf(vat)) //Spawn some gibs.
@@ -98,7 +98,7 @@
return
QDEL_NULL(vat.biological_sample)
/datum/micro_organism/cell_line/proc/succeed_growing(obj/machinery/plumbing/growing_vat/vat)
/datum/micro_organism/cell_line/proc/succeed_growing(obj/machinery/vatgrower/vat)
var/datum/effect_system/fluid_spread/smoke/smoke = new
smoke.set_up(0, holder = vat, location = vat.loc)
smoke.start()
@@ -112,18 +112,18 @@
///Overriden to show more info like needs, supplementary and supressive reagents and also growth.
/datum/micro_organism/cell_line/get_details(show_details)
. += "[span_notice("[desc] - growth progress: [growth]%")]\n"
. += "[span_notice("[desc] - growth progress: [growth]%")]"
if(show_details)
. += return_reagent_text("It requires:", required_reagents)
. += return_reagent_text("It likes:", supplementary_reagents)
. += return_reagent_text("It hates:", suppressive_reagents)
. += "\n- " + return_reagent_text("Requires:", required_reagents)
. += "\n- " + return_reagent_text("Likes:", supplementary_reagents)
. += "\n- " + return_reagent_text("Hates:", suppressive_reagents)
///Return a nice list of all the reagents in a specific category with a specific prefix. This needs to be reworked because the formatting sucks ass.
/datum/micro_organism/cell_line/proc/return_reagent_text(prefix_text = "It requires:", list/reagentlist)
if(!reagentlist.len)
return
var/all_reagents_text
var/list/reagent_names = list()
for(var/i in reagentlist)
var/datum/reagent/reagent = i
all_reagents_text += " - [initial(reagent.name)]\n"
return span_notice("[prefix_text]\n[all_reagents_text]")
reagent_names += initial(reagent.name)
return span_notice("[prefix_text] [jointext(reagent_names, ", ")]")
@@ -31,7 +31,7 @@
return TRUE
///Call handle_growth on all our microorganisms.
/datum/biological_sample/proc/handle_growth(obj/machinery/plumbing/growing_vat/vat)
/datum/biological_sample/proc/handle_growth(obj/machinery/vatgrower/vat)
for(var/datum/micro_organism/cell_line/organism in micro_organisms) //Types because we don't grow viruses.
organism.handle_growth(vat)
@@ -450,7 +450,7 @@
virus_suspectibility = 0.5
resulting_atom = /mob/living/simple_animal/hostile/vatbeast
/datum/micro_organism/cell_line/vat_beast/succeed_growing(obj/machinery/plumbing/growing_vat/vat)
/datum/micro_organism/cell_line/vat_beast/succeed_growing(obj/machinery/vatgrower/vat)
. = ..()
qdel(vat)
@@ -476,11 +476,11 @@
virus_suspectibility = 0
/datum/micro_organism/cell_line/netherworld/succeed_growing(obj/machinery/plumbing/growing_vat/vat)
/datum/micro_organism/cell_line/netherworld/succeed_growing(obj/machinery/vatgrower/vat)
resulting_atom = pick(/mob/living/basic/creature, /mob/living/basic/migo, /mob/living/basic/blankbody) //i looked myself, pretty much all of them are reasonably strong and somewhat on the same level. except migo is the jackpot and the blank body is whiff.
return ..()
/datum/micro_organism/cell_line/clown/fuck_up_growing(obj/machinery/plumbing/growing_vat/vat)
/datum/micro_organism/cell_line/clown/fuck_up_growing(obj/machinery/vatgrower/vat)
vat.visible_message(span_warning("The biological sample in [vat] seems to have created something horrific!"))
var/mob/selected_mob = pick(list(/mob/living/basic/clown/mutant/slow, /mob/living/basic/clown/fleshclown))
@@ -656,7 +656,7 @@
virus_suspectibility = 0
resulting_atom = /obj/item/queen_bee/bought
/datum/micro_organism/cell_line/queen_bee/fuck_up_growing(obj/machinery/plumbing/growing_vat/vat) //we love job hazards
/datum/micro_organism/cell_line/queen_bee/fuck_up_growing(obj/machinery/vatgrower/vat) //we love job hazards
vat.visible_message(span_warning("You hear angry buzzing coming from the inside of the vat!"))
for(var/i in 1 to 5)
new /mob/living/basic/bee(get_turf(vat))
@@ -0,0 +1,182 @@
///Used to make mobs from microbiological samples. Grow grow grow.
/obj/machinery/vatgrower
name = "growing vat"
desc = "Tastes just like the chef's soup."
icon = 'icons/obj/science/vatgrowing.dmi'
icon_state = "growing_vat"
density = TRUE
pass_flags_self = PASSMACHINE | LETPASSTHROW
circuit = /obj/item/circuitboard/machine/vatgrower
use_power = NO_POWER_USE
///Soup container reagents
var/reagent_volume = 300
var/reagent_flags = OPENCONTAINER | DUNKABLE
///List of all microbiological samples in this soup.
var/datum/biological_sample/biological_sample
///If the vat will restart the sample upon completion
var/resampler_active = FALSE
/obj/machinery/vatgrower/Initialize(mapload, bolt, layer)
. = ..()
create_reagents(reagent_volume, reagent_flags)
AddComponent(/datum/component/simple_rotation)
AddComponent(/datum/component/plumbing/simple_demand)
var/static/list/hovering_item_typechecks = list(
/obj/item/petri_dish = list(
SCREENTIP_CONTEXT_LMB = "Add Sample",
),
/obj/item/reagent_containers = list(
SCREENTIP_CONTEXT_LMB = "Pour Reagents",
),
)
AddElement(/datum/element/contextual_screentip_item_typechecks, hovering_item_typechecks)
AddElement(/datum/element/contextual_screentip_bare_hands, lmb_text = "Toggle Resampler", rmb_text = "Flush Soup")
/obj/machinery/vatgrower/create_reagents(max_vol, flags)
. = ..()
RegisterSignals(reagents, list(COMSIG_REAGENTS_NEW_REAGENT, COMSIG_REAGENTS_ADD_REAGENT, COMSIG_REAGENTS_DEL_REAGENT, COMSIG_REAGENTS_REM_REAGENT), PROC_REF(on_reagent_change))
RegisterSignal(reagents, COMSIG_QDELETING, PROC_REF(on_reagents_del))
/// Handles properly detaching signal hooks.
/obj/machinery/vatgrower/proc/on_reagents_del(datum/reagents/reagents)
SIGNAL_HANDLER
UnregisterSignal(reagents, list(COMSIG_REAGENTS_NEW_REAGENT, COMSIG_REAGENTS_ADD_REAGENT, COMSIG_REAGENTS_DEL_REAGENT, COMSIG_REAGENTS_REM_REAGENT, COMSIG_QDELETING))
return NONE
///When we process, we make use of our reagents to try and feed the samples we have.
/obj/machinery/vatgrower/process(seconds_per_tick)
if(!is_operational)
return
if(!biological_sample)
return
if(biological_sample.handle_growth(src))
if(!prob(10))
return
playsound(loc, 'sound/effects/slosh.ogg', 25, TRUE)
audible_message(pick(list(span_notice("[src] grumbles!"), span_notice("[src] makes a splashing noise!"), span_notice("[src] sloshes!"))))
use_energy(active_power_usage * seconds_per_tick)
/obj/machinery/vatgrower/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
. = ..()
if(istype(tool, /obj/item/petri_dish))
return deposit_sample(user, tool)
/obj/machinery/vatgrower/screwdriver_act(mob/living/user, obj/item/tool)
. = ..()
if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool))
return ITEM_INTERACT_SUCCESS
/obj/machinery/vatgrower/crowbar_act(mob/living/user, obj/item/tool)
. = ..()
if(default_deconstruction_crowbar(tool))
return ITEM_INTERACT_SUCCESS
/obj/machinery/vatgrower/wrench_act(mob/living/user, obj/item/tool)
. = ..()
if(default_unfasten_wrench(user, tool))
return ITEM_INTERACT_SUCCESS
/obj/machinery/vatgrower/attack_hand(mob/living/user, list/modifiers)
. = ..()
playsound(src, 'sound/machines/click.ogg', 30, TRUE)
if(obj_flags & EMAGGED)
return
resampler_active = !resampler_active
balloon_alert(user, "resampler [resampler_active ? "activated" : "deactivated"]")
update_appearance()
/obj/machinery/vatgrower/attack_hand_secondary(mob/user, list/modifiers)
. = ..()
if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
return
if(!anchored)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
var/warning = tgui_alert(user, "Are you sure you want to empty the soup container?","Flush soup container?", list("Flush", "Cancel"))
if(warning == "Flush" && user.can_perform_action(src))
reagents.clear_reagents()
if(biological_sample)
QDEL_NULL(biological_sample)
balloon_alert(user, "container empty")
update_appearance()
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
///Creates a clone of the supplied sample and puts it in the vat
/obj/machinery/vatgrower/proc/deposit_sample(mob/user, obj/item/petri_dish/petri)
if(!petri.sample)
balloon_alert(user, "dish empty")
return ITEM_INTERACT_FAILURE
if(biological_sample)
balloon_alert(user, "already has a sample")
return ITEM_INTERACT_FAILURE
biological_sample = new
for(var/datum/micro_organism/m in petri.sample.micro_organisms)
biological_sample.micro_organisms += new m.type()
biological_sample.sample_layers = petri.sample.sample_layers
biological_sample.sample_color = petri.sample.sample_color
balloon_alert(user, "added sample")
playsound(src, 'sound/effects/bubbles.ogg', 50, TRUE)
update_appearance()
RegisterSignal(biological_sample, COMSIG_SAMPLE_GROWTH_COMPLETED, PROC_REF(on_sample_growth_completed))
return ITEM_INTERACT_SUCCESS
///Adds text for when there is a sample in the vat
/obj/machinery/vatgrower/examine(mob/user)
. = ..()
if(!biological_sample)
return
. += span_notice("It seems to have a sample in it!")
for(var/i in biological_sample.micro_organisms)
var/datum/micro_organism/MO = i
. += MO.get_details(HAS_TRAIT(user, TRAIT_RESEARCH_SCANNER))
/// Call update icon when reagents change to update the reagent content icons. Eats signal args.
/obj/machinery/vatgrower/proc/on_reagent_change(datum/reagents/holder, ...)
SIGNAL_HANDLER
update_appearance()
return NONE
///Adds overlays to show the reagent contents
/obj/machinery/vatgrower/update_overlays()
. = ..()
var/static/image/on_overlay
var/static/image/off_overlay
var/static/image/emissive_overlay
if(isnull(on_overlay))
on_overlay = iconstate2appearance(icon, "growing_vat_on")
off_overlay = iconstate2appearance(icon, "growing_vat_off")
emissive_overlay = emissive_appearance(icon, "growing_vat_glow", src, alpha = src.alpha)
. += emissive_overlay
if(is_operational)
if(resampler_active)
. += on_overlay
else
. += off_overlay
if(!reagents.total_volume)
return
var/reagentcolor = mix_color_from_reagents(reagents.reagent_list)
var/mutable_appearance/base_overlay = mutable_appearance(icon, "vat_reagent")
base_overlay.appearance_flags = RESET_COLOR
base_overlay.color = reagentcolor
. += base_overlay
if(biological_sample && is_operational)
var/mutable_appearance/bubbles_overlay = mutable_appearance(icon, "vat_bubbles")
. += bubbles_overlay
/obj/machinery/vatgrower/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
return FALSE
obj_flags |= EMAGGED
playsound(src, SFX_SPARKS, 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
balloon_alert(user, "resampling circuit overloaded")
flick("growing_vat_emagged", src)
return TRUE
/obj/machinery/vatgrower/proc/on_sample_growth_completed()
SIGNAL_HANDLER
if(resampler_active)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(playsound), get_turf(src), 'sound/effects/servostep.ogg', 100, 1), 1.5 SECONDS)
biological_sample.reset_sample()
return SPARE_SAMPLE
UnregisterSignal(biological_sample, COMSIG_SAMPLE_GROWTH_COMPLETED)