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/modules/reagents/machinery/dispenser/reagent_tank.dm b/code/modules/reagents/machinery/dispenser/reagent_tank.dm index bfe7dc58114..ae03e2999c9 100644 --- a/code/modules/reagents/machinery/dispenser/reagent_tank.dm +++ b/code/modules/reagents/machinery/dispenser/reagent_tank.dm @@ -9,10 +9,11 @@ density = 1 anchored = 0 pressure_resistance = 2*ONE_ATMOSPHERE - + atom_flags = ATOM_REAGENTS_NO_REFILL + var/volume = 5000 + var/has_hose = TRUE var/obj/item/hose_connector/input/active/InputSocket var/obj/item/hose_connector/output/active/OutputSocket - var/amount_per_transfer_from_this = 10 var/possible_transfer_amounts = list(10,25,50,100) @@ -22,21 +23,20 @@ /obj/structure/reagent_dispensers/Destroy() QDEL_NULL(InputSocket) QDEL_NULL(OutputSocket) - - ..() + return ..() /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) diff --git a/code/modules/reagents/reagent_containers/_reagent_containers.dm b/code/modules/reagents/reagent_containers/_reagent_containers.dm index 322fe5389dc..85f8e3e251a 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].") @@ -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..59667050583 --- /dev/null +++ b/code/modules/reagents/reagent_containers/bidon.dm @@ -0,0 +1,158 @@ +/obj/structure/reagent_dispensers/bidon + name = "bidon canister" + desc = "A canister for handling large volumes of chemicals." + icon = 'icons/obj/structures/bidon.dmi' + icon_state = "bidon" + possible_transfer_amounts = list(10, 30, 60, 120, 200, 300) + unacidable = TRUE + has_hose = FALSE + var/use_reagent_color = TRUE + var/fill_step = 10 + + +/obj/structure/reagent_dispensers/bidon/Initialize() + . = ..() + update_icon() + + +/obj/structure/reagent_dispensers/bidon/update_icon() + cut_overlays() + if (!is_open_container()) + add_overlay("[icon_state]_lid") + var/fill_state = ceil(round(reagents.total_volume / volume * 100, fill_step), 0, 100) + if (!fill_state) + return + if (use_reagent_color) + var/image/image = image(icon, icon_state = "[icon_state][fill_state]") + image.color = reagents.get_color() + add_overlay(image) + else + add_overlay("[icon_state][fill_state]") + + +/obj/structure/reagent_dispensers/bidon/examine(mob/user, distance, infix, suffix) + . = ..() + if (distance > 5) + return + . += "The lid is [is_open_container() ? "off" : "on"]." + if (distance < 3) + . += "It holds [round(reagents.total_volume, 0.1)]/[volume] units of reagents." + + +/obj/structure/reagent_dispensers/bidon/attack_hand(mob/living/user) + playsound(src, 'sound/items/trayhit2.ogg', 50, TRUE) + atom_flags ^= ATOM_REAGENTS_IS_OPEN + if (is_open_container()) + to_chat(user, SPAN_ITALIC("You open the lid of \the [src].")) + else + to_chat(user, SPAN_ITALIC("You close the lid of \the [src].")) + update_icon() + + +/obj/structure/reagent_dispensers/bidon/attackby(obj/item/item, mob/living/user) + if (!is_open_container() && istype(item, /obj/item/reagent_containers)) + to_chat(user, SPAN_WARNING("Remove the lid first.")) + return TRUE + return ..() + + +/obj/structure/reagent_dispensers/bidon/stasis + name = "stasis bidon canister" + desc = "A canister for handling large volumes of chemicals. This one has a stasis field." + icon_state = "bidon_stasis" + atom_flags = ATOM_REAGENTS_SKIP_REACTIONS + use_reagent_color = FALSE + fill_step = 20 + var/timer_seconds + var/timer_handle + + +/obj/structure/reagent_dispensers/bidon/stasis/update_icon() + ..() + if (timer_handle) + add_overlay("timer_active") + else if (timer_seconds) + add_overlay("timer_idle") + + +/obj/structure/reagent_dispensers/bidon/stasis/examine(mob/user, distance, infix, suffix) + . = ..() + if (distance > 5 || !timer_seconds) + return + var/timer_display = "a timer" + if (timer_handle) + timer_display = "an active timer" + if (distance > 3) + . += "It has [timer_display] attached." + else + . += "It has [timer_display] attached set for [timer_seconds] seconds." + + +/obj/structure/reagent_dispensers/bidon/stasis/attackby(obj/item/item, mob/living/user) + if (istype(item, /obj/item/assembly/timer)) + if (timer_seconds) + to_chat(user, SPAN_WARNING("\The [src] already has a timer attached.")) + else if (user.unEquip(item)) + var/obj/item/assembly/timer/timer = item + timer_seconds = timer.time + qdel(item) + playsound(src, 'sound/items/Screwdriver.ogg', 50, TRUE) + user.visible_message( + SPAN_ITALIC("\The [user] attaches \a [item] to \a [src]."), + SPAN_ITALIC("You attach \the [item] to \the [src]."), + SPAN_ITALIC("You hear metal clicking together."), + range = 5 + ) + return TRUE + if (item.is_screwdriver()) + if (!timer_seconds) + to_chat(user, SPAN_WARNING("\The [src] doesn't have a timer attached.")) + else if (timer_handle) + to_chat(user, SPAN_WARNING("\The [src]'s timer is active.")) + else + user.visible_message( + SPAN_ITALIC("\The [user] removes the timer from \the [src]."), + SPAN_ITALIC("You remove the timer from \the [src]."), + SPAN_ITALIC("You hear metal clicking together."), + range = 5 + ) + playsound(src, item.usesound, 50, TRUE) + var/obj/item/assembly/timer/timer = new (loc) + user.put_in_hands(timer) + timer.time = timer_seconds + timer_seconds = 0 + return TRUE + if (item.is_multitool()) + if (!timer_seconds) + to_chat(user, SPAN_WARNING("\The [src] doesn't have a timer attached.")) + return TRUE + else if (timer_handle) + deltimer(timer_handle) + timer_handle = null + user.visible_message( + SPAN_ITALIC("\The [user] disables the timer on \the [src]."), + SPAN_ITALIC("You disable the timer on \the [src]."), + SPAN_ITALIC("You hear soft beeping."), + range = 5 + ) + update_icon() + else + timer_handle = addtimer(CALLBACK(src, .proc/timer_end), timer_seconds SECONDS, TIMER_STOPPABLE) + user.visible_message( + SPAN_ITALIC("\The [user] activates the timer on \the [src]."), + SPAN_ITALIC("You activate the timer on \the [src]."), + SPAN_ITALIC("You hear soft beeping."), + range = 5 + ) + playsound(src, item.usesound, 50, TRUE) + update_icon() + return TRUE + return ..() + + +/obj/structure/reagent_dispensers/bidon/stasis/proc/timer_end() + atom_flags &= ~(ATOM_REAGENTS_SKIP_REACTIONS) + reagents.handle_reactions() + atom_flags |= ATOM_REAGENTS_SKIP_REACTIONS + timer_handle = null + update_icon() diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index ad6877fd37f..ebf920734bb 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -106,6 +106,11 @@ 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? diff --git a/code/modules/research/designs/bio_devices.dm b/code/modules/research/designs/bio_devices.dm index f3aa33845ff..7c6a26c6a88 100644 --- a/code/modules/research/designs/bio_devices.dm +++ b/code/modules/research/designs/bio_devices.dm @@ -59,3 +59,18 @@ build_path = /obj/item/analyzer/plant_analyzer sort_string = "JAADA" +/datum/design/item/biotech/bidon + desc = "A canister for handling large volumes 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 = "JAADB" + +/datum/design/item/biotech/bidon_stasis + desc = "A stasis canister for handling large volumes of chemicals." + id = "bidon_stasis" + 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/stasis + sort_string = "JAADC" diff --git a/icons/obj/structures/bidon.dmi b/icons/obj/structures/bidon.dmi new file mode 100644 index 00000000000..6dea9015bf7 Binary files /dev/null and b/icons/obj/structures/bidon.dmi differ diff --git a/polaris.dme b/polaris.dme index 7632f1ce87b..eba303d8ca4 100644 --- a/polaris.dme +++ b/polaris.dme @@ -3002,6 +3002,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"