diff --git a/code/__defines/dcs/signals/signals_disposals.dm b/code/__defines/dcs/signals/signals_disposals.dm
index be5b57eff0..d53bd9d744 100644
--- a/code/__defines/dcs/signals/signals_disposals.dm
+++ b/code/__defines/dcs/signals/signals_disposals.dm
@@ -1,11 +1,20 @@
///called when a disposal connected object flushes its contents into the disposal pipe network
#define COMSIG_DISPOSAL_FLUSH "disposal_system_flushing"
-///called when a disposal connected object gets a packet from the disposal pipe network
-#define COMSIG_DISPOSAL_RECEIVING "disposal_system_receiving"
+///called when a disposal trunk attempts to send a packet, to be recieved by an atom with a disposal network connection component.
+#define COMSIG_DISPOSAL_SEND "disposal_system_sending"
-///called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source)
+///called when a disposal connected object recieves an object from it's connected trunk
+#define COMSIG_DISPOSAL_RECEIVE "disposal_system_receiving"
+
+///called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, atom/source)
//#define COMSIG_MOVABLE_DISPOSING "movable_disposing" //This is in signals_atom_movable.dm but kept here for housekeeping.
///Called right after the atom is flushed into a disposal holder and sent through the disposal network: (/obj/structure/disposalholder)
#define COMSIG_ATOM_DISPOSAL_FLUSHED "atom_disposal_flushed"
+
+///called when a disposal connected object attempts to link to a trunk: (/obj/structure/disposalpipe/trunk)
+#define COMSIG_DISPOSAL_LINK "disposal_system_linkage"
+
+///called when a disposal connected object should unlink from a trunk it's attached to.
+#define COMSIG_DISPOSAL_UNLINK "disposal_system_unlink"
diff --git a/code/datums/autolathe/tools.dm b/code/datums/autolathe/tools.dm
index 698cbe1001..f3166f445d 100644
--- a/code/datums/autolathe/tools.dm
+++ b/code/datums/autolathe/tools.dm
@@ -63,3 +63,8 @@
/datum/category_item/autolathe/tools/rsf
name = "rapid service fabricator"
path = /obj/item/rsf
+
+/datum/category_item/autolathe/tools/dest_tagger
+ name = "destination tagger"
+ path = /obj/item/destTagger
+ resources = list(MAT_STEEL = 250, MAT_GLASS = 125)
diff --git a/code/datums/components/machinery/disposal_connection.dm b/code/datums/components/machinery/disposal_connection.dm
index 57a0c7e81e..47b3160d11 100644
--- a/code/datums/components/machinery/disposal_connection.dm
+++ b/code/datums/components/machinery/disposal_connection.dm
@@ -1,75 +1,104 @@
///Disposal connection component, allows an atom to recieve and send disposal packages if attached to a disposal trunk.
/datum/component/disposal_system_connection
- VAR_PROTECTED/obj/disposal_owner = null
+ //The connected trunk. Also determines if we're linked already or not.
+ var/obj/structure/disposalpipe/trunk/connected_trunk = null
-/datum/component/disposal_system_connection/Initialize()
+ var/atom/disposal_owner
+ /// The proc that the owner has that'll accept a list of items from recieved disposal packets.
+ var/visible_connection
+
+/datum/component/disposal_system_connection/Initialize(visibly_connects = TRUE)
+ if(!isatom(parent))
+ return COMPONENT_INCOMPATIBLE
+ if(isarea(parent))
+ return COMPONENT_INCOMPATIBLE
disposal_owner = parent
- RegisterSignal(disposal_owner, COMSIG_DISPOSAL_FLUSH, PROC_REF(on_flush))
- RegisterSignal(disposal_owner, COMSIG_DISPOSAL_RECEIVING, PROC_REF(on_recieve))
- RegisterSignal(disposal_owner, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
+ visible_connection = visibly_connects
/datum/component/disposal_system_connection/Destroy()
- UnregisterSignal(disposal_owner, COMSIG_DISPOSAL_FLUSH)
- UnregisterSignal(disposal_owner, COMSIG_DISPOSAL_RECEIVING)
- UnregisterSignal(disposal_owner, COMSIG_ATOM_EXAMINE)
- disposal_owner = null
+ if(connected_trunk)
+ UnregisterSignal(connected_trunk, COMSIG_DISPOSAL_SEND)
+ connected_trunk = null
. = ..()
+ disposal_owner = null
+
+/datum/component/disposal_system_connection/RegisterWithParent()
+ RegisterSignal(disposal_owner, COMSIG_DISPOSAL_FLUSH, PROC_REF(on_flush))
+ RegisterSignal(disposal_owner, COMSIG_DISPOSAL_LINK, PROC_REF(link_to_trunk))
+ RegisterSignal(disposal_owner, COMSIG_DISPOSAL_UNLINK, PROC_REF(unlink_from_trunk))
+ RegisterSignal(disposal_owner, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
+
+
+/datum/component/disposal_system_connection/UnregisterFromParent()
+ UnregisterSignal(disposal_owner, COMSIG_DISPOSAL_FLUSH)
+ UnregisterSignal(disposal_owner, COMSIG_DISPOSAL_LINK)
+ UnregisterSignal(disposal_owner, COMSIG_DISPOSAL_UNLINK)
+ UnregisterSignal(disposal_owner, COMSIG_ATOM_EXAMINE)
+
// Signal handling
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-/datum/component/disposal_system_connection/proc/on_flush(datum/source,datum/gas_mixture/flush_gas)
+/datum/component/disposal_system_connection/proc/on_flush(datum/source, list/flushed_items, datum/gas_mixture/flush_gas)
SIGNAL_HANDLER
SHOULD_NOT_OVERRIDE(TRUE)
- if(!can_accept())
- return FALSE
// Important note, the flush_gas will be passed to the disposal packet when it's made. Caller should make a fresh gasmix datum after flushing this one!
- return handle_flush(flush_gas)
+ return handle_flush(flushed_items, flush_gas)
-/datum/component/disposal_system_connection/proc/on_recieve(datum/source,obj/structure/disposalholder/packet)
+/datum/component/disposal_system_connection/proc/link_to_trunk(datum/source, obj/structure/disposalpipe/trunk/trunk)
SIGNAL_HANDLER
SHOULD_NOT_OVERRIDE(TRUE)
- if(!can_accept())
+ if(!trunk)
return FALSE
+ if(trunk.linked) //Already linked to something
+ return FALSE
+ connected_trunk = trunk
+ trunk.linked = disposal_owner
+ RegisterSignal(trunk, COMSIG_DISPOSAL_SEND, PROC_REF(on_recieve))
+
+/datum/component/disposal_system_connection/proc/unlink_from_trunk(datum/source)
+ SIGNAL_HANDLER
+ SHOULD_NOT_OVERRIDE(TRUE)
+ if(connected_trunk)
+ UnregisterSignal(connected_trunk, COMSIG_DISPOSAL_SEND)
+ connected_trunk = null
+
+/datum/component/disposal_system_connection/proc/on_recieve(datum/source, obj/structure/disposalholder/packet)
+ SIGNAL_HANDLER
+ SHOULD_NOT_OVERRIDE(TRUE)
return handle_expel(packet)
/datum/component/disposal_system_connection/proc/on_examine(datum/source, mob/user, list/examine_texts)
SIGNAL_HANDLER
- var/has_connection = FALSE
- if(can_accept() && (locate(/obj/structure/disposalpipe/trunk) in get_turf(disposal_owner)))
- has_connection = TRUE
- examine_texts += span_notice("It [has_connection ? "is connected" : "can be connected"] to a disposal pipe network.")
+ if(!visible_connection)
+ return
+ examine_texts += span_notice("It [connected_trunk ? "is connected" : "can be connected"] to a disposal pipe network.")
// Flush handling, can be override by subtypes but excepts parent proc to handle core logic
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-/datum/component/disposal_system_connection/proc/handle_flush(datum/gas_mixture/flush_gas)
+/datum/component/disposal_system_connection/proc/handle_flush(list/flushed_items, datum/gas_mixture/flush_gas)
PROTECTED_PROC(TRUE)
SHOULD_CALL_PARENT(TRUE)
var/obj/structure/disposalholder/packet = new() // virtual holder object which actually travels through the pipes.
- packet.init(get_flushed_item_list(), flush_gas)
- finish_flush(packet)
- return TRUE
+ packet.init(flushed_items, flush_gas)
-/datum/component/disposal_system_connection/proc/finish_flush(obj/structure/disposalholder/packet)
- PROTECTED_PROC(TRUE)
- SHOULD_CALL_PARENT(TRUE)
// if no trunk connected, expel immediately
- var/obj/structure/disposalpipe/trunk/trunk = locate() in get_turf(disposal_owner)
- if(!trunk)
+ if(!connected_trunk)
handle_expel(packet)
- return
+ return TRUE
// start the holder processing movement
- packet.forceMove(trunk)
+ packet.forceMove(connected_trunk)
packet.active = TRUE
packet.set_dir(DOWN)
packet.move()
+ return TRUE
+
// Expel handling, can be override by subtypes but excepts parent proc to handle core logic
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-/datum/component/disposal_system_connection/proc/handle_expel(obj/structure/disposalholder/packet, delay_time = 0)
+/datum/component/disposal_system_connection/proc/handle_expel(obj/structure/disposalholder/packet)
// Returns true if our owner could handle this packet, used by our child procs to animate our owner.
PROTECTED_PROC(TRUE)
- SHOULD_CALL_PARENT(TRUE)
if(!packet || QDELETED(packet))
return FALSE
@@ -82,71 +111,5 @@
var/datum/gas_mixture/gas = new()
gas.copy_from(packet.gas)
qdel(packet)
-
- // Handle expelling stuff, most things have a delay before ejecting.
- if(delay_time <= 0) // Someone is going to pass a negative, I just know it. No, BAD, cutting this off before it gets the chance.
- expel_finish(expelled_items, gas)
- else
- addtimer(CALLBACK(src, PROC_REF(expel_finish), expelled_items, gas), delay_time, TIMER_DELETE_ME)
+ SEND_SIGNAL(disposal_owner, COMSIG_DISPOSAL_RECEIVE, expelled_items, gas)
return TRUE
-
-/datum/component/disposal_system_connection/proc/expel_finish(list/expelled_items,datum/gas_mixture/gas)
- PROTECTED_PROC(TRUE)
- SHOULD_CALL_PARENT(TRUE)
- // This proc has some checks just incase we have a subtype that wants to handle expelled items or if it vents gasses itself.
- // This way it can just pass nulls to this parent proc if it does it's own handling for those things. Like a machine that eats all stuff dumped into it instead of ejecting.
-
- // Drop all those items
- if(expelled_items.len)
- var/turf/target = get_expel_target()
- for(var/atom/movable/AM in expelled_items)
- if(QDELETED(AM))
- continue
- AM.forceMove(get_turf(disposal_owner))
- AM.pipe_eject(disposal_owner.dir)
- if(istype(AM,/mob/living/silicon/robot/drone)) //Drones keep smashing windows from being fired out of chutes. Bad for the station. ~Z
- continue
- AM.throw_at(target, 3, 1)
- expelled_items.Cut()
-
- // vent gasses to turf
- if(gas)
- if(gas.return_pressure() > 0)
- playsound(disposal_owner, 'sound/machines/hiss.ogg', 50, 0, 0)
- var/turf/T = get_turf(disposal_owner)
- if(T)
- T.assume_air(gas)
- qdel(gas)
-
-// Overridable procs for easily customizing subtypes
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-/// Override this to add additional checks if an object can flush or accept incoming packets
-/datum/component/disposal_system_connection/proc/can_accept()
- PROTECTED_PROC(TRUE)
- return disposal_owner.anchored
-
-/// Override this to launch items in a specific direction
-/datum/component/disposal_system_connection/proc/get_expel_target()
- PROTECTED_PROC(TRUE)
- return get_offset_target_turf(get_turf(disposal_owner), rand(5)-rand(5), rand(5)-rand(5))
-
-/// Override this to give a custom list of items to flush instead of just the contents of the owner
-/datum/component/disposal_system_connection/proc/get_flushed_item_list()
- PROTECTED_PROC(TRUE)
- return disposal_owner.contents
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Subtypes for handling how things are animated, if items are spat out, or deciding what items inside an object are flushed
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Disposal outlets, needs to animate with a timed buzzer before stuff ejects
-/datum/component/disposal_system_connection/disposaloutlet/handle_expel(obj/structure/disposalholder/packet, delay_time)
- . = ..(packet,3 SECONDS)
- if(.)
- flick("outlet-open", disposal_owner)
- playsound(disposal_owner, 'sound/machines/warning-buzzer.ogg', 50, 0, 0)
-
-/datum/component/disposal_system_connection/disposaloutlet/get_expel_target()
- return get_ranged_target_turf(get_turf(disposal_owner), disposal_owner.dir, 10)
diff --git a/code/datums/components/traits/unlucky.dm b/code/datums/components/traits/unlucky.dm
index a59a5b1e64..d28ef3ef8e 100644
--- a/code/datums/components/traits/unlucky.dm
+++ b/code/datums/components/traits/unlucky.dm
@@ -195,7 +195,7 @@
our_guy.visible_message(span_danger("[our_guy] slips on a spill near the [evil_disposal] and falls in!"), span_boldwarning("You slip on a spill near the [evil_disposal] and fall in!"))
living_guy.forceMove(evil_disposal)
evil_disposal.flush = TRUE
- evil_disposal.update()
+ evil_disposal.update_icon()
living_guy.Stun(5)
consume_omen()
return
diff --git a/code/game/objects/stumble_into_vr.dm b/code/game/objects/stumble_into_vr.dm
index 43206c743e..911bd23262 100644
--- a/code/game/objects/stumble_into_vr.dm
+++ b/code/game/objects/stumble_into_vr.dm
@@ -28,7 +28,7 @@
M.Weaken(2)
M.forceMove(src)
M.stop_flying()
- update()
+ update_icon()
/obj/structure/inflatable/stumble_into(mob/living/M)
playsound(src, "sound/effects/Glasshit.ogg", 25, 1, -1)
diff --git a/code/modules/recycling/disposal_bin_subtypes.dm b/code/modules/recycling/disposal_bin_subtypes.dm
index 0df64a3b63..851e512054 100644
--- a/code/modules/recycling/disposal_bin_subtypes.dm
+++ b/code/modules/recycling/disposal_bin_subtypes.dm
@@ -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"
diff --git a/code/modules/recycling/disposal_holder.dm b/code/modules/recycling/disposal_holder.dm
index de9855acb0..64fcd10c30 100644
--- a/code/modules/recycling/disposal_holder.dm
+++ b/code/modules/recycling/disposal_holder.dm
@@ -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, "CLONG, clong!")
+ M.show_message("CLONG, clong!", 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 ..()
diff --git a/code/modules/recycling/disposal_machines.dm b/code/modules/recycling/disposal_machines.dm
index 350beac682..8803673b6b 100644
--- a/code/modules/recycling/disposal_machines.dm
+++ b/code/modules/recycling/disposal_machines.dm
@@ -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
diff --git a/code/modules/recycling/disposal_outlet.dm b/code/modules/recycling/disposal_outlet.dm
index 4415379117..e974055387 100644
--- a/code/modules/recycling/disposal_outlet.dm
+++ b/code/modules/recycling/disposal_outlet.dm
@@ -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
diff --git a/code/modules/recycling/disposal_trunk.dm b/code/modules/recycling/disposal_trunk.dm
index 947e9c6f83..27317c7d11 100644
--- a/code/modules/recycling/disposal_trunk.dm
+++ b/code/modules/recycling/disposal_trunk.dm
@@ -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
diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm
index 024bc0b433..1e2b759212 100755
--- a/code/modules/recycling/sortingmachinery.dm
+++ b/code/modules/recycling/sortingmachinery.dm
@@ -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