[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 19:12:11 +00:00
committed by GitHub
co-authored by Time-Green
parent a175be4500
commit 25092a85bb
11 changed files with 291 additions and 110 deletions
+33 -7
View File
@@ -21,9 +21,13 @@
var/recipient_reagents_holder
///How do we apply the new reagents to the receiver? Generally doesn't matter, but some stuff, like people, does care if its injected or whatevs
var/methods
///What color is our demand connect? Also it's not auto-colored so you'll have to make new sprites if its anything other than red, blue, yellow or green
var/demand_color = "red"
///What color is our supply connect? Also, refrain from pointlessly using non-standard colors unless it's really funny or something
var/supply_color = "blue"
///turn_connects is for wheter or not we spin with the object to change our pipes
/datum/component/plumbing/Initialize(start=TRUE, _turn_connects=TRUE, _ducting_layer)
/datum/component/plumbing/Initialize(start=TRUE, _turn_connects=TRUE, _ducting_layer, datum/reagents/custom_receiver)
if(!ismovable(parent))
return COMPONENT_INCOMPATIBLE
@@ -31,12 +35,16 @@
ducting_layer = ducting_layer
var/atom/movable/AM = parent
if(!AM.reagents)
if(!AM.reagents && !custom_receiver)
return COMPONENT_INCOMPATIBLE
reagents = AM.reagents
turn_connects = _turn_connects
recipient_reagents_holder = AM.reagents
if(custom_receiver)
recipient_reagents_holder = custom_receiver
else
recipient_reagents_holder = AM.reagents
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED,COMSIG_PARENT_PREQDELETED), .proc/disable)
RegisterSignal(parent, list(COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH), .proc/toggle_active)
@@ -145,9 +153,9 @@
var/color
var/direction
if(D & initial(demand_connects))
color = "red" //red because red is mean and it takes
color = demand_color
else if(D & initial(supply_connects))
color = "blue" //blue is nice and gives
color = supply_color
else
continue
@@ -164,10 +172,10 @@
direction = "west"
if(turn_connects)
I = image('icons/obj/plumbing/plumbers.dmi', "[direction]-[color]", layer = AM.layer - 1)
I = image('icons/obj/plumbing/connects.dmi', "[direction]-[color]", layer = AM.layer - 1)
else
I = image('icons/obj/plumbing/plumbers.dmi', "[direction]-[color]-s", layer = AM.layer - 1) //color is not color as in the var, it's just the name of the icon_state
I = image('icons/obj/plumbing/connects.dmi', "[direction]-[color]-s", layer = AM.layer - 1) //color is not color as in the var, it's just the name of the icon_state
I.dir = D
I.pixel_x = duct_x
@@ -308,3 +316,21 @@
/datum/component/plumbing/tank
demand_connects = WEST
supply_connects = EAST
#define READY 2
///Baby component for the buffer plumbing machine
/datum/component/plumbing/buffer
demand_connects = WEST
supply_connects = EAST
/datum/component/plumbing/buffer/Initialize(start=TRUE, _turn_connects=TRUE, _ducting_layer, datum/reagents/custom_receiver)
if(!istype(parent, /obj/machinery/plumbing/buffer))
return COMPONENT_INCOMPATIBLE
return ..()
/datum/component/plumbing/buffer/can_give(amount, reagent, datum/ductnet/net)
var/obj/machinery/plumbing/buffer/buffer = parent
return (buffer.mode == READY) ? ..() : FALSE
#undef READY
@@ -1,6 +1,6 @@
/datum/component/plumbing/reaction_chamber
demand_connects = WEST
supply_connects = EAST
demand_connects = NORTH
supply_connects = SOUTH
/datum/component/plumbing/reaction_chamber/Initialize(start=TRUE, _turn_connects=TRUE)
. = ..()
@@ -10,25 +10,18 @@
/datum/component/plumbing/reaction_chamber/can_give(amount, reagent, datum/ductnet/net)
. = ..()
var/obj/machinery/plumbing/reaction_chamber/RC = parent
if(!. || !RC.emptying)
if(!. || !RC.emptying || reagents.is_reacting == TRUE)
return FALSE
/datum/component/plumbing/reaction_chamber/send_request(dir)
var/obj/machinery/plumbing/reaction_chamber/RC = parent
if(RC.emptying || !LAZYLEN(RC.required_reagents))
if(RC.emptying)
return
process_request(amount = min(MACHINE_REAGENT_TRANSFER, RC.target_volume - reagents.total_volume), dir = dir)
if(RC.target_volume > round(reagents.total_volume, CHEMICAL_VOLUME_ROUNDING)) //not enough yet
return
for(var/RT in RC.required_reagents)
var/has_reagent = FALSE
for(var/A in reagents.reagent_list)
var/datum/reagent/RD = A
if(RT == RD.type)
has_reagent = TRUE
if(RD.volume < RC.required_reagents[RT])
process_request(min(RC.required_reagents[RT] - RD.volume, MACHINE_REAGENT_TRANSFER) , RT, dir)
return
if(!has_reagent)
process_request(min(RC.required_reagents[RT], MACHINE_REAGENT_TRANSFER), RT, dir)
return
reagents.flags &= ~NO_REACT
reagents.handle_reactions()
@@ -37,8 +30,24 @@
//everything for every chemical removed, wich isn't a good option either.
RC.on_reagent_change(reagents) //We need to check it now, because some reactions leave nothing left.
///Special connect that we currently use for reaction chambers. Being used so we can keep certain inputs seperate, like into a special internal acid container
/datum/component/plumbing/acidic_input
demand_connects = WEST
demand_color = "yellow"
ducting_layer = SECOND_DUCT_LAYER
/datum/component/plumbing/acidic_input/send_request(dir)
process_request(amount = MACHINE_REAGENT_TRANSFER, reagent = /datum/reagent/reaction_agent/acidic_buffer, dir = dir)
///Special connect that we currently use for reaction chambers. Being used so we can keep certain inputs seperate, like into a special internal base container
/datum/component/plumbing/alkaline_input
demand_connects = EAST
demand_color = "green"
ducting_layer = SECOND_DUCT_LAYER
/datum/component/plumbing/alkaline_input/send_request(dir)
process_request(amount = MACHINE_REAGENT_TRANSFER, reagent = /datum/reagent/reaction_agent/basic_buffer, dir = dir)
/datum/component/plumbing/reaction_chamber/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net)
if(reagents.is_reacting == TRUE) //Let the thing react in peace
return
return ..()
+2 -1
View File
@@ -1021,9 +1021,10 @@ RLD
/obj/machinery/plumbing/tank = 20,
/obj/machinery/plumbing/synthesizer = 15,
/obj/machinery/plumbing/reaction_chamber = 15,
/obj/machinery/plumbing/acclimator = 10,
/obj/machinery/plumbing/buffer = 10,
/obj/machinery/plumbing/pill_press = 20,
//Above are the most common machinery which is shown on the first cycle. Keep new additions below THIS line
/obj/machinery/plumbing/acclimator = 10,
/obj/machinery/plumbing/bottler = 50,
/obj/machinery/plumbing/disposer = 10,
/obj/machinery/plumbing/fermenter = 30,
@@ -76,8 +76,7 @@
var/target_layer = DUCT_LAYER_DEFAULT
///Assoc list for possible layers
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/plunger/attack_obj(obj/O, mob/living/user, params)
if(layer_mode)
+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"]))