diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 5a01fa82547..df2d47e8ba7 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -1008,7 +1008,7 @@
return SEND_SIGNAL(src, COMSIG_ITEM_MICROWAVE_ACT, microwave_source, microwaver, randomize_pixel_offset)
-//Used to check for extra requirements for blending(grinding or juicing) an object
+///Used to check for extra requirements for blending(grinding or juicing) an object
/obj/item/proc/blend_requirements(obj/machinery/reagentgrinder/R)
return TRUE
@@ -1018,15 +1018,16 @@
///Grind item, adding grind_results to item's reagents and transfering to target_holder if specified
/obj/item/proc/grind(datum/reagents/target_holder, mob/user)
+ . = FALSE
if(on_grind() == -1)
- return FALSE
+ return
if(length(grind_results))
target_holder.add_reagent_list(grind_results)
+ . = TRUE
if(reagents?.total_volume)
reagents.trans_to(target_holder, reagents.total_volume, transferred_by = user)
-
- return TRUE
+ . = TRUE
///Called BEFORE the object is ground up - use this to change grind results based on conditions. Return "-1" to prevent the grinding from occurring
/obj/item/proc/on_juice()
diff --git a/code/game/objects/items/rcd/RPLD.dm b/code/game/objects/items/rcd/RPLD.dm
index 21e68bd92dd..8ae38982692 100644
--- a/code/game/objects/items/rcd/RPLD.dm
+++ b/code/game/objects/items/rcd/RPLD.dm
@@ -247,23 +247,8 @@
if(duct_machine.duct_layer & layer_id)
return FALSE
-/obj/item/construction/plumbing/pre_attack_secondary(obj/machinery/target, mob/user, params)
- if(!istype(target, /obj/machinery/duct))
- return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
-
- var/obj/machinery/duct/duct = target
- if(duct.duct_layer && duct.duct_color)
- current_color = GLOB.pipe_color_name[duct.duct_color]
- current_layer = GLOB.plumbing_layer_names["[duct.duct_layer]"]
- balloon_alert(user, "using [current_color], layer [current_layer]")
-
- return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
-
-/obj/item/construction/plumbing/afterattack(atom/target, mob/user, proximity)
- . = ..()
- if(!proximity)
- return
-
+/obj/item/construction/plumbing/interact_with_atom(atom/target, mob/living/user, list/modifiers)
+ . = NONE
for(var/category_name in plumbing_design_types)
var/list/designs = plumbing_design_types[category_name]
@@ -274,13 +259,26 @@
var/obj/machinery/machine_target = target
if(machine_target.anchored)
balloon_alert(user, "unanchor first!")
- return
+ return ITEM_INTERACT_BLOCKING
if(do_after(user, 2 SECONDS, target = target))
machine_target.deconstruct() //Let's not substract matter
playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE) //this is just such a great sound effect
- return
+ return ITEM_INTERACT_SUCCESS
+
+ if(create_machine(target, user))
+ return ITEM_INTERACT_SUCCESS
+
+/obj/item/construction/plumbing/interact_with_atom_secondary(atom/target, mob/living/user, list/modifiers)
+ . = NONE
+ if(!istype(target, /obj/machinery/duct))
+ return ITEM_INTERACT_BLOCKING
- create_machine(target, user)
+ var/obj/machinery/duct/duct = target
+ if(duct.duct_layer && duct.duct_color)
+ current_color = GLOB.pipe_color_name[duct.duct_color]
+ current_layer = GLOB.plumbing_layer_names["[duct.duct_layer]"]
+ balloon_alert(user, "using [current_color], layer [current_layer]")
+ return ITEM_INTERACT_SUCCESS
/obj/item/construction/plumbing/click_alt(mob/user)
ui_interact(user)
diff --git a/code/modules/plumbing/plumbers/_plumb_machinery.dm b/code/modules/plumbing/plumbers/_plumb_machinery.dm
index e3f9486bee9..2e8eaee9d6d 100644
--- a/code/modules/plumbing/plumbers/_plumb_machinery.dm
+++ b/code/modules/plumbing/plumbers/_plumb_machinery.dm
@@ -11,6 +11,8 @@
processing_flags = START_PROCESSING_MANUALLY
active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2.75
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ interaction_flags_machine = parent_type::interaction_flags_machine | INTERACT_MACHINE_OFFLINE
+
///Plumbing machinery is always gonna need reagents, so we might aswell put it here
var/buffer = 50
///Flags for reagents, like INJECTABLE, TRANSPARENT bla bla everything thats in DEFINES/reagents.dm
@@ -21,11 +23,42 @@
set_anchored(bolt)
create_reagents(buffer, reagent_flags)
AddComponent(/datum/component/simple_rotation)
- interaction_flags_machine |= INTERACT_MACHINE_OFFLINE
+ register_context()
+
+/obj/machinery/plumbing/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ . = NONE
+ if(isnull(held_item))
+ return
+
+ if(held_item.tool_behaviour == TOOL_WRENCH)
+ context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Un" : ""]Anchor"
+ return CONTEXTUAL_SCREENTIP_SET
+ else if(held_item.tool_behaviour == TOOL_WELDER && !anchored)
+ context[SCREENTIP_CONTEXT_LMB] = "Deconstruct"
+ return CONTEXTUAL_SCREENTIP_SET
+ else if(istype(held_item, /obj/item/plunger))
+ context[SCREENTIP_CONTEXT_LMB] = "Flush"
+ return CONTEXTUAL_SCREENTIP_SET
/obj/machinery/plumbing/examine(mob/user)
. = ..()
- . += span_notice("The maximum volume display reads: [reagents.maximum_volume] units.")
+ if(isobserver(user) || !in_range(src, user))
+ return
+
+ . += span_notice("The maximum volume display reads: [reagents.maximum_volume]u capacity. Contains:")
+ if(reagents.total_volume)
+ for(var/datum/reagent/reg as anything in reagents.reagent_list)
+ . += span_notice("[round(reg.volume, CHEMICAL_VOLUME_ROUNDING)]u of [reg.name]")
+ else
+ . += span_notice("Nothing.")
+
+ if(anchored)
+ . += span_notice("It's [EXAMINE_HINT("anchored")] in place.")
+ else
+ . += span_warning("Needs to be [EXAMINE_HINT("anchored")] to start operations.")
+ . += span_notice("It can be [EXAMINE_HINT("welded")] apart.")
+
+ . += span_notice("An [EXAMINE_HINT("plunger")] can be used to flush out reagents.")
/obj/machinery/plumbing/wrench_act(mob/living/user, obj/item/tool)
if(user.combat_mode)
@@ -39,6 +72,23 @@
end_processing()
return ITEM_INTERACT_SUCCESS
+/obj/machinery/plumbing/welder_act(mob/living/user, obj/item/I)
+ if(user.combat_mode)
+ return NONE
+
+ if(anchored)
+ balloon_alert(user, "unanchor first!")
+ return ITEM_INTERACT_BLOCKING
+
+ if(I.tool_start_check(user, amount = 1))
+ to_chat(user, span_notice("You start slicing the [name] apart."))
+ if(I.use_tool(src, user, 1.5 SECONDS, volume = 50))
+ deconstruct(TRUE)
+ to_chat(user, span_notice("You slice the [name] apart."))
+ return ITEM_INTERACT_SUCCESS
+
+ return ITEM_INTERACT_BLOCKING
+
/obj/machinery/plumbing/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
user.balloon_alert_to_viewers("furiously plunging...")
if(do_after(user, 3 SECONDS, target = src))
@@ -46,17 +96,6 @@
reagents.expose(get_turf(src), TOUCH) //splash on the floor
reagents.clear_reagents()
-/obj/machinery/plumbing/welder_act(mob/living/user, obj/item/I)
- . = ..()
- if(anchored)
- to_chat(user, span_warning("The [name] needs to be unbolted to do that!"))
- if(I.tool_start_check(user, amount=1))
- to_chat(user, span_notice("You start slicing the [name] apart."))
- if(I.use_tool(src, user, (1.5 SECONDS), volume=50))
- deconstruct(TRUE)
- to_chat(user, span_notice("You slice the [name] apart."))
- return TRUE
-
///We can empty beakers in here and everything
/obj/machinery/plumbing/input
name = "input gate"
diff --git a/code/modules/plumbing/plumbers/grinder_chemical.dm b/code/modules/plumbing/plumbers/grinder_chemical.dm
index f75ec94f21c..bd0a69e6d5e 100644
--- a/code/modules/plumbing/plumbers/grinder_chemical.dm
+++ b/code/modules/plumbing/plumbers/grinder_chemical.dm
@@ -7,6 +7,9 @@
reagent_flags = TRANSPARENT | DRAINABLE
buffer = 400
+ /// Are we grinding or juicing
+ var/grinding = TRUE
+
/obj/machinery/plumbing/grinder_chemical/Initialize(mapload, bolt, layer)
. = ..()
AddComponent(/datum/component/plumbing/simple_supply, bolt, layer)
@@ -15,17 +18,74 @@
)
AddElement(/datum/element/connect_loc, loc_connections)
-/obj/machinery/plumbing/grinder_chemical/attackby(obj/item/weapon, mob/user, params)
- if(istype(weapon, /obj/item/storage/bag))
- to_chat(user, span_notice("You dump items from [weapon] into the grinder."))
- for(var/obj/item/obj_item in weapon.contents)
- grind(obj_item)
- else
- to_chat(user, span_notice("You attempt to grind [weapon]."))
- grind(weapon)
+/obj/machinery/plumbing/grinder_chemical/examine(mob/user)
+ . = ..()
+
+ . += span_notice("Use empty hand to change operation mode. Currently [grinding ? "Grinding" : "Juicing"]")
+
+/**
+ * Check if the user can interact with the grinder
+ * Arguments
+ *
+ * * mob/user - the player we are checking for
+ */
+/obj/machinery/plumbing/grinder_chemical/proc/check_interactable(mob/user)
+ PRIVATE_PROC(TRUE)
+ return can_interact(user)
+
+/obj/machinery/plumbing/grinder_chemical/attack_hand(mob/living/user, list/modifiers)
+ if(user.combat_mode || !user.can_perform_action(src, ALLOW_SILICON_REACH | FORBID_TELEKINESIS_REACH))
+ return FALSE
+
+ var/list/options = list()
+
+ var/static/radial_grind = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_grind")
+ options["grind"] = radial_grind
+
+ var/static/radial_juice = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_juice")
+ options["juice"] = radial_juice
+
+ var/choice = show_radial_menu(
+ user,
+ src,
+ options,
+ custom_check = CALLBACK(src, PROC_REF(check_interactable), user),
+ )
+ if(!choice)
+ return FALSE
+
+ grinding = (choice == "grind")
return TRUE
+/obj/machinery/plumbing/grinder_chemical/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ . = NONE
+ if(user.combat_mode || !user.can_perform_action(src, ALLOW_SILICON_REACH | FORBID_TELEKINESIS_REACH))
+ return ITEM_INTERACT_SKIP_TO_ATTACK
+
+ if(istype(tool, /obj/item/construction/plumbing))
+ return tool.interact_with_atom(src, user, modifiers)
+ else if(istype(tool, /obj/item/plunger))
+ return
+ else if(istype(tool, /obj/item/storage/bag))
+ if(!anchored)
+ to_chat(user, span_warning("Anchor first to start [grinding ? "grind" : "juice"]."))
+ return ITEM_INTERACT_BLOCKING
+
+ to_chat(user, span_notice("You dump items from [tool] into the grinder."))
+ for(var/obj/item/obj_item in tool.contents)
+ grind(obj_item)
+ return ITEM_INTERACT_SUCCESS
+ else if(!tool.tool_behaviour)
+ var/action = "[grinding ? "grind" : "juice"]"
+ if(!anchored)
+ to_chat(user, span_warning("Anchor first to star [action]."))
+ return ITEM_INTERACT_BLOCKING
+
+ to_chat(user, span_notice("You attempt to [action] [tool]."))
+ grind(tool)
+ return ITEM_INTERACT_SUCCESS
+
/obj/machinery/plumbing/grinder_chemical/CanAllowThrough(atom/movable/mover, border_dir)
. = ..()
if(!anchored)
@@ -37,7 +97,7 @@
/obj/machinery/plumbing/grinder_chemical/proc/on_entered(datum/source, atom/movable/AM)
SIGNAL_HANDLER
- grind(AM)
+ INVOKE_ASYNC(src, PROC_REF(grind), AM)
/**
* Grinds/Juices the atom
@@ -45,7 +105,9 @@
* * [AM][atom] - the atom to grind or juice
*/
/obj/machinery/plumbing/grinder_chemical/proc/grind(atom/AM)
- if(!is_operational)
+ PRIVATE_PROC(TRUE)
+
+ if(!is_operational || !anchored)
return
if(reagents.holder_full())
return
@@ -53,11 +115,15 @@
return
var/obj/item/I = AM
+ if((I.item_flags & ABSTRACT) || (I.flags_1 & HOLOGRAM_1))
+ return
+
var/result
- if(I.grind_results)
- result = I.grind(reagents, usr)
- else
+ if(!grinding)
result = I.juice(reagents, usr)
+ else if(length(I.grind_results) || I.reagents?.total_volume)
+ result = I.grind(reagents, usr)
+
+ use_energy(active_power_usage)
if(result)
- use_energy(active_power_usage)
qdel(I)
diff --git a/code/modules/plumbing/plumbers/vatgrower.dm b/code/modules/plumbing/plumbers/vatgrower.dm
index 7327a648dad..1dcfb08e0cc 100644
--- a/code/modules/plumbing/plumbers/vatgrower.dm
+++ b/code/modules/plumbing/plumbers/vatgrower.dm
@@ -11,9 +11,9 @@
var/resampler_active = FALSE
///Add that sexy demnand component
-/obj/machinery/plumbing/growing_vat/Initialize(mapload, bolt)
+/obj/machinery/plumbing/growing_vat/Initialize(mapload, bolt, layer)
. = ..()
- AddComponent(/datum/component/plumbing/simple_demand, bolt)
+ AddComponent(/datum/component/plumbing/simple_demand, bolt, layer)
/obj/machinery/plumbing/growing_vat/create_reagents(max_vol, flags)
. = ..()