[MIRROR] Reworks plumbing reaction chamber, purity support (#3763)

* Rework plumbing reaction chamber, purity support (#57071)

Currently does four things:

The reaction chamber now supports purity! It has a yellow (acid) and green (basic) input for buffers, aswell as a setting to automatically dispense either an acidic or alkalic buffer when above/below a certain pH! Now you can make a 100% pure meth factory! The buffer connects are on an alternate layer.

Probably going to be less loved, but I removed the reaction chambers ability to pick reagents from the net. Instead, it will pull untill a set volume is reached. Then it'll start reacting. While this means that players will have to be more creative and use a wider array of machinery.

Also new machine! Buffers! They fill the hole that reagent chambers left. They can be set with a threshold volume and will only start putting out chems when ALL of their neighbouring buffers also are also above this threshold. You might have a lot of one chem and have to wait for a more specialized chem to be produced, and with the cleverness of reaction chambers gone, bufferers can do just that: wait.

I also removed all but two layers. I want to make it obvious what layer the buffer connects are on. Also layers are basically unusable and I'm gonna give them a rework very soon. I'll put the things back in then when they actually have something to contribute

* Reworks plumbing reaction chamber, purity support

Co-authored-by: Time-Green <timkoster1@hotmail.com>
This commit is contained in:
SkyratBot
2021-03-02 20:12:11 +01:00
committed by GitHub
parent a175be4500
commit 25092a85bb
11 changed files with 291 additions and 110 deletions
+5 -6
View File
@@ -89,10 +89,10 @@ All the important duct code:
if(istype(AM, /obj/machinery/duct))
return connect_duct(AM, direction, ignore_color)
var/plumber = AM.GetComponent(/datum/component/plumbing)
if(!plumber)
return
return connect_plumber(plumber, direction)
for(var/plumber in AM.GetComponents(/datum/component/plumbing))
if(!plumber) //apparently yes it will be null hahahaasahsdvashufv
return
. += connect_plumber(plumber, direction) //so that if one is true, all is true. beautiful.
///connect to a duct
/obj/machinery/duct/proc/connect_duct(obj/machinery/duct/D, direction, ignore_color)
@@ -402,8 +402,7 @@ All the important duct code:
///Default layer of our duct
var/duct_layer = "Default Layer"
///Assoc index with all the available layers. yes five might be a bit much. Colors uses a global by the way
var/list/layers = list("First Layer" = FIRST_DUCT_LAYER, "Second Layer" = SECOND_DUCT_LAYER, "Default Layer" = DUCT_LAYER_DEFAULT,
"Fourth Layer" = FOURTH_DUCT_LAYER, "Fifth Layer" = FIFTH_DUCT_LAYER)
var/list/layers = list("Alternate Layer" = SECOND_DUCT_LAYER, "Default Layer" = DUCT_LAYER_DEFAULT)
/obj/item/stack/ducts/examine(mob/user)
. = ..()
@@ -0,0 +1,122 @@
#define UNREADY 0
#define IDLE 1
#define READY 2
/obj/machinery/plumbing/buffer
name = "automatic buffer"
desc = "A chemical holding tank that waits for neighbouring automatic buffers to complete before allowing a withdrawal. Connect/reset by screwdrivering"
icon_state = "buffer"
buffer = 200
var/datum/buffer_net/buffer_net
var/activation_volume = 100
var/mode
/obj/machinery/plumbing/buffer/Initialize(mapload, bolt)
. = ..()
AddComponent(/datum/component/plumbing/buffer, bolt)
/obj/machinery/plumbing/buffer/create_reagents(max_vol, flags)
. = ..()
RegisterSignal(reagents, list(COMSIG_REAGENTS_ADD_REAGENT, COMSIG_REAGENTS_NEW_REAGENT, COMSIG_REAGENTS_REM_REAGENT, COMSIG_REAGENTS_DEL_REAGENT, COMSIG_REAGENTS_CLEAR_REAGENTS, COMSIG_REAGENTS_REACTED), .proc/on_reagent_change)
RegisterSignal(reagents, COMSIG_PARENT_QDELETING, .proc/on_reagents_del)
/// Handles properly detaching signal hooks.
/obj/machinery/plumbing/buffer/proc/on_reagents_del(datum/reagents/reagents)
SIGNAL_HANDLER
UnregisterSignal(reagents, list(COMSIG_REAGENTS_ADD_REAGENT, COMSIG_REAGENTS_NEW_REAGENT, COMSIG_REAGENTS_REM_REAGENT, COMSIG_REAGENTS_DEL_REAGENT, COMSIG_REAGENTS_CLEAR_REAGENTS, COMSIG_REAGENTS_REACTED, COMSIG_PARENT_QDELETING))
return NONE
/obj/machinery/plumbing/buffer/proc/on_reagent_change()
if(!buffer_net)
return
if(reagents.total_volume >= activation_volume && mode == UNREADY)
mode = IDLE
buffer_net.check_active()
else if(reagents.total_volume < activation_volume && mode != UNREADY)
mode = UNREADY
buffer_net.check_active()
/obj/machinery/plumbing/buffer/update_icon()
. = ..()
icon_state = initial(icon_state)
if(buffer_net)
switch(mode)
if(UNREADY)
icon_state += "_red"
if(IDLE)
icon_state += "_yellow"
if(READY)
icon_state += "_green"
/obj/machinery/plumbing/buffer/proc/attempt_connect()
for(var/direction in GLOB.cardinals)
var/turf/T = get_step(src, direction)
for(var/atom/movable/movable in T)
if(istype(movable, /obj/machinery/plumbing/buffer))
var/obj/machinery/plumbing/buffer/neighbour = movable
if(neighbour.buffer_net != buffer_net)
neighbour.buffer_net?.destruct()
//we could put this on a proc, but its so simple I dont think its worth the overhead
buffer_net.buffer_list += neighbour
neighbour.buffer_net = buffer_net
neighbour.attempt_connect() //technically this would runtime if you made about 200~ buffers
add_overlay(icon_state + "_alert")
addtimer(CALLBACK(src, /atom/.proc/cut_overlay, icon_state + "_alert"), 20)
/obj/machinery/plumbing/buffer/attack_hand_secondary(mob/user, modifiers)
. = ..()
var/new_volume = input(user, "Enter new activation threshold", "Beepityboop", activation_volume) as num|null
if(!new_volume)
return
activation_volume = round(clamp(new_volume, 0, buffer))
to_chat(user, "<span class='notice'>New activation threshold is now [activation_volume].</span>")
/obj/machinery/plumbing/buffer/attackby(obj/item/item, mob/user, params)
if(item.tool_behaviour == TOOL_SCREWDRIVER)
to_chat(user, "<span class='notice'>You reset the automatic buffer.</span>")
//reset the net
buffer_net?.destruct()
buffer_net = new()
LAZYADD(buffer_net.buffer_list, src)
attempt_connect()
else
return . = ..()
/obj/machinery/plumbing/buffer/doMove(destination)
. = ..()
buffer_net?.destruct()
/datum/buffer_net
var/list/obj/machinery/plumbing/buffer/buffer_list
/datum/buffer_net/proc/destruct()
for(var/obj/machinery/plumbing/buffer/buffer in buffer_list)
buffer.buffer_net = null
buffer_list.Cut()
qdel(src)
/datum/buffer_net/proc/check_active()
var/ready = TRUE
for(var/obj/machinery/plumbing/buffer/buffer in buffer_list)
if(buffer.mode == UNREADY)
ready = FALSE
break
for(var/obj/machinery/plumbing/buffer/buffer in buffer_list)
if(buffer.mode == READY && !ready)
buffer.mode = IDLE
else if(buffer.mode == IDLE && ready)
buffer.mode = READY
buffer.update_icon()
#undef UNREADY
#undef IDLE
#undef READY
@@ -6,10 +6,12 @@
buffer = 200
reagent_flags = TRANSPARENT | NO_REACT
/**list of set reagents that the reaction_chamber allows in, and must all be present before mixing is enabled.
* example: list(/datum/reagent/water = 20, /datum/reagent/fuel/oil = 50)
*/
var/list/required_reagents = list()
///At what volume do we start reacting?
var/target_volume = 200
///If above this pH, we start dumping buffer into it
var/acidic_limit = 9
///If below this pH, we start dumping buffer into it
var/alkaline_limit = 5
///our reagent goal has been reached, so now we lock our inputs and start emptying
var/emptying = FALSE
@@ -17,11 +19,21 @@
var/target_temperature = 300
///cool/heat power
var/heater_coefficient = 0.05 //same lvl as acclimator
///Beaker that holds the acidic buffer. I don't want to deal with snowflaking so it's just a seperate thing. It's a small (50u) beaker
var/obj/item/reagent_containers/glass/beaker/acidic_beaker
///beaker that holds the alkaline buffer.
var/obj/item/reagent_containers/glass/beaker/alkaline_beaker
/obj/machinery/plumbing/reaction_chamber/Initialize(mapload, bolt)
. = ..()
AddComponent(/datum/component/plumbing/reaction_chamber, bolt)
acidic_beaker = new (src)
alkaline_beaker = new (src)
AddComponent(/datum/component/plumbing/acidic_input, bolt, custom_receiver = acidic_beaker)
AddComponent(/datum/component/plumbing/alkaline_input, bolt, custom_receiver = alkaline_beaker)
/obj/machinery/plumbing/reaction_chamber/create_reagents(max_vol, flags)
. = ..()
RegisterSignal(reagents, list(COMSIG_REAGENTS_REM_REAGENT, COMSIG_REAGENTS_DEL_REAGENT, COMSIG_REAGENTS_CLEAR_REAGENTS, COMSIG_REAGENTS_REACTED), .proc/on_reagent_change)
@@ -43,6 +55,11 @@
return NONE
/obj/machinery/plumbing/reaction_chamber/process(delta_time)
if(!reagents.is_reacting && reagents.ph < alkaline_limit)
alkaline_beaker.reagents.trans_to(reagents, 1 * delta_time)
if(!reagents.is_reacting && reagents.ph > acidic_limit)
acidic_beaker.reagents.trans_to(reagents, 1 * delta_time)
if(!emptying) //suspend heating/cooling during emptying phase
reagents.adjust_thermal_energy((target_temperature - reagents.chem_temp) * heater_coefficient * delta_time * SPECIFIC_HEAT_DEFAULT * reagents.total_volume) //keep constant with chem heater
reagents.handle_reactions()
@@ -62,17 +79,15 @@
/obj/machinery/plumbing/reaction_chamber/ui_data(mob/user)
var/list/data = list()
var/list/text_reagents = list()
for(var/A in required_reagents) //make a list where the key is text, because that looks alot better in the ui than a typepath
var/datum/reagent/R = A
text_reagents[initial(R.name)] = required_reagents[R]
data["reagents"] = text_reagents
data["emptying"] = emptying
data["temperature"] = round(reagents.chem_temp, 0.1)
data["ph"] = round(reagents.ph, 0.01)
data["targetTemp"] = target_temperature
data["isReacting"] = reagents.is_reacting
data["reagentQuantity"] = target_volume
data["reagentAcidic"] = acidic_limit
data["reagentAlkaline"] = alkaline_limit
return data
/obj/machinery/plumbing/reaction_chamber/ui_act(action, params)
@@ -81,16 +96,6 @@
return
. = TRUE
switch(action)
if("remove")
var/reagent = get_chem_id(params["chem"])
if(reagent)
required_reagents.Remove(reagent)
if("add")
var/input_reagent = get_chem_id(params["chem"])
if(input_reagent && !required_reagents.Find(input_reagent))
var/input_amount = text2num(params["amount"])
if(input_amount)
required_reagents[input_reagent] = input_amount
if("temperature")
var/target = params["target"]
if(text2num(target) != null)
@@ -98,3 +103,10 @@
. = TRUE
if(.)
target_temperature = clamp(target, 0, 1000)
if("volume")
target_volume = round(text2num(params["target"]))
if("acidic")
acidic_limit = round(text2num(params["target"]))
if("alkaline")
alkaline_limit = round(text2num(params["target"]))