General maintenance for plumbing disposer (#94944)

## About The Pull Request
- Plumbing disposer disposal rate can now be changed with hand nad has
TGUI interface. It accepts a value between 5->15 meaning it can dispose
anywhere from 10u to 50u reagents per tick. Added examines & screen tips
for the same
- Fixes plumbing disposer icon state not correctly switching between
working and off under certain circumstances

## Changelog
🆑
qol: plumbing disposer now has TGUI interface for operations
fix: plumbing disposer icon state correctly switches between on & off
under circumstances
/🆑
This commit is contained in:
SyncIt21
2026-02-03 22:23:58 -05:00
committed by GitHub
parent 6f37db300b
commit c779efbeec
3 changed files with 151 additions and 11 deletions
@@ -20,6 +20,19 @@
edge_overlay.pixel_z = -parent_movable.pixel_y - parent_movable.pixel_z
overlays += edge_overlay
///For disposing reagents
/datum/component/plumbing/simple_demand/disposer
/datum/component/plumbing/simple_demand/disposer/Initialize(ducting_layer, distinct_reagent_cap)
if(!istype(parent, /obj/machinery/plumbing/disposer))
return COMPONENT_INCOMPATIBLE
return ..()
/datum/component/plumbing/simple_demand/disposer/send_request(dir)
var/obj/machinery/plumbing/disposer/target = parent
if(target.on)
process_request(target.disposal_rate * SSFLUIDS_DT, dir = dir)
///has one pipe output that only supplies. example is liquid pump and manual input pipe
/datum/component/plumbing/simple_supply
supply_connects = SOUTH
+80 -11
View File
@@ -1,25 +1,94 @@
//Maximum disposal rate
#define MAX_DISPOSAL_RATE 25
/obj/machinery/plumbing/disposer
name = "chemical disposer"
desc = "Breaks down chemicals and annihilates them."
icon_state = "disposal"
base_icon_state = "disposal"
pass_flags_self = PASSMACHINE | LETPASSTHROW // Small
active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 4
///we remove 5 reagents per second
///Reagents to remove per second
var/disposal_rate = 5
///Is this machine switched on
var/on = FALSE
/obj/machinery/plumbing/disposer/Initialize(mapload, layer)
. = ..()
AddComponent(/datum/component/plumbing/simple_demand, layer)
AddComponent(/datum/component/plumbing/simple_demand/disposer, layer)
RegisterSignal(reagents, COMSIG_REAGENTS_HOLDER_UPDATED, PROC_REF(update))
/obj/machinery/plumbing/disposer/examine(mob/user)
. = ..()
. += span_notice("It is disposing [disposal_rate]u reagents per second.")
. += span_notice("Use hand to change disposal rate.")
/obj/machinery/plumbing/disposer/add_context(atom/source, list/context, obj/item/held_item, mob/user)
if(isnull(held_item))
context[SCREENTIP_CONTEXT_LMB] = "Set transfer rate"
return CONTEXTUAL_SCREENTIP_SET
return ..()
/obj/machinery/plumbing/disposer/proc/update()
SIGNAL_HANDLER
update_appearance(UPDATE_ICON_STATE)
/obj/machinery/plumbing/disposer/update_icon_state()
icon_state = "[base_icon_state][is_operational && anchored && on && reagents.total_volume ? "_working" : ""]"
return ..()
/obj/machinery/plumbing/disposer/on_set_is_operational(old_value)
. = ..()
update_appearance(UPDATE_ICON_STATE)
/obj/machinery/plumbing/disposer/wrench_act(mob/living/user, obj/item/tool)
. = ..()
if(. == ITEM_INTERACT_SUCCESS)
update_appearance(UPDATE_ICON_STATE)
/obj/machinery/plumbing/disposer/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ChemDisposer", name)
ui.open()
/obj/machinery/plumbing/disposer/ui_static_data(mob/user)
return list(
max_volume = MAX_DISPOSAL_RATE
)
/obj/machinery/plumbing/disposer/ui_data(mob/user)
return list(
enabled = on,
disposal_rate = disposal_rate
)
/obj/machinery/plumbing/disposer/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return
switch(action)
if("toggle_power")
on = !on
update_appearance(UPDATE_ICON_STATE)
return TRUE
if("change_volume")
var/num = text2num(params["volume"])
if(!isnum(num))
return FALSE
disposal_rate = round(clamp(num, 0.1, MAX_DISPOSAL_RATE), CHEMICAL_VOLUME_ROUNDING)
return TRUE
/obj/machinery/plumbing/disposer/process(seconds_per_tick)
if(!is_operational)
if(!is_operational || !reagents.total_volume || !on)
return
if(reagents.total_volume)
if(icon_state != initial(icon_state) + "_working") //threw it here instead of update icon since it only has two states
icon_state = initial(icon_state) + "_working"
reagents.remove_all(disposal_rate * seconds_per_tick)
use_energy(active_power_usage * seconds_per_tick)
else
if(icon_state != initial(icon_state))
icon_state = initial(icon_state)
reagents.remove_all(disposal_rate * seconds_per_tick)
use_energy((disposal_rate / MAX_DISPOSAL_RATE) * active_power_usage * seconds_per_tick)
#undef MAX_DISPOSAL_RATE
@@ -0,0 +1,58 @@
import { useBackend } from 'tgui/backend';
import {
Button,
LabeledList,
NumberInput,
Section,
} from 'tgui-core/components';
import type { BooleanLike } from 'tgui-core/react';
import { Window } from '../layouts';
type Data = {
enabled: BooleanLike;
max_volume: number;
disposal_rate: number;
};
export function ChemDisposer() {
const { act, data } = useBackend<Data>();
const { enabled, max_volume, disposal_rate } = data;
return (
<Window width={320} height={105}>
<Window.Content>
<Section
title="Control Panel"
buttons={
<Button
icon="power-off"
selected={enabled}
onClick={() => act('toggle_power')}
>
{enabled ? 'On' : 'Off'}
</Button>
}
>
<LabeledList>
<LabeledList.Item label="Volume">
<NumberInput
value={disposal_rate}
unit="u"
width="50px"
minValue={0.1}
maxValue={max_volume}
step={1}
stepPixelSize={2}
onChange={(value) =>
act('change_volume', {
volume: value,
})
}
/>
</LabeledList.Item>
</LabeledList>
</Section>
</Window.Content>
</Window>
);
}