Refactors disposal connection components, makes them more properly connected (#18912)

* Awawa I scopecreeped too hard

* functionality

* oops, missed a spot

* unglog

Ouuurrrrp my code so full of bad

---------

Co-authored-by: Cameron Lennox <killer65311@gmail.com>
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
Reo Lozzot
2026-01-14 14:13:21 -06:00
committed by GitHub
parent 6a8b83a087
commit d8684edb94
11 changed files with 419 additions and 281 deletions
@@ -23,12 +23,12 @@
// Incin/space
/obj/machinery/disposal/burn_pit
name = "disposal(hazardous)"
name = "disposal (hazardous)"
desc = "A pneumatic waste disposal unit. This unit is either connected directly to the station's waste processor or dumped into space."
icon_state = "red"
/obj/machinery/disposal/wall/burn_pit
name = "disposal(hazardous)"
name = "disposal (hazardous)"
desc = "A pneumatic waste disposal unit. This unit is either connected directly to the station's waste processor or dumped into space."
icon_state = "redwall"
+46 -27
View File
@@ -14,6 +14,19 @@
flags = REMOTEVIEW_ON_ENTER
dir = 0
/obj/structure/disposalholder/Destroy()
QDEL_NULL(gas)
if(contents.len)
var/turf/qdelloc = get_turf(src)
if(qdelloc)
for(var/atom/movable/AM in contents)
AM.forceMove(qdelloc)
else
log_runtime("A disposal holder was deleted with contents in nullspace") //ideally, this should never happen
active = FALSE
return ..()
// initialize a holder from the contents of a disposal unit
/obj/structure/disposalholder/proc/init(list/flush_list, datum/gas_mixture/flush_gas)
gas = flush_gas// transfer gas resv. into holder object -- let's be explicit about the data this proc consumes, please.
@@ -23,6 +36,7 @@
for(var/mob/living/M in flush_list)
if(M.stat != DEAD && !istype(M,/mob/living/silicon/robot/drone))
hasmob = TRUE
break
//Checks 1 contents level deep. This means that players can be sent through disposals...
//...but it should require a second person to open the package. (i.e. person inside a wrapped locker)
@@ -32,21 +46,23 @@
for(var/mob/living/M in O.contents)
if(M && M.stat != DEAD && !istype(M,/mob/living/silicon/robot/drone))
hasmob = TRUE
break
// now everything inside the disposal gets put into the holder
// note AM since can contain mobs or objs
for(var/atom/movable/AM in flush_list)
AM.forceMove(src)
// Mail will use it's sorting tag if dropped into disposals
if(istype(AM, /obj/structure/bigDelivery) && !hasmob)
var/obj/structure/bigDelivery/T = AM
src.destinationTag = T.sortTag
if(istype(AM, /obj/item/smallDelivery) && !hasmob)
var/obj/item/smallDelivery/T = AM
src.destinationTag = T.sortTag
if(istype(AM, /obj/item/mail) && !hasmob)
var/obj/item/mail/T = AM
src.destinationTag = T.sortTag
if(!hasmob)
if(istype(AM, /obj/structure/bigDelivery))
var/obj/structure/bigDelivery/T = AM
src.destinationTag = T.sortTag
if(istype(AM, /obj/item/smallDelivery))
var/obj/item/smallDelivery/T = AM
src.destinationTag = T.sortTag
if(istype(AM, /obj/item/mail))
var/obj/item/mail/T = AM
src.destinationTag = T.sortTag
// Drones can mail themselves through maint.
if(istype(AM, /mob/living/silicon/robot/drone))
var/mob/living/silicon/robot/drone/drone = AM
@@ -112,37 +128,40 @@
else
partialTag = new_tag
// Nolonger shall you be stuck forever in the tubes. ...It might just hurt a bit.
/obj/structure/disposalholder/container_resist(mob/living/escapee)
. = ..()
if(!istype(loc, /obj/structure/disposalpipe))
return //Somehow we're not in a pipe, shits probably fucked
var/obj/structure/disposalpipe/transport_cylinder = loc
if(active)
return
to_chat(escapee, span_warning("You push against the thin pipe walls..."))
playsound(loc, 'sound/machines/door/airlock_creaking.ogg', 30, FALSE, 3) //yeah I know but at least it sounds like metal being bent.
if(!do_after(escapee, 20 SECONDS, transport_cylinder))
return
for(var/mob/living/jailbird in contents)
jailbird.apply_damage(rand(5,15), BRUTE)
transport_cylinder.expel(src, get_turf(loc), NONE) //Direction: NONE, this makes the stuff spew everywhere (lol)
// called when player tries to move while in a pipe
/obj/structure/disposalholder/relaymove(mob/living/user)
if(!isliving(user))
return
if(user.stat || user.last_special <= world.time)
// If someone has sent you here to add a delay to this proc, inform them that it is a bug with /relaymove
// it's a minor bug, but it results in the proc being called much more frequently than it should, and when the bug is fixed the delay will work properly.
if(user.stat)
return
user.last_special = world.time+100
if(QDELETED(src))
return
for(var/mob/M in hearers(get_turf(src)))
to_chat(M, "<FONT size=[max(0, 5 - get_dist(src, M))]>CLONG, clong!</FONT>")
M.show_message("<FONT size=[max(0, 5 - get_dist(src, M))]>CLONG, clong!</FONT>", AUDIBLE_MESSAGE)
playsound(src, 'sound/effects/clang.ogg', 50, 0, 0)
// called to vent all gas in holder to a location
// called to vent all gas in holder to a location
/obj/structure/disposalholder/proc/vent_gas(atom/location)
location.assume_air(gas) // vent all gas to turf
return
/obj/structure/disposalholder/Destroy()
QDEL_NULL(gas)
if(contents.len)
var/turf/qdelloc = get_turf(src)
if(qdelloc)
for(var/atom/movable/AM in contents)
AM.forceMove(qdelloc)
else
log_and_message_admins("A disposal holder was deleted with contents in nullspace") //ideally, this should never happen
active = FALSE
return ..()
+204 -111
View File
@@ -27,6 +27,7 @@
var/flushing = FALSE // true if flushing in progress
var/flush_every_ticks = 30 //Every 30 ticks it will look whether it is ready to flush
var/flush_count = 0 //this var adds 1 once per tick. When it reaches flush_every_ticks it resets and tries to flush.
var/last_sound
active_power_usage = 2200 //the pneumatic pump power. 3 HP ~ 2200W
idle_power_usage = 100
var/stat_tracking = TRUE
@@ -34,22 +35,37 @@
// create a new disposal
// find the attached trunk (if present) and init gas resvr.
/obj/machinery/disposal/Initialize(mapload)
/obj/machinery/disposal/Initialize(mapload, obj/structure/disposalconstruct/make_from)
. = ..()
var/obj/structure/disposalpipe/trunk/trunk = locate() in loc
if(!trunk)
if(make_from)
set_dir(make_from.dir)
/* //I dont wanna set this up yet.
make_from.moveToNullspace()
stored = make_from
*/
qdel(make_from)
mode = DISPOSALMODE_OFF
flush = FALSE
var/obj/structure/disposalpipe/trunk/trunk = locate() in loc
AddComponent(/datum/component/disposal_system_connection)
RegisterSignal(src, COMSIG_DISPOSAL_RECEIVE, PROC_REF(expel))
if(trunk)
SEND_SIGNAL(src, COMSIG_DISPOSAL_LINK, trunk)
air_contents = new(PRESSURE_TANK_VOLUME)
update()
AddComponent(/datum/component/disposal_system_connection)
update_icon()
/obj/machinery/disposal/Destroy()
eject()
return ..()
/obj/machinery/disposal/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
deconstruct()
// attack by item places it in to disposal
/obj/machinery/disposal/attackby(obj/item/I, mob/user)
if(stat & BROKEN || !I || !user)
@@ -86,13 +102,7 @@
if(do_after(user, 2 SECONDS * W.toolspeed, target = src))
if(!src || !W.isOn()) return
to_chat(user, "You sliced the floorweld off the disposal unit.")
var/obj/structure/disposalconstruct/C = new (get_turf(src))
transfer_fingerprints_to(C)
C.ptype = 6 // 6 = disposal unit
C.anchored = TRUE
C.density = TRUE
C.update()
qdel(src)
deconstruct()
return
else
to_chat(user, "You need more welding fuel to complete this task.")
@@ -105,7 +115,7 @@
for(var/obj/item/O in T.contents)
T.remove_from_storage(O,src)
T.update_icon()
update()
update_icon()
return
if(istype(I, /obj/item/material/ashtray))
@@ -115,7 +125,7 @@
for(var/obj/item/O in A.contents)
O.forceMove(src)
A.update_icon()
update()
update_icon()
return
var/obj/item/grab/G = I
@@ -123,7 +133,7 @@
if(ismob(G.affecting))
var/mob/GM = G.affecting
for (var/mob/V in viewers(user))
V.show_message("[user] starts putting [GM.name] into the disposal.", 3)
V.visible_message("[user] starts putting [GM.name] into the disposal.", 3)
if(do_after(user, 2 SECONDS, target = src))
GM.forceMove(src)
for (var/mob/C in viewers(src))
@@ -143,14 +153,22 @@
if(istype(I, /obj/item/holder))
var/obj/item/holder/holder = I
var/mob/victim = holder.held_mob
if(ishuman(victim) || victim.client)
log_and_message_admins("placed [victim] inside \the [src]", user)
if(victim.client)
log_and_message_admins("placed [victim] inside \the [src]", user)
victim.forceMove(src)
qdel(I)
user.visible_message(
span_danger("[user] tosses \the [victim] into \the [src]."),
span_danger("You toss \the [victim] into \the [src]."),
span_warning("Pr-Thunk")
)
update_icon()
return 1
I.forceMove(src)
user.visible_message("[user] places \the [I] into the [src].", "You place \the [I] into the [src].","Ca-Clunk")
update()
update_icon()
// Transform into next machine type
/obj/machinery/disposal/proc/alter_bin_type(mob/user)
@@ -226,7 +244,7 @@
new_bin.stat = stat
new_bin.dir = new_dir
new_bin.mode = mode
new_bin.update() // sets up wall outlets
new_bin.update_icon() // sets up wall outlets
new_bin.update_icon()
new_bin.visible_message("\The [src] reconfigures into \a [new_bin]!")
// Effects
@@ -241,71 +259,66 @@
// mouse drop another mob or self
//
/obj/machinery/disposal/MouseDrop_T(mob/target, mob/user)
/obj/machinery/disposal/MouseDrop_T(mob/living/target, mob/living/user)
if(istype(target))
stuff_mob_in(target, user)
/obj/machinery/disposal/proc/stuff_mob_in(mob/living/target, mob/living/user)
//animals cannot put mobs other than themselves into disposal
if(isanimal(user) && target != user)
return
if(user.stat || !user.canmove || !istype(target))
return
if(target.buckled || get_dist(user, src) > 1 || get_dist(user, target) > 1)
return
//animals cannot put mobs other than themselves into disposal
if(isanimal(user) && target != user)
return
add_fingerprint(user)
var/target_loc = target.loc
var/msg
for (var/mob/V in viewers(user))
if(target == user && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
V.show_message("[user] starts climbing into the disposal.", 3)
if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
if(target.anchored) return
V.show_message("[user] starts stuffing [target.name] into the disposal.", 3)
if(!do_after(user, 2 SECONDS, target))
return
if(target_loc != target.loc)
return
if(target == user && !user.stat && !user.weakened && !user.stunned && !user.paralysis) // if drop self, then climbed in
// must be awake, not stunned or whatever
msg = "[user.name] climbs into the [src]."
to_chat(user, "You climb into the [src].")
log_and_message_admins("climbed into disposals!", user)
else if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
msg = "[user.name] stuffs [target.name] into the [src]!"
to_chat(user, "You stuff [target.name] into the [src]!")
add_attack_logs(user,target,"Disposals dunked")
if(user == target)
user.visible_message("[user] starts climbing into [src]")
else
return
target.visible_message(span_danger("[user] starts stuffing [target] into [src]."), span_userdanger("[user] starts stuffing you into [src]!"))
target.forceMove(src)
for (var/mob/C in viewers(src))
if(C == user)
continue
C.show_message(msg, 3)
update()
return
if(do_after(user, 2 SECONDS, target))
if(!loc)
return
target.forceMove(src)
if(user == target)
user.visible_message("[user] climbs into [src].", span_notice("You climb into [src]"))
log_and_message_admins("climbed into disposals!", user)
else
target.visible_message(span_danger("[user] stuffs [target] into \the [src]."), span_userdanger("[user] stuffs [target] into \the [src]."))
add_attack_logs(user,target,"Disposals dunked")
update_icon()
// attempt to move while inside
/obj/machinery/disposal/relaymove(mob/user)
attempt_escape(user)
// resist to escape the bin
/obj/machinery/disposal/container_resist(mob/living/user)
attempt_escape(user)
/obj/machinery/disposal/proc/attempt_escape(mob/user)
if(user.stat || flushing)
return
if(user.loc == src)
go_out(user)
return
go_out(user)
// leave the disposal
/obj/machinery/disposal/proc/go_out(mob/user)
user.forceMove(get_turf(src))
update()
return
update_icon()
// ai as human but can't flush
/obj/machinery/disposal/attack_ai(mob/user)
add_hiddenprint(user)
tgui_interact(user)
/*
/obj/machinery/disposal/attack_paw()
if(stat & BROKEN)
return
flush = !flush
update_icon()
*/
// human interact with machine
/obj/machinery/disposal/attack_hand(mob/user)
if(stat & BROKEN)
@@ -320,9 +333,19 @@
tgui_interact(user)
else
flush = !flush
update()
update_icon()
return
/obj/machinery/disposal/click_alt(mob/user)
/*
if(user.canUseTopic) //Later...
return
*/
if(get_dist(user, src) > 1 || user.stat) //Until the above exists...
return
flush = !flush
update_icon()
// user interaction
/obj/machinery/disposal/tgui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
@@ -360,22 +383,22 @@
if(flushing)
return
if(isturf(loc))
if(action == "pumpOn")
switch(action)
if("pumpOn")
mode = DISPOSALMODE_CHARGING
update()
if(action == "pumpOff")
update_icon()
if("pumpOff")
mode = DISPOSALMODE_OFF
update()
update_icon()
if(action == "engageHandle")
if("engageHandle")
flush = TRUE
update()
if(action == "disengageHandle")
update_icon()
if("disengageHandle")
flush = FALSE
update()
update_icon()
if(action == "eject")
if("eject")
eject()
return TRUE
@@ -394,10 +417,10 @@
for(var/atom/movable/AM in src)
AM.forceMove(get_turf(src))
AM.pipe_eject(0)
update()
update_icon()
// update the icon & overlays to reflect mode & status
/obj/machinery/disposal/proc/update()
/obj/machinery/disposal/update_icon()
cut_overlays()
if(stat & BROKEN)
icon_state = "disposal-broken"
@@ -446,7 +469,7 @@
update_use_power(USE_POWER_IDLE)
else if(air_contents.return_pressure() >= SEND_PRESSURE)
mode = DISPOSALMODE_CHARGED //if full enough, switch to ready mode
update()
update_icon()
else
pressurize() //otherwise charge
@@ -468,61 +491,119 @@
// perform a flush
/obj/machinery/disposal/proc/flush()
if(flushing)
return
// We don't ever want digestion remains going through disposals, but people understandably thing they're doing right by trashing them
// So let's just delete them instead!
for(var/obj/item/digestion_remains/flushed_item in src)
qdel(flushed_item)
flushing = TRUE
flick("[icon_state]-flush", src)
// wait for animation to finish
addtimer(CALLBACK(src, PROC_REF(flush_animation)), 1 SECOND, TIMER_DELETE_ME)
flush_animation()
//Bit of a nasty way to do this. But sleep()s are nastier.
addtimer(CALLBACK(src, PROC_REF(flush_startup)), 1 SECOND)
/obj/machinery/disposal/proc/flush_animation()
PROTECTED_PROC(TRUE)
// wait for animation to finish
playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0)
addtimer(CALLBACK(src, PROC_REF(flush_resolve)), 0.5 SECOND, TIMER_DELETE_ME)
flick("[icon_state]-flush", src)
/obj/machinery/disposal/proc/flush_startup()
PROTECTED_PROC(TRUE)
if(last_sound < world.time + 1)
playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0)
last_sound = world.time
addtimer(CALLBACK(src, PROC_REF(flush_complete)), 0.5 SECONDS) // wait for animation to finish
/obj/machinery/disposal/proc/flush_complete()
PROTECTED_PROC(TRUE)
if(QDELETED(src))
return
// We don't ever want digestion remains going through disposals, but people understandably thing they're doing right by trashing them
// So let's just delete them instead!
for(var/obj/item/digestion_remains/bone in src)
qdel(bone)
var/list/flushed_items = list()
for(var/atom/movable/AM in src)
flushed_items += AM
/obj/machinery/disposal/proc/flush_resolve()
SEND_SIGNAL(src,COMSIG_DISPOSAL_FLUSH,air_contents)
air_contents = new(PRESSURE_TANK_VOLUME) // new empty gas resv. Disposal packet takes ownership of the original one!
if(stat_tracking)
GLOB.disposals_flush_shift_roundstat++
if(!SEND_SIGNAL(src, COMSIG_DISPOSAL_FLUSH, flushed_items, air_contents)) //If the signal isnt recieved, we'll just expel immediately.
if(length(contents))
expel(flushed_items)
air_contents = new(PRESSURE_TANK_VOLUME) // new empty gas resv. Disposal packet takes ownership of the original one!
flushing = FALSE
// now reset disposal state
flush = FALSE
if(mode == DISPOSALMODE_CHARGED) // if was ready,
mode = DISPOSALMODE_CHARGING // switch to charging
update()
return
update_icon()
// called when area power changes
/obj/machinery/disposal/power_change()
..() // do default setting/reset of stat NOPOWER bit
update() // update icon
update_icon() // update icon
return
/obj/machinery/disposal/hitby(atom/movable/source, datum/thrownthing/throwingdatum)
. = ..()
if(isitem(source) && !istype(source, /obj/item/projectile))
if(prob(75))
source.forceMove(src)
visible_message("\The [source] lands in \the [src].")
else
visible_message("\The [source] bounces off of \the [src]'s rim!")
// called when the bin expels items, generally from a disposal network, or trying to flush without a proper connection.
// should usually only occur if the pipe network if modified or delivering mail
/obj/machinery/disposal/proc/expel(list/expelled_items, datum/gas_mixture/gas)
var/turf/T = get_turf(src)
var/turf/target
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
if(isliving(source))
if(prob(75))
for(var/atom/movable/AM in expelled_items)
target = get_offset_target_turf(loc, rand(5)-rand(5), rand(5)-rand(5))
AM.forceMove(T)
AM.pipe_eject(0)
AM.throw_at(target, 5, 1)
T.assume_air(gas)
/obj/machinery/disposal/hitby(atom/movable/source, datum/thrownthing/throwingdatum)
if(!source.CanEnterDisposals())
return ..()
if(prob(75))
source.forceMove(src)
if(isliving(source))
var/mob/living/to_be_dunked = source
if(ishuman(source) ||to_be_dunked.client)
log_and_message_admins("[source] was thrown into \the [src]", null)
source.forceMove(src)
if(to_be_dunked.client)
log_and_message_admins("has thrown [source] into \the [src]", throwingdatum?.get_thrower())
//flush()
visible_message("\The [source] lands in \the [src].") // "and triggers the flush system!"
else
visible_message("\The [source] lands in \the [src].")
else
visible_message("\The [source] bounces off of \the [src]'s rim!")
return ..()
update_icon()
// Ideally, deconstruct would be a proc on /machinery, but you cant have nice things with polaris.
// AKA: FUKKIN CHANGE THIS WHEN THAT HAPPENS!!!!!1!! pls. -Reo
/obj/machinery/disposal/proc/deconstruct(disassembled = TRUE)
var/turf/T = loc
/* // More nice things... Someday we'll have flags_1 and then have proper support for anything being a hologram.
if(!(flags_1 & NODECONSTRUCT_1))
if(stored)
stored.forceMove(T)
src.transfer_fingerprints_to(stored)
stored.anchored = FALSE
stored.density = TRUE
stored.update_icon()
*/
//This is temporary until the above gets used. Or it's permanant if you're reading this 5 years from now.
var/obj/structure/disposalconstruct/C = new (src.loc/*, null, SOUTH, FALSE, src*/)
transfer_fingerprints_to(C)
C.ptype = 6 // 6 = disposal unit
C.update_icon()
C.anchored = TRUE
C.density = TRUE
//End of "temporary" code
for(var/atom/movable/AM in src)
AM.forceMove(T)
//..() //*cough
qdel(src) //Parent above should do this, but that's not a thing as of writing this.
/obj/machinery/disposal/proc/clean_items()
// Clean items before sending them
@@ -544,7 +625,7 @@
density = FALSE
/obj/machinery/disposal/wall/update()
/obj/machinery/disposal/wall/update_icon()
. = ..()
switch(dir)
if(NORTH)
@@ -567,3 +648,15 @@
#undef SEND_PRESSURE
#undef PRESSURE_TANK_VOLUME
#undef PUMP_MAX_FLOW_RATE
/atom/movable/proc/CanEnterDisposals()
return TRUE
/obj/item/projectile/CanEnterDisposals()
return FALSE
/obj/effect/CanEnterDisposals()
return FALSE
/obj/mecha/CanEnterDisposals()
return FALSE
+62 -8
View File
@@ -1,3 +1,6 @@
#define OUTLET_SCREWED 0
#define OUTLET_UNSCREWED 1
// the disposal outlet machine
/obj/structure/disposaloutlet
name = "disposal outlet"
@@ -6,38 +9,58 @@
icon_state = "outlet"
density = TRUE
anchored = TRUE
var/active = 0
var/active = FALSE // Code appendix.
var/turf/target // this will be where the output objects are 'thrown' to.
var/mode = 0
var/start_eject = 0
var/eject_range = 3 //Did you know, in TGcode, it's a default of 2 tiles?
/obj/structure/disposaloutlet/Initialize(mapload)
. = ..()
AddComponent(/datum/component/disposal_system_connection/disposaloutlet) // Special subtype for directional tossing and it's animation/buzzer
target = get_ranged_target_turf(src, dir, 10)
var/obj/structure/disposalpipe/trunk/trunk = locate() in get_turf(src)
AddComponent(/datum/component/disposal_system_connection)
RegisterSignal(src, COMSIG_DISPOSAL_RECEIVE, PROC_REF(expel))
if(trunk)
SEND_SIGNAL(src, COMSIG_DISPOSAL_LINK, trunk)
/obj/structure/disposaloutlet/Destroy()
target = null
. = ..()
/obj/structure/disposaloutlet/attackby(obj/item/I, mob/user)
if(!I || !user)
return
src.add_fingerprint(user)
if(I.has_tool_quality(TOOL_SCREWDRIVER))
if(mode==0)
mode=1
if(mode == OUTLET_SCREWED)
mode = OUTLET_UNSCREWED
to_chat(user, "You remove the screws around the power connection.")
playsound(src, I.usesound, 50, 1)
return
else if(mode==1)
mode=0
else if(mode == OUTLET_UNSCREWED)
mode = OUTLET_SCREWED
to_chat(user, "You attach the screws around the power connection.")
playsound(src, I.usesound, 50, 1)
return
else if(I.has_tool_quality(TOOL_WELDER) && mode==1)
if(mode == OUTLET_SCREWED)
return ..()
if(I.has_tool_quality(TOOL_WELDER) && mode==1)
var/obj/item/weldingtool/W = I.get_welder()
if(!W.isOn())
to_chat(user, span_warning("Your [W] needs to be on to complete this task."))
if(W.remove_fuel(0,user))
playsound(src, W.usesound, 100, 1)
to_chat(user, "You start slicing the floorweld off the disposal outlet.")
if(do_after(user, 2 SECONDS * W.toolspeed, target = src))
if(!src || !W.isOn()) return
to_chat(user, "You sliced the floorweld off the disposal outlet.")
var/obj/structure/disposalconstruct/C = new (src.loc)
SEND_SIGNAL(src, COMSIG_DISPOSAL_UNLINK)
var/obj/structure/disposalconstruct/C = new (src.loc/*, null, SOUTH, FALSE, src*/)
src.transfer_fingerprints_to(C)
C.set_dir(dir)
C.ptype = 7 // 7 = outlet
C.update()
C.anchored = TRUE
@@ -47,3 +70,34 @@
else
to_chat(user, "You need more welding fuel to complete this task.")
return
else if(I.has_tool_quality(TOOL_MULTITOOL))
var/new_range = tgui_input_number(user, "Input a new ejection distance", "Set ejection strength", 3 , 5, 1, round_value = TRUE)
eject_range = new_range
to_chat(user, span_notice("You set the range on the [src] to [new_range] tiles."))
/obj/structure/disposaloutlet/proc/expel(datum/source, list/received_items, datum/gas_mixture/gas)
SIGNAL_HANDLER
flick("outlet-open", src)
if((start_eject + 30) < world.time)
start_eject = world.time
playsound(src, 'sound/machines/warning-buzzer.ogg', 50, 0, 0)
addtimer(CALLBACK(src, PROC_REF(expel_contents), received_items, gas, TRUE), 2 SECONDS)
else
addtimer(CALLBACK(src, PROC_REF(expel_contents), received_items, gas), 2 SECONDS)
/obj/structure/disposaloutlet/proc/expel_contents(list/ejected_items, datum/gas_mixture/gas, playsound = FALSE)
if(playsound)
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
var/turf/T = get_turf(src)
for(var/atom/movable/AM in ejected_items)
AM.forceMove(T)
AM.pipe_eject(dir)
AM.throw_at(target, eject_range, 1)
T.assume_air(gas)
#undef OUTLET_SCREWED
#undef OUTLET_UNSCREWED
+20 -28
View File
@@ -1,6 +1,7 @@
//a trunk joining to a disposal bin or outlet on the same turf
/obj/structure/disposalpipe/trunk
icon_state = "pipe-t"
var/atom/linked // The linked atom. It should have a /datum/component/disposal_connection to handle receiving disposal packets.
/obj/structure/disposalpipe/trunk/Initialize(mapload)
..()
@@ -10,30 +11,25 @@
/obj/structure/disposalpipe/trunk/LateInitialize()
update()
/obj/structure/disposalpipe/trunk/Destroy()
if(linked) //Linked to something, better unlink.
SEND_SIGNAL(linked, COMSIG_DISPOSAL_UNLINK)
linked = null
. = ..()
// Override attackby so we disallow trunkremoval when somethings ontop
/obj/structure/disposalpipe/trunk/attackby(obj/item/I, mob/user)
//Linked atom.
if(linked)
return
//Disposal constructors
var/turf/T = get_turf(src)
var/obj/structure/disposalconstruct/C = locate() in T
if(C && C.anchored)
return
for(var/obj/structure/disposalconstruct/C in T)
if(C.ptype == DISPOSAL_PIPE_BIN || C.ptype == DISPOSAL_PIPE_OUTLET || C.ptype == DISPOSAL_PIPE_CHUTE)
if(C.anchored)
return
if(!T.is_plating())
return // prevent interaction with T-scanner revealed pipes
add_fingerprint(user)
if(I.has_tool_quality(TOOL_WELDER))
var/obj/item/weldingtool/W = I.get_welder()
if(W.remove_fuel(0,user))
playsound(src, W.usesound, 100, 1)
to_chat(user, "Slicing the disposal pipe.")
if(do_after(user, 3 SECONDS * W.toolspeed, target = src))
if(!src || !W.isOn()) return
welded()
else
to_chat(user, "You must stay still while welding the pipe.")
else
to_chat(user, "You need more welding fuel to cut the pipe.")
return ..() //Run the check from parent, instead of copypasta code
// would transfer to next pipe segment, but we are in a trunk
// if not entering from disposal bin,
@@ -42,15 +38,11 @@
if(H.dir == DOWN) // we just entered from a disposer
return ..() // so do base transfer proc
// Find a disposal handler component. First come first serve.
var/transfered = FALSE
var/turf/T = get_turf(src)
for(var/obj/O in T)
if(SEND_SIGNAL(O,COMSIG_DISPOSAL_RECEIVING,H))
transfered = TRUE
break
if(!transfered) // Check if anything handled it, will be deleted if so.
expel(H, T, 0) // expel at turf if nothing handled it
if(linked)
if(SEND_SIGNAL(src, COMSIG_DISPOSAL_SEND, H))
return //Sent, and handled. Our job is done.
expel(H, get_turf(src), 0) // expel at turf if nothing handled it
return null
+4 -1
View File
@@ -9,7 +9,10 @@
/obj/machinery/disposal/deliveryChute/interact()
return
/obj/machinery/disposal/deliveryChute/update()
/obj/machinery/disposal/deliveryChute/update_icon()
return
/obj/machinery/disposal/deliveryChute/click_alt(mob/user) //No flushing the chute
return
/obj/machinery/disposal/deliveryChute/Bumped(var/atom/movable/AM) //Go straight into the chute