diff --git a/code/__defines/flags.dm b/code/__defines/flags.dm index 0bad588e678..7a8151ef7fd 100644 --- a/code/__defines/flags.dm +++ b/code/__defines/flags.dm @@ -32,6 +32,9 @@ /// This atom is queued for an overlay update. #define ATOM_AWAITING_OVERLAY_UPDATE (1<<5) +///The Reagent cannot be refilled +#define ATOM_REAGENTS_NO_REFILL (1<<6) + /* -- /turf/var/turf_flags -- */ diff --git a/code/game/atoms.dm b/code/game/atoms.dm index e63a02358aa..9e59e0f1ae3 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -129,6 +129,9 @@ var/global/list/pre_init_created_atoms // atom creation ordering means some stuf /atom/proc/is_open_container() return atom_flags & ATOM_REAGENTS_IS_OPEN +/atom/proc/can_refill() + return atom_flags & ~ATOM_REAGENTS_NO_REFILL + /*//Convenience proc to see whether a container can be accessed in a certain way. proc/can_subract_container() diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index a7ca3385ce0..93f81f97900 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -113,6 +113,9 @@ Class Procs: var/obj/item/circuitboard/circuit = null var/list/materials = list() //Exclusively used for machines that take materials - lathes, fabricators etc. Honestly overdue for a whole lathe/fab refactor at some point. + var/anchor_type = null //What type of object can be anchored to a machine + var/anchor_direction = null //The immediate directions an object can be anchored to a machine. If null, any direction is allowed. + var/speed_process = FALSE //If false, SSmachines. If true, SSfastprocess. required_dexterity = MOB_DEXTERITY_TOUCHSCREENS @@ -486,4 +489,4 @@ Class Procs: S.amount = round(materials[mat] / S.perunit) else qdel(S) //Prevents stacks smaller than 1 - return \ No newline at end of file + return diff --git a/code/modules/reagents/machinery/dispenser/reagent_tank.dm b/code/modules/reagents/machinery/dispenser/reagent_tank.dm index bfe7dc58114..ae8cdc6a36d 100644 --- a/code/modules/reagents/machinery/dispenser/reagent_tank.dm +++ b/code/modules/reagents/machinery/dispenser/reagent_tank.dm @@ -10,9 +10,12 @@ anchored = 0 pressure_resistance = 2*ONE_ATMOSPHERE + var/volume = 5000 + + var/has_hose = TRUE var/obj/item/hose_connector/input/active/InputSocket var/obj/item/hose_connector/output/active/OutputSocket - + atom_flags = ATOM_REAGENTS_NO_REFILL var/amount_per_transfer_from_this = 10 var/possible_transfer_amounts = list(10,25,50,100) @@ -20,25 +23,28 @@ src.add_fingerprint(user) /obj/structure/reagent_dispensers/Destroy() - QDEL_NULL(InputSocket) - QDEL_NULL(OutputSocket) + if(has_hose) + QDEL_NULL(InputSocket) + QDEL_NULL(OutputSocket) ..() /obj/structure/reagent_dispensers/Initialize() - var/datum/reagents/R = new/datum/reagents(5000) + var/datum/reagents/R = new/datum/reagents(volume) reagents = R R.my_atom = src if (!possible_transfer_amounts) src.verbs -= /obj/structure/reagent_dispensers/verb/set_APTFT - InputSocket = new(src) - InputSocket.carrier = src - OutputSocket = new(src) - OutputSocket.carrier = src - + if(has_hose) + InputSocket = new(src) + InputSocket.carrier = src + OutputSocket = new(src) + OutputSocket.carrier = src . = ..() + + /obj/structure/reagent_dispensers/examine(mob/user) . = ..() if(get_dist(user, src) <= 2) @@ -57,6 +63,9 @@ if (N) amount_per_transfer_from_this = N +/obj/structure/reagent_dispensers/blob_act() + qdel(src) + /obj/structure/reagent_dispensers/ex_act(severity) switch(severity) if(1.0) @@ -75,8 +84,6 @@ else return -/obj/structure/reagent_dispensers/blob_act() - qdel(src) diff --git a/code/modules/reagents/reagent_containers/_reagent_containers.dm b/code/modules/reagents/reagent_containers/_reagent_containers.dm index 322fe5389dc..078e4fb2002 100644 --- a/code/modules/reagents/reagent_containers/_reagent_containers.dm +++ b/code/modules/reagents/reagent_containers/_reagent_containers.dm @@ -22,6 +22,9 @@ src.verbs -= /obj/item/reagent_containers/verb/set_APTFT create_reagents(volume) +/obj/item/reagent_containers/on_reagent_change() + update_icon() + /obj/item/reagent_containers/attack_self(mob/user as mob) return @@ -38,12 +41,14 @@ return 0 if(!target.reagents || !target.reagents.total_volume) - to_chat(user, "[target] is empty.") - return 1 + if(target.can_refill()) + return 0 + else + to_chat(user, "[target] is empty.") + return 1 if(reagents && !reagents.get_free_space()) - to_chat(user, "[src] is full.") - return 1 + return 0 var/trans = target.reagents.trans_to_obj(src, target:amount_per_transfer_from_this) to_chat(user, "You fill [src] with [trans] units of the contents of [target].") @@ -98,12 +103,12 @@ return FALSE user.setClickCooldown(user.get_attack_speed(src)) //puts a limit on how fast people can eat/drink things - if(user == target) + if(user == target) self_feed_message(user) reagents.trans_to_mob(user, issmall(user) ? CEILING(amount_per_transfer_from_this/2, 1) : amount_per_transfer_from_this, CHEM_INGEST) feed_sound(user) return TRUE - + else other_feed_message_start(user, target) if(!do_mob(user, target)) @@ -116,8 +121,8 @@ feed_sound(user) return TRUE -/obj/item/reagent_containers/proc/standard_pour_into(var/mob/user, var/atom/target) // This goes into afterattack and yes, it's atom-level - if(!target.is_open_container() || !target.reagents) +/obj/item/reagent_containers/proc/standard_pour_into(var/mob/user, var/atom/target, var/pour_all = FALSE) // This goes into afterattack and yes, it's atom-level + if(!target.is_open_container() || !target.reagents || !target.can_refill()) return 0 if(!reagents || !reagents.total_volume) @@ -128,6 +133,7 @@ to_chat(user, "[target] is full.") return 1 - var/trans = reagents.trans_to(target, amount_per_transfer_from_this) + var/trans = pour_all ? reagents.total_volume : amount_per_transfer_from_this + trans = reagents.trans_to(target, trans) to_chat(user, "You transfer [trans] units of the solution to [target].") return 1 diff --git a/code/modules/reagents/reagent_containers/bidon.dm b/code/modules/reagents/reagent_containers/bidon.dm new file mode 100644 index 00000000000..c9cf0ff0881 --- /dev/null +++ b/code/modules/reagents/reagent_containers/bidon.dm @@ -0,0 +1,163 @@ + +//this is big movable beaker +/obj/structure/reagent_dispensers/bidon + name = "B.I.D.O.N. canister" + desc = "Banded Industrial Drum for Organic Nonvolatiles. A canister with acid-resistant linings intended for handling big volumes of chemicals." + icon = 'icons/obj/machines/chemistry.dmi' + icon_state = "bidon" + amount_per_transfer_from_this = 30 + possible_transfer_amounts = list(10,30,60,120,200,300) + var/filling_states = list(10,20,30,40,50,60,70,80,100) + unacidable = 1 + anchored = 0 + var/obj/machinery/anchored_machine + density = TRUE + volume = 6000 + var/lid = TRUE + var/starting_reagent + var/starting_volume = 0 + has_hose=FALSE + atom_flags = EMPTY_BITFIELD + +/obj/structure/reagent_dispensers/bidon/Initialize() + . = ..() + if(starting_reagent && starting_volume) + reagents.add_reagent(starting_reagent, starting_volume) + +/obj/structure/reagent_dispensers/bidon/advanced + name = "stasis B.I.D.O.N. canister" + desc = "An advanced B.I.D.O.N. canister with stasis function." + icon_state = "bidon_adv" + atom_flags = ATOM_REAGENTS_SKIP_REACTIONS // It's a stasis BIDON, shouldn't allow chems to react inside it. + filling_states = list(20,40,60,80,100) + volume = 9000 + +/obj/structure/reagent_dispensers/bidon/trigger + name = "trigger-stasis B.I.D.O.N. canister" + desc = "An advanced B.I.D.O.N. canister with a stasis function that can be temporarily disabled with a multitool." + icon_state = "bidon_adv" + atom_flags = ATOM_REAGENTS_SKIP_REACTIONS //Tho its not a subtype its meant to be + filling_states = list(20,40,60,80,100) + volume = 9000 + var/timer_till_mixing = 120 + var/timing = FALSE + +/obj/structure/reagent_dispensers/bidon/trigger/examine(mob/user) + . = ..() + if(timing) + to_chat(user, SPAN_DANGER("[timer_till_mixing] seconds until stasis is disabled.")) + else + to_chat(user, SPAN_NOTICE("[src]'s timer isn't activated.")) + +/obj/structure/reagent_dispensers/bidon/trigger/attackby(obj/item/I, mob/user) + if(!timing) + if(I.is_multitool()) + timing=TRUE + to_chat(user, SPAN_NOTICE("You start the timer.")) + addtimer(CALLBACK(src, ./proc/timer_end), (1 SECOND * timer_till_mixing)) + timing=FALSE + return + else + . = ..() + update_icon() + +/obj/structure/reagent_dispensers/bidon/trigger/proc/timer_end() + atom_flags &= ~(ATOM_REAGENTS_SKIP_REACTIONS) + reagents.handle_reactions() + atom_flags |= ATOM_REAGENTS_SKIP_REACTIONS + + +/obj/structure/reagent_dispensers/bidon/Initialize(mapload, ...) + . = ..() + update_icon() + +/obj/structure/reagent_dispensers/bidon/examine(mob/user) + . = ..() + if(get_dist(user, src) <= 2) + if(lid) + . += "It has lid on it." + if(reagents.total_volume) + . += "It's filled with [reagents.total_volume]/[volume] units of reagents." + +/obj/structure/reagent_dispensers/bidon/attack_hand(mob/user as mob) + //Prevent the bidon from being messed with while it is anchored. + if(anchored) + to_chat(user, SPAN_NOTICE("You can't remove the lid while the canister is anchored!")) + return + lid = !lid + if(lid) + to_chat(user, SPAN_NOTICE("You put the lid on.")) + atom_flags &= ~(ATOM_REAGENTS_IS_OPEN) + else + atom_flags |= ATOM_REAGENTS_IS_OPEN + to_chat(user, SPAN_NOTICE("You removed the lid.")) + playsound(src,'sound/items/trayhit2.ogg',50,1) + update_icon() + +/obj/structure/reagent_dispensers/bidon/attackby(obj/item/I, mob/user) + + //Handle attaching the BIDON to a valid machine, should one exist + if(I.is_wrench()) + if(anchored) + anchored = FALSE + anchored_machine = null + playsound(src, I.usesound, 50, 1) + else + var/list/directions = list(WEST, NORTH, SOUTH, EAST) + for(var/direction_from_obj in directions) + for (var/obj/machinery/valid_machine in get_step(get_turf(src), direction_from_obj)) + if(ispath(valid_machine.anchor_type) && istype(src, valid_machine.anchor_type)) + if(valid_machine.anchor_direction) + if(valid_machine.anchor_direction == reverse_direction(direction_from_obj)) + anchored_machine = valid_machine + break + else + anchored_machine = valid_machine + break + if(anchored_machine) + to_chat(user, SPAN_NOTICE("You [anchored ? "detach" : "attach"] the B.I.D.O.N canister to the [anchored_machine].")) + anchored = TRUE + playsound(src, I.usesound, 50, 1) + //Remove the lid if it is currently sealed, so we don't have to deal with checking for it + if(lid) + to_chat(user, SPAN_NOTICE("The machine removes the lid automatically!")) + lid = FALSE + atom_flags |= ATOM_REAGENTS_IS_OPEN + playsound(src,'sound/items/trayhit2.ogg',50,1) + else if(lid) + to_chat(user, SPAN_NOTICE("Remove the lid first.")) + return + . = ..() + update_icon() + +/obj/structure/reagent_dispensers/bidon/update_icon() + cut_overlays() + if(lid) + var/mutable_appearance/lid_icon = mutable_appearance(icon, "[icon_state]_lid") + add_overlay(lid_icon) + if(anchored) + var/mutable_appearance/anchor_icon = mutable_appearance(icon, "bidon_anchored") + add_overlay(anchor_icon) + if(reagents.total_volume) + var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "[icon_state][get_filling_state()]") + if(!istype(src,/obj/structure/reagent_dispensers/bidon/advanced)) + filling.color = reagents.get_color() + add_overlay(filling) + +/obj/structure/reagent_dispensers/bidon/proc/get_filling_state() + var/percent = round((reagents.total_volume / volume) * 100) + for(var/increment in filling_states) + if(increment >= percent) + return increment + +/obj/structure/reagent_dispensers/bidon/advanced/examine(mob/user) + . = ..() + if(reagents.reagent_list.len && get_dist(user, src) <= 2) + for(var/I in reagents.reagent_list) + var/datum/reagent/R = I + . += "[R.volume] units of [R.name]" + +//Department starting protein to get the process off the ground +/obj/structure/reagent_dispensers/bidon/protein_can/si + starting_reagent = "protein" + starting_volume = 1000 diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index ad6877fd37f..0c020de9992 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -106,10 +106,18 @@ for(var/type in can_be_placed_into) //Is it something it can be placed into? if(istype(target, type)) return 1 + + + //Disarm intent tries to empty the beaker + if(user.a_intent == I_DISARM && standard_pour_into(user, target, TRUE)) + return TRUE + if(standard_dispenser_refill(user, target)) //Are they clicking a water tank/some dispenser? return 1 + if(standard_pour_into(user, target)) //Pouring into another beaker? return + if(user.a_intent == I_HURT) if(standard_splash_mob(user,target)) return 1 diff --git a/code/modules/research/designs/bio_devices.dm b/code/modules/research/designs/bio_devices.dm index f3aa33845ff..3ab18846b3f 100644 --- a/code/modules/research/designs/bio_devices.dm +++ b/code/modules/research/designs/bio_devices.dm @@ -59,3 +59,26 @@ build_path = /obj/item/analyzer/plant_analyzer sort_string = "JAADA" +/datum/design/item/biotech/bidon + desc = "A lumbering metal drum used to hold large amounts of chemicals." + id = "bidon" + req_tech = list(TECH_MATERIAL = 4, TECH_BIO = 4) + materials = list(MAT_STEEL = 2000, "glass" = 1000) + build_path = /obj/structure/reagent_dispensers/bidon + sort_string = "IAAAC" + +/datum/design/item/biotech/advanced_bidon + desc = "A lumbering metal drum used to hold large amounts of chemicals in sustained cryostasis." + id = "advanced_bidon" + req_tech = list(TECH_MATERIAL = 6, TECH_BIO = 4, TECH_DATA = 5) + materials = list(MAT_STEEL = 2000, "glass" = 1000, MAT_SILVER = 100) + build_path = /obj/structure/reagent_dispensers/bidon/advanced + sort_string = "IAAAD" + +/datum/design/item/biotech/trigger_bidon + desc = "A dubiously legal metal drum that can be triggered to mix all of its contents at the same time." + id = "trigger_bidon" + req_tech = list(TECH_MATERIAL = 6, TECH_BIO = 4, TECH_DATA = 5, TECH_ILLEGAL = 3) + materials = list(MAT_STEEL = 2000, "glass" = 1000, MAT_GOLD = 500) + build_path = /obj/structure/reagent_dispensers/bidon/trigger + sort_string = "IAAAE" diff --git a/icons/obj/machines/chemistry.dmi b/icons/obj/machines/chemistry.dmi new file mode 100644 index 00000000000..ccab439b84e Binary files /dev/null and b/icons/obj/machines/chemistry.dmi differ diff --git a/icons/obj/reagentfillings.dmi b/icons/obj/reagentfillings.dmi index ab553f5f922..34ea6e3112b 100644 Binary files a/icons/obj/reagentfillings.dmi and b/icons/obj/reagentfillings.dmi differ diff --git a/polaris.dme b/polaris.dme index be8eeacc525..b16e0aac039 100644 --- a/polaris.dme +++ b/polaris.dme @@ -2983,6 +2983,7 @@ #include "code\modules\reagents\reactions\instant\instant.dm" #include "code\modules\reagents\reactions\instant\vox.dm" #include "code\modules\reagents\reagent_containers\_reagent_containers.dm" +#include "code\modules\reagents\reagent_containers\bidon.dm" #include "code\modules\reagents\reagent_containers\blood_pack.dm" #include "code\modules\reagents\reagent_containers\borghypo.dm" #include "code\modules\reagents\reagent_containers\dropper.dm"