mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-23 23:56:46 +01:00
preliminary reorganization of conveyors, disposals, packaging, etc (#6706)
factorio gaming --------- Co-authored-by: LordME <58342752+TheLordME@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
# Industry Module
|
||||
|
||||
tl;dr if it belongs in a game of factorio it belongs here
|
||||
|
||||
contains:
|
||||
|
||||
- disposals
|
||||
- conveyors
|
||||
- general package code; while this is equally belonging in cargo and here, it's used here more.
|
||||
@@ -0,0 +1,211 @@
|
||||
#define OFF 0
|
||||
#define FORWARDS 1
|
||||
#define BACKWARDS -1
|
||||
|
||||
//conveyor2 is pretty much like the original, except it supports corners, but not diverters.
|
||||
//note that corner pieces transfer stuff clockwise when running forward, and anti-clockwise backwards.
|
||||
// todo: main-like stacks of conveyor belts.
|
||||
|
||||
/obj/machinery/conveyor
|
||||
icon = 'icons/obj/recycling.dmi'
|
||||
icon_state = "conveyor_map"
|
||||
name = "conveyor belt"
|
||||
desc = "A conveyor belt."
|
||||
plane = TURF_PLANE
|
||||
layer = ABOVE_TURF_LAYER
|
||||
anchored = 1
|
||||
circuit = /obj/item/circuitboard/conveyor
|
||||
speed_process = TRUE
|
||||
/// What we set things to glide size to when they are being moved by us
|
||||
var/conveyor_glide_size = 8
|
||||
|
||||
var/operating = OFF // 1 if running forward, -1 if backwards, 0 if off
|
||||
var/operable = 1 // true if can operate (no broken segments in this belt run)
|
||||
var/forwards // this is the default (forward) direction, set by the map dir
|
||||
var/backwards // hopefully self-explanatory
|
||||
var/movedir // the actual direction to move stuff in
|
||||
|
||||
var/id = "" // the control ID - must match controller ID
|
||||
|
||||
// create a conveyor
|
||||
/obj/machinery/conveyor/Initialize(mapload, newdir, on = 0)
|
||||
. = ..()
|
||||
icon_state = "conveyor0"
|
||||
if(newdir)
|
||||
setDir(newdir)
|
||||
|
||||
update_dir()
|
||||
|
||||
if(on)
|
||||
operating = FORWARDS
|
||||
setmove()
|
||||
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/stock_parts/gear(src)
|
||||
component_parts += new /obj/item/stock_parts/motor(src)
|
||||
component_parts += new /obj/item/stock_parts/gear(src)
|
||||
component_parts += new /obj/item/stock_parts/motor(src)
|
||||
component_parts += new /obj/item/stack/cable_coil(src,5)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/conveyor/examine(mob/user, dist)
|
||||
. = ..()
|
||||
// give a hint about catastrophic crowding
|
||||
if(length(loc?.contents) > TURF_CROWDING_HARD_LIMIT)
|
||||
. += SPAN_WARNING("There's far too many things on [src] for it to move!")
|
||||
|
||||
/obj/machinery/conveyor/proc/setmove()
|
||||
if(operating == FORWARDS)
|
||||
movedir = forwards
|
||||
else if(operating == BACKWARDS)
|
||||
movedir = backwards
|
||||
else
|
||||
operating = OFF
|
||||
update()
|
||||
|
||||
/obj/machinery/conveyor/setDir()
|
||||
. =..()
|
||||
update_dir()
|
||||
|
||||
/obj/machinery/conveyor/Crossed(atom/movable/AM)
|
||||
. = ..()
|
||||
if(operating)
|
||||
AM.set_glide_size(conveyor_glide_size)
|
||||
|
||||
/obj/machinery/conveyor/Uncrossed(atom/movable/AM)
|
||||
. = ..()
|
||||
if(operating)
|
||||
AM.reset_glide_size()
|
||||
|
||||
/obj/machinery/conveyor/proc/update_dir()
|
||||
if(!(dir in GLOB.cardinal)) // Diagonal. Forwards is *away* from dir, curving to the right.
|
||||
forwards = turn(dir, 135)
|
||||
backwards = turn(dir, 45)
|
||||
else
|
||||
forwards = dir
|
||||
backwards = turn(dir, 180)
|
||||
|
||||
/obj/machinery/conveyor/proc/update()
|
||||
if(machine_stat & BROKEN)
|
||||
icon_state = "conveyor-broken"
|
||||
operating = OFF
|
||||
return
|
||||
if(!operable)
|
||||
operating = OFF
|
||||
if(machine_stat & NOPOWER)
|
||||
operating = OFF
|
||||
if(operating)
|
||||
for(var/atom/movable/AM in loc)
|
||||
AM.set_glide_size(conveyor_glide_size)
|
||||
icon_state = "conveyor[operating]"
|
||||
|
||||
// machine process
|
||||
// move items to the target location
|
||||
/obj/machinery/conveyor/process(delta_time)
|
||||
if(machine_stat & (BROKEN | NOPOWER))
|
||||
return
|
||||
if(!operating)
|
||||
return
|
||||
use_power(10)
|
||||
// check catastrophic crowding
|
||||
if(length(loc.contents) > TURF_CROWDING_HARD_LIMIT)
|
||||
return
|
||||
// todo: this is still kind of tick-dependent, and will result in issues
|
||||
// todo: conveyors should be on their own subsystem that lets it run a collect-sweep cycle?
|
||||
addtimer(CALLBACK(src, PROC_REF(convey), loc.contents.Copy()), 1)
|
||||
|
||||
/**
|
||||
* Conveys a list of movables.
|
||||
*
|
||||
* * This does filter to make sure the movables in question are still in us.
|
||||
* * This is done in a separate proc so that order of operations from process() is canonical.
|
||||
*/
|
||||
/obj/machinery/conveyor/proc/convey(list/atom/movable/to_convey)
|
||||
var/turf/target_turf = get_step(src, movedir)
|
||||
if(!target_turf)
|
||||
return
|
||||
// limit items to soft crowding limit
|
||||
to_convey.len = clamp(TURF_CROWDING_SOFT_LIMIT - length(target_turf.contents), 0, length(to_convey))
|
||||
if(!length(to_convey))
|
||||
return
|
||||
// move items
|
||||
for(var/atom/movable/AM in to_convey)
|
||||
// todo: movement force check?
|
||||
if(AM.anchored)
|
||||
continue
|
||||
if(AM.loc != loc)
|
||||
continue
|
||||
step(AM, movedir)
|
||||
|
||||
// attack with item, place item on conveyor
|
||||
/obj/machinery/conveyor/attackby(var/obj/item/I, mob/user)
|
||||
if(default_deconstruction_screwdriver(user, I))
|
||||
return CLICKCHAIN_DO_NOT_PROPAGATE
|
||||
if(default_deconstruction_crowbar(user, I))
|
||||
return CLICKCHAIN_DO_NOT_PROPAGATE
|
||||
|
||||
if(istype(I, /obj/item/multitool))
|
||||
if(panel_open)
|
||||
var/input = sanitize(input(usr, "What id would you like to give this conveyor?", "Multitool-Conveyor interface", id))
|
||||
if(!input)
|
||||
to_chat(user, "No input found. Please hang up and try your call again.")
|
||||
return CLICKCHAIN_DO_NOT_PROPAGATE
|
||||
id = input
|
||||
for(var/obj/machinery/conveyor_switch/C in GLOB.machines)
|
||||
if(C.id == id)
|
||||
C.conveyors |= src
|
||||
return CLICKCHAIN_DO_NOT_PROPAGATE
|
||||
|
||||
if(user.a_intent == INTENT_HELP)
|
||||
user.transfer_item_to_loc(I, loc)
|
||||
return CLICKCHAIN_DO_NOT_PROPAGATE
|
||||
return ..()
|
||||
|
||||
// attack with hand, move pulled object onto conveyor
|
||||
/obj/machinery/conveyor/attack_hand(mob/user, list/params)
|
||||
if(!CHECK_ALL_MOBILITY(user, MOBILITY_CAN_MOVE | MOBILITY_CAN_USE))
|
||||
return
|
||||
if(isnull(user.pulling) || user.pulling.anchored)
|
||||
return
|
||||
if ((user.pulling.loc != user.loc && get_dist(user, user.pulling) > 1))
|
||||
return
|
||||
if (ismob(user.pulling))
|
||||
var/mob/M = user.pulling
|
||||
M.stop_pulling()
|
||||
step(user.pulling, get_dir(user.pulling.loc, src))
|
||||
user.stop_pulling()
|
||||
else
|
||||
step(user.pulling, get_dir(user.pulling.loc, src))
|
||||
user.stop_pulling()
|
||||
|
||||
// make the conveyor broken
|
||||
// also propagate inoperability to any connected conveyor with the same ID
|
||||
/obj/machinery/conveyor/proc/broken()
|
||||
machine_stat |= BROKEN
|
||||
update()
|
||||
|
||||
var/obj/machinery/conveyor/C = locate() in get_step(src, dir)
|
||||
if(C)
|
||||
C.set_operable(dir, id, 0)
|
||||
|
||||
C = locate() in get_step(src, turn(dir,180))
|
||||
if(C)
|
||||
C.set_operable(turn(dir,180), id, 0)
|
||||
|
||||
|
||||
//set the operable var if ID matches, propagating in the given direction
|
||||
|
||||
/obj/machinery/conveyor/proc/set_operable(stepdir, match_id, op)
|
||||
|
||||
if(id != match_id)
|
||||
return
|
||||
operable = op
|
||||
|
||||
update()
|
||||
var/obj/machinery/conveyor/C = locate() in get_step(src, stepdir)
|
||||
if(C)
|
||||
C.set_operable(stepdir, id, op)
|
||||
|
||||
/obj/machinery/conveyor/power_change()
|
||||
..()
|
||||
update()
|
||||
@@ -0,0 +1,128 @@
|
||||
/obj/machinery/conveyor_switch
|
||||
|
||||
name = "conveyor switch"
|
||||
desc = "A conveyor control switch."
|
||||
icon = 'icons/obj/recycling.dmi'
|
||||
icon_state = "switch-off"
|
||||
var/position = 0 // 0 off, -1 reverse, 1 forward
|
||||
var/last_pos = -1 // last direction setting
|
||||
var/operated = 1 // true if just operated
|
||||
|
||||
var/id = "" // must match conveyor IDs to control them
|
||||
|
||||
var/list/conveyors // the list of converyors that are controlled by this switch
|
||||
anchored = 1
|
||||
|
||||
/obj/machinery/conveyor_switch/two_way_on
|
||||
position = 1
|
||||
|
||||
|
||||
/obj/machinery/conveyor_switch/Initialize(mapload)
|
||||
. = ..()
|
||||
update()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/conveyor_switch/LateInitialize()
|
||||
conveyors = list()
|
||||
for(var/obj/machinery/conveyor/C in GLOB.machines)
|
||||
if(C.id == id)
|
||||
conveyors += C
|
||||
|
||||
// update the icon depending on the position
|
||||
|
||||
/obj/machinery/conveyor_switch/proc/update()
|
||||
if(position<0)
|
||||
icon_state = "switch-rev"
|
||||
else if(position>0)
|
||||
icon_state = "switch-fwd"
|
||||
else
|
||||
icon_state = "switch-off"
|
||||
|
||||
// timed process
|
||||
// if the switch changed, update the linked conveyors
|
||||
|
||||
/obj/machinery/conveyor_switch/process(delta_time)
|
||||
if(!operated)
|
||||
return
|
||||
operated = 0
|
||||
|
||||
for(var/obj/machinery/conveyor/C in conveyors)
|
||||
C.operating = position
|
||||
C.setmove()
|
||||
|
||||
// attack with hand, switch position
|
||||
/obj/machinery/conveyor_switch/attack_hand(mob/user, list/params)
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
|
||||
if(position == 0)
|
||||
if(last_pos < 0)
|
||||
position = 1
|
||||
last_pos = 0
|
||||
else
|
||||
position = -1
|
||||
last_pos = 0
|
||||
else
|
||||
last_pos = position
|
||||
position = 0
|
||||
|
||||
operated = 1
|
||||
update()
|
||||
|
||||
// find any switches with same id as this one, and set their positions to match us
|
||||
for(var/obj/machinery/conveyor_switch/S in GLOB.machines)
|
||||
if(S.id == src.id)
|
||||
S.position = position
|
||||
S.update()
|
||||
|
||||
/obj/machinery/conveyor_switch/attackby(var/obj/item/I, mob/user)
|
||||
if(default_deconstruction_screwdriver(user, I))
|
||||
return
|
||||
|
||||
if(istype(I, /obj/item/weldingtool))
|
||||
if(panel_open)
|
||||
var/obj/item/weldingtool/WT = I
|
||||
if(!WT.remove_fuel(0, user))
|
||||
to_chat(user, "The welding tool must be on to complete this task.")
|
||||
return
|
||||
playsound(src, WT.tool_sound, 50, 1)
|
||||
if(do_after(user, 20 * WT.tool_speed))
|
||||
if(!src || !WT.isOn()) return
|
||||
to_chat(user, "<span class='notice'>You deconstruct the frame.</span>")
|
||||
new /obj/item/stack/material/steel( src.loc, 2 )
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(istype(I, /obj/item/multitool))
|
||||
if(panel_open)
|
||||
var/input = sanitize(input(usr, "What id would you like to give this conveyor switch?", "Multitool-Conveyor interface", id))
|
||||
if(!input)
|
||||
to_chat(user, "No input found. Please hang up and try your call again.")
|
||||
return
|
||||
id = input
|
||||
conveyors = list() // Clear list so they aren't double added.
|
||||
for(var/obj/machinery/conveyor/C in GLOB.machines)
|
||||
if(C.id == id)
|
||||
conveyors += C
|
||||
return
|
||||
|
||||
/obj/machinery/conveyor_switch/oneway
|
||||
var/convdir = 1 //Set to 1 or -1 depending on which way you want the convayor to go. (In other words keep at 1 and set the proper dir on the belts.)
|
||||
desc = "A conveyor control switch. It appears to only go in one direction."
|
||||
|
||||
// attack with hand, switch position
|
||||
/obj/machinery/conveyor_switch/oneway/attack_hand(mob/user, list/params)
|
||||
if(position == 0)
|
||||
position = convdir
|
||||
else
|
||||
position = 0
|
||||
|
||||
operated = 1
|
||||
update()
|
||||
|
||||
// find any switches with same id as this one, and set their positions to match us
|
||||
for(var/obj/machinery/conveyor_switch/S in GLOB.machines)
|
||||
if(S.id == src.id)
|
||||
S.position = position
|
||||
S.update()
|
||||
@@ -0,0 +1,45 @@
|
||||
/obj/item/destTagger
|
||||
name = "destination tagger"
|
||||
desc = "Used to set the destination of properly wrapped packages."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "dest_tagger"
|
||||
var/currTag = 0
|
||||
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
item_state = "electronic"
|
||||
slot_flags = SLOT_BELT
|
||||
|
||||
/obj/item/destTagger/ui_state()
|
||||
return GLOB.inventory_state
|
||||
|
||||
/obj/item/destTagger/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "DestinationTagger", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/destTagger/ui_data(mob/user, datum/tgui/ui)
|
||||
var/list/data = ..()
|
||||
|
||||
data["currTag"] = currTag
|
||||
data["taggerLocs"] = GLOB.tagger_locations
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/destTagger/attack_self(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/destTagger/ui_act(action, list/params, datum/tgui/ui)
|
||||
if(..())
|
||||
return TRUE
|
||||
add_fingerprint(usr)
|
||||
switch(action)
|
||||
if("set_tag")
|
||||
var/new_tag = params["tag"]
|
||||
if(!(new_tag in GLOB.tagger_locations))
|
||||
return FALSE
|
||||
currTag = new_tag
|
||||
. = TRUE
|
||||
@@ -0,0 +1,28 @@
|
||||
// todo: /machinery/disposal that trunks connect to
|
||||
|
||||
// called when movable is expelled from a disposal pipe or outlet
|
||||
// by default does nothing, override for special behaviour
|
||||
/atom/movable/proc/pipe_eject(direction)
|
||||
return
|
||||
|
||||
// check if mob has client, if so restore client view on eject
|
||||
/mob/pipe_eject(direction)
|
||||
update_perspective()
|
||||
|
||||
/obj/effect/debris/cleanable/blood/gibs/pipe_eject(direction)
|
||||
var/list/dirs
|
||||
if(direction)
|
||||
dirs = list( direction, turn(direction, -45), turn(direction, 45))
|
||||
else
|
||||
dirs = GLOB.alldirs.Copy()
|
||||
|
||||
src.streak(dirs)
|
||||
|
||||
/obj/effect/debris/cleanable/blood/gibs/robot/pipe_eject(direction)
|
||||
var/list/dirs
|
||||
if(direction)
|
||||
dirs = list( direction, turn(direction, -45), turn(direction, 45))
|
||||
else
|
||||
dirs = GLOB.alldirs.Copy()
|
||||
|
||||
src.streak(dirs)
|
||||
@@ -0,0 +1,513 @@
|
||||
// Disposal bin
|
||||
// Holds items for disposal into pipe system
|
||||
// Draws air from turf, gradually charges internal reservoir
|
||||
// Once full (~1 atm), uses air resv to flush items into the pipes
|
||||
// Automatically recharges air (unless off), will flush when ready if pre-set
|
||||
// Can hold items and human size things, no other draggables
|
||||
// Toilets are a type of disposal bin for small objects only and work on magic. By magic, I mean torque rotation
|
||||
///kPa - assume the inside of a dispoal pipe is 1 atm, so that needs to be added.
|
||||
#define SEND_PRESSURE (700 + ONE_ATMOSPHERE)
|
||||
///L
|
||||
#define PRESSURE_TANK_VOLUME 150
|
||||
///L/s - 4 m/s using a 15 cm by 15 cm inlet
|
||||
#define PUMP_MAX_FLOW_RATE 90
|
||||
// todo: /obj/machinery/disposal/chute
|
||||
/obj/machinery/disposal
|
||||
name = "disposal unit"
|
||||
desc = "A pneumatic waste disposal unit."
|
||||
icon = 'icons/obj/pipes/disposal.dmi'
|
||||
icon_state = "disposal"
|
||||
atom_colouration_system = FALSE
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
pass_flags_self = ATOM_PASS_OVERHEAD_THROW
|
||||
var/datum/gas_mixture/air_contents // internal reservoir
|
||||
var/mode = 1 // item mode 0=off 1=charging 2=charged
|
||||
var/flush = FALSE // true if flush handle is pulled
|
||||
var/obj/structure/disposalpipe/trunk/trunk = null // the attached pipe trunk
|
||||
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 = 0
|
||||
active_power_usage = 2200 //the pneumatic pump power. 3 HP ~ 2200W
|
||||
idle_power_usage = 100
|
||||
|
||||
// create a new disposal
|
||||
// find the attached trunk (if present) and init gas resvr.
|
||||
/obj/machinery/disposal/Initialize(mapload, newdir)
|
||||
. = ..()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/disposal/LateInitialize()
|
||||
. = ..()
|
||||
trunk = locate() in src.loc
|
||||
if(!trunk)
|
||||
mode = 0
|
||||
flush = FALSE
|
||||
else
|
||||
trunk.linked = src // link the pipe trunk to self
|
||||
|
||||
air_contents = new/datum/gas_mixture(PRESSURE_TANK_VOLUME)
|
||||
update()
|
||||
|
||||
/obj/machinery/disposal/Destroy()
|
||||
eject()
|
||||
if(trunk)
|
||||
trunk.linked = null
|
||||
return ..()
|
||||
|
||||
// attack by item places it in to disposal
|
||||
/obj/machinery/disposal/attackby(var/obj/item/I, var/mob/user)
|
||||
if(user.a_intent != INTENT_HELP)
|
||||
return ..()
|
||||
|
||||
. = CLICKCHAIN_DO_NOT_PROPAGATE
|
||||
|
||||
if(machine_stat & BROKEN || !I || !user)
|
||||
return
|
||||
|
||||
add_fingerprint(user, 0, I)
|
||||
if(mode<=0) // It's off
|
||||
if(I.is_screwdriver())
|
||||
if(contents.len > 0)
|
||||
to_chat(user, "Eject the items first!")
|
||||
return
|
||||
if(mode==0) // It's off but still not unscrewed
|
||||
mode=-1 // Set it to doubleoff l0l
|
||||
playsound(src, I.tool_sound, 50, 1)
|
||||
to_chat(user, "You remove the screws around the power connection.")
|
||||
return
|
||||
else if(mode==-1)
|
||||
mode=0
|
||||
playsound(src, I.tool_sound, 50, 1)
|
||||
to_chat(user, "You attach the screws around the power connection.")
|
||||
return
|
||||
else if(istype(I, /obj/item/weldingtool) && mode==-1)
|
||||
if(contents.len > 0)
|
||||
to_chat(user, "Eject the items first!")
|
||||
return
|
||||
var/obj/item/weldingtool/W = I
|
||||
if(W.remove_fuel(0,user))
|
||||
playsound(src, W.tool_sound, 100, 1)
|
||||
to_chat(user, "You start slicing the floorweld off the disposal unit.")
|
||||
|
||||
if(do_after(user,20 * W.tool_speed))
|
||||
if(!src || !W.isOn()) return
|
||||
to_chat(user, "You sliced the floorweld off the disposal unit.")
|
||||
var/obj/structure/disposalconstruct/C = new (src.loc)
|
||||
src.transfer_fingerprints_to(C)
|
||||
C.ptype = 6 // 6 = disposal unit
|
||||
C.anchored = 1
|
||||
C.density = 1
|
||||
C.update()
|
||||
qdel(src)
|
||||
return
|
||||
else
|
||||
to_chat(user, "You need more welding fuel to complete this task.")
|
||||
return
|
||||
|
||||
if(istype(I, /obj/item/storage/bag/trash))
|
||||
var/obj/item/storage/bag/trash/T = I
|
||||
to_chat(user, "<font color=#4F49AF>You empty the bag.</font>")
|
||||
for(var/obj/item/O in T.contents)
|
||||
T.obj_storage.remove(O, src)
|
||||
T.update_icon()
|
||||
update()
|
||||
return
|
||||
|
||||
if(istype(I, /obj/item/material/ashtray))
|
||||
var/obj/item/material/ashtray/A = I
|
||||
if(A.contents.len > 0)
|
||||
user.visible_message("<span class='notice'>\The [user] empties \the [A.name] into [src].</span>")
|
||||
for(var/obj/item/O in A.contents)
|
||||
O.forceMove(src)
|
||||
A.update_icon()
|
||||
update()
|
||||
return
|
||||
|
||||
var/obj/item/grab/G = I
|
||||
if(istype(G)) // handle grabbed mob
|
||||
if(ismob(G.affecting))
|
||||
var/mob/GM = G.affecting
|
||||
for (var/mob/V in viewers(usr))
|
||||
V.show_message("[usr] starts putting [GM.name] into the disposal.", 3)
|
||||
if(do_after(usr, 20))
|
||||
GM.forceMove(src)
|
||||
GM.update_perspective()
|
||||
for (var/mob/C in viewers(src))
|
||||
C.show_message("<font color='red'>[GM.name] has been placed in \the [src] by [user].</font>", 3)
|
||||
qdel(G)
|
||||
|
||||
add_attack_logs(user,GM,"Disposals dunked")
|
||||
return
|
||||
|
||||
if(!user.attempt_insert_item_for_installation(I, src))
|
||||
return
|
||||
|
||||
to_chat(user, "You place \the [I] into \the [src].")
|
||||
for(var/mob/M in viewers(src))
|
||||
if(M == user)
|
||||
continue
|
||||
M.show_message("[user.name] places \the [I] into \the [src].", 3)
|
||||
|
||||
update()
|
||||
|
||||
// mouse drop another mob or self
|
||||
//
|
||||
/obj/machinery/disposal/MouseDroppedOnLegacy(mob/target, mob/user)
|
||||
if(!CHECK_MOBILITY(user, MOBILITY_CAN_USE) || !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
|
||||
|
||||
src.add_fingerprint(user)
|
||||
var/target_loc = target.loc
|
||||
var/msg
|
||||
for (var/mob/V in viewers(usr))
|
||||
if(target == user && !user.stat && CHECK_ALL_MOBILITY(user, MOBILITY_CAN_MOVE | MOBILITY_CAN_USE))
|
||||
V.show_message("[usr] starts climbing into the disposal.", 3)
|
||||
if(target != user && !user.restrained() && !user.stat && CHECK_ALL_MOBILITY(user, MOBILITY_CAN_MOVE | MOBILITY_CAN_USE))
|
||||
if(target.anchored) return
|
||||
V.show_message("[usr] starts stuffing [target.name] into the disposal.", 3)
|
||||
if(!do_after(usr, 20))
|
||||
return
|
||||
if(target_loc != target.loc)
|
||||
return
|
||||
if(target == user && !user.stat && CHECK_ALL_MOBILITY(user, MOBILITY_CAN_MOVE | MOBILITY_CAN_USE)) // 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].")
|
||||
else if(target != user && !user.restrained() && !user.stat && CHECK_ALL_MOBILITY(user, MOBILITY_CAN_MOVE | MOBILITY_CAN_USE))
|
||||
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")
|
||||
else
|
||||
return
|
||||
target.forceMove(src)
|
||||
target.update_perspective()
|
||||
|
||||
for (var/mob/C in viewers(src))
|
||||
if(C == user)
|
||||
continue
|
||||
C.show_message(msg, 3)
|
||||
|
||||
update()
|
||||
return
|
||||
|
||||
// attempt to move while inside
|
||||
/obj/machinery/disposal/relaymove(mob/user as mob)
|
||||
if(user.stat || src.flushing)
|
||||
return
|
||||
if(user.loc == src)
|
||||
src.go_out(user)
|
||||
return
|
||||
|
||||
// leave the disposal
|
||||
/obj/machinery/disposal/proc/go_out(mob/user)
|
||||
user.forceMove(loc)
|
||||
user.update_perspective()
|
||||
update()
|
||||
return
|
||||
|
||||
// ai as human but can't flush
|
||||
/obj/machinery/disposal/attack_ai(mob/user as mob)
|
||||
interact(user, 1)
|
||||
|
||||
// human interact with machine
|
||||
/obj/machinery/disposal/attack_hand(mob/user, list/params)
|
||||
|
||||
if(machine_stat & BROKEN)
|
||||
return
|
||||
|
||||
if(user && user.loc == src)
|
||||
to_chat(user, "<font color='red'>You cannot reach the controls from inside.</font>")
|
||||
return
|
||||
|
||||
// Clumsy folks can only flush it.
|
||||
if(user.IsAdvancedToolUser(1))
|
||||
interact(user, 0)
|
||||
else
|
||||
flush = !flush
|
||||
update()
|
||||
return
|
||||
|
||||
// user interaction
|
||||
/obj/machinery/disposal/interact(mob/user, var/ai=0)
|
||||
|
||||
src.add_fingerprint(user)
|
||||
if(machine_stat & BROKEN)
|
||||
user.unset_machine()
|
||||
return
|
||||
|
||||
var/dat = "<head><title>Waste Disposal Unit</title></head><body><TT><B>Waste Disposal Unit</B><HR>"
|
||||
|
||||
if(!ai) // AI can't pull flush handle
|
||||
if(flush)
|
||||
dat += "Disposal handle: <A href='?src=\ref[src];handle=0'>Disengage</A> <B>Engaged</B>"
|
||||
else
|
||||
dat += "Disposal handle: <B>Disengaged</B> <A href='?src=\ref[src];handle=1'>Engage</A>"
|
||||
|
||||
dat += "<BR><HR><A href='?src=\ref[src];eject=1'>Eject contents</A><HR>"
|
||||
|
||||
if(mode <= 0)
|
||||
dat += "Pump: <B>Off</B> <A href='?src=\ref[src];pump=1'>On</A><BR>"
|
||||
else if(mode == 1)
|
||||
dat += "Pump: <A href='?src=\ref[src];pump=0'>Off</A> <B>On</B> (pressurizing)<BR>"
|
||||
else
|
||||
dat += "Pump: <A href='?src=\ref[src];pump=0'>Off</A> <B>On</B> (idle)<BR>"
|
||||
|
||||
var/per = 100* air_contents.return_pressure() / (SEND_PRESSURE)
|
||||
|
||||
dat += "Pressure: [round(per, 1)]%<BR></body>"
|
||||
|
||||
|
||||
user.set_machine(src)
|
||||
user << browse(dat, "window=disposal;size=360x170")
|
||||
onclose(user, "disposal")
|
||||
|
||||
// handle machine interaction
|
||||
|
||||
/obj/machinery/disposal/Topic(href, href_list)
|
||||
if(usr.loc == src)
|
||||
to_chat(usr, "<font color='red'>You cannot reach the controls from inside.</font>")
|
||||
return
|
||||
|
||||
if(mode==-1 && !href_list["eject"]) // only allow ejecting if mode is -1
|
||||
to_chat(usr, "<font color='red'>The disposal units power is disabled.</font>")
|
||||
return
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(machine_stat & BROKEN)
|
||||
return
|
||||
if(usr.stat || usr.restrained() || src.flushing)
|
||||
return
|
||||
|
||||
if(istype(src.loc, /turf))
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["close"])
|
||||
usr.unset_machine()
|
||||
usr << browse(null, "window=disposal")
|
||||
return
|
||||
|
||||
if(href_list["pump"])
|
||||
if(text2num(href_list["pump"]))
|
||||
mode = 1
|
||||
else
|
||||
mode = 0
|
||||
update()
|
||||
|
||||
if(!isAI(usr))
|
||||
if(href_list["handle"])
|
||||
flush = text2num(href_list["handle"])
|
||||
update()
|
||||
|
||||
if(href_list["eject"])
|
||||
eject()
|
||||
else
|
||||
usr << browse(null, "window=disposal")
|
||||
usr.unset_machine()
|
||||
return
|
||||
return
|
||||
|
||||
// eject the contents of the disposal unit
|
||||
/obj/machinery/disposal/proc/eject()
|
||||
for(var/atom/movable/AM in src)
|
||||
AM.forceMove(src.loc)
|
||||
AM.pipe_eject(0)
|
||||
update()
|
||||
|
||||
// update the icon & overlays to reflect mode & status
|
||||
/obj/machinery/disposal/proc/update()
|
||||
cut_overlays()
|
||||
if(machine_stat & BROKEN)
|
||||
icon_state = "disposal-broken"
|
||||
mode = 0
|
||||
flush = 0
|
||||
return
|
||||
|
||||
var/list/overlays_to_add = list()
|
||||
|
||||
// flush handle
|
||||
if(flush)
|
||||
overlays_to_add += image('icons/obj/pipes/disposal.dmi', "dispover-handle")
|
||||
|
||||
// only handle is shown if no power
|
||||
if(machine_stat & NOPOWER || mode == -1)
|
||||
add_overlay(overlays_to_add)
|
||||
return
|
||||
|
||||
// check for items in disposal - occupied light
|
||||
if(contents.len > 0)
|
||||
overlays_to_add += image('icons/obj/pipes/disposal.dmi', "dispover-full")
|
||||
|
||||
// charging and ready light
|
||||
if(mode == 1)
|
||||
overlays_to_add += image('icons/obj/pipes/disposal.dmi', "dispover-charge")
|
||||
else if(mode == 2)
|
||||
overlays_to_add += image('icons/obj/pipes/disposal.dmi', "dispover-ready")
|
||||
|
||||
add_overlay(overlays_to_add)
|
||||
|
||||
// timed process
|
||||
// charge the gas reservoir and perform flush if ready
|
||||
/obj/machinery/disposal/process(delta_time)
|
||||
if(!air_contents || (machine_stat & BROKEN)) // nothing can happen if broken
|
||||
update_use_power(USE_POWER_OFF)
|
||||
return
|
||||
|
||||
flush_count++
|
||||
if( flush_count >= flush_every_ticks )
|
||||
if( contents.len )
|
||||
if(mode == 2)
|
||||
spawn(0)
|
||||
feedback_inc("disposal_auto_flush",1)
|
||||
flush()
|
||||
flush_count = 0
|
||||
|
||||
src.updateDialog()
|
||||
|
||||
if(flush && air_contents.return_pressure() >= SEND_PRESSURE ) // flush can happen even without power
|
||||
flush()
|
||||
|
||||
if(mode != 1) //if off or ready, no need to charge
|
||||
update_use_power(USE_POWER_IDLE)
|
||||
else if(air_contents.return_pressure() >= SEND_PRESSURE)
|
||||
mode = 2 //if full enough, switch to ready mode
|
||||
update()
|
||||
else
|
||||
src.pressurize() //otherwise charge
|
||||
|
||||
/obj/machinery/disposal/proc/pressurize()
|
||||
if(machine_stat & NOPOWER) // won't charge if no power
|
||||
update_use_power(USE_POWER_OFF)
|
||||
return
|
||||
|
||||
var/atom/L = loc // recharging from loc turf
|
||||
var/datum/gas_mixture/env = L.return_air()
|
||||
|
||||
var/power_draw = -1
|
||||
if(env && env.temperature > 0)
|
||||
var/transfer_moles = (PUMP_MAX_FLOW_RATE/env.volume)*env.total_moles //group_multiplier is divided out here
|
||||
power_draw = pump_gas(src, env, air_contents, transfer_moles, active_power_usage)
|
||||
|
||||
if (power_draw > 0)
|
||||
use_power(power_draw)
|
||||
|
||||
// perform a flush
|
||||
/obj/machinery/disposal/proc/flush()
|
||||
|
||||
flushing = 1
|
||||
flick("[icon_state]-flush", src)
|
||||
|
||||
var/wrapcheck = 0
|
||||
var/obj/structure/disposalholder/H = new() // virtual holder object which actually
|
||||
// travels through the pipes.
|
||||
//Hacky test to get drones to mail themselves through disposals.
|
||||
for(var/mob/living/silicon/robot/drone/D in src)
|
||||
wrapcheck = 1
|
||||
|
||||
for(var/obj/item/smallDelivery/O in src)
|
||||
wrapcheck = 1
|
||||
|
||||
if(wrapcheck == 1)
|
||||
H.tomail = 1
|
||||
|
||||
|
||||
sleep(10)
|
||||
if(last_sound < world.time + 1)
|
||||
playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0)
|
||||
last_sound = world.time
|
||||
sleep(5) // wait for animation to finish
|
||||
|
||||
|
||||
H.init(src, air_contents) // copy the contents of disposer to holder
|
||||
air_contents = new(PRESSURE_TANK_VOLUME) // new empty gas resv.
|
||||
|
||||
H.start(src) // start the holder processing movement
|
||||
flushing = 0
|
||||
// now reset disposal state
|
||||
flush = 0
|
||||
if(mode == 2) // if was ready,
|
||||
mode = 1 // switch to charging
|
||||
update()
|
||||
return
|
||||
|
||||
|
||||
// called when area power changes
|
||||
/obj/machinery/disposal/power_change()
|
||||
..() // do default setting/reset of stat NOPOWER bit
|
||||
update() // update icon
|
||||
return
|
||||
|
||||
|
||||
/// Called when holder is expelled from a disposal.
|
||||
/// Should usually only occur if the pipe network is modified.
|
||||
/obj/machinery/disposal/proc/expel(obj/structure/disposalholder/H)
|
||||
|
||||
var/turf/target
|
||||
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
|
||||
if(H) // Somehow, someone managed to flush a window which broke mid-transit and caused the disposal to go in an infinite loop trying to expel null, hopefully this fixes it
|
||||
for(var/atom/movable/AM in H)
|
||||
target = get_offset_target_turf(src.loc, rand(5)-rand(5), rand(5)-rand(5))
|
||||
|
||||
AM.forceMove(src.loc)
|
||||
AM.pipe_eject(0)
|
||||
if(!istype(AM,/mob/living/silicon/robot/drone)) //Poor drones kept smashing windows and taking system damage being fired out of disposals. ~Z
|
||||
spawn(1)
|
||||
if(AM)
|
||||
AM.throw_at_old(target, 5, 1)
|
||||
|
||||
H.vent_gas(loc)
|
||||
qdel(H)
|
||||
|
||||
/obj/machinery/disposal/throw_impacted(atom/movable/AM, datum/thrownthing/TT)
|
||||
if(istype(AM, /obj/item) && !istype(AM, /obj/projectile))
|
||||
if(prob(75))
|
||||
AM.forceMove(src)
|
||||
visible_message("\The [AM] lands in \the [src].")
|
||||
return COMPONENT_THROW_HIT_TERMINATE
|
||||
else
|
||||
visible_message("\The [AM] bounces off of \the [src]'s rim!")
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/disposal/CanAllowThrough(atom/movable/mover, turf/target)
|
||||
if(istype(mover, /obj/projectile))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/disposal/wall
|
||||
name = "inset disposal unit"
|
||||
icon_state = "wall"
|
||||
|
||||
density = FALSE
|
||||
|
||||
/obj/machinery/disposal/wall/Initialize()
|
||||
. = ..()
|
||||
|
||||
spawn(1 SECOND) // Fixfix for weird interaction with buildmode or other late-spawning.
|
||||
update()
|
||||
|
||||
/obj/machinery/disposal/wall/update()
|
||||
..()
|
||||
|
||||
switch(dir)
|
||||
if(1)
|
||||
pixel_x = 0
|
||||
pixel_y = -32
|
||||
if(2)
|
||||
pixel_x = 0
|
||||
pixel_y = 32
|
||||
if(4)
|
||||
pixel_x = -32
|
||||
pixel_y = 0
|
||||
if(8)
|
||||
pixel_x = 32
|
||||
pixel_y = 0
|
||||
@@ -0,0 +1,105 @@
|
||||
|
||||
// todo: /obj/machinery/disposal/chute/intake
|
||||
/obj/machinery/disposal/deliveryChute
|
||||
name = "Delivery chute"
|
||||
desc = "A chute for big and small packages alike!"
|
||||
density = 1
|
||||
icon_state = "intake"
|
||||
|
||||
var/c_mode = 0
|
||||
|
||||
/obj/machinery/disposal/deliveryChute/Initialize(mapload, newdir)
|
||||
. = ..()
|
||||
spawn(5)
|
||||
trunk = locate() in src.loc
|
||||
if(trunk)
|
||||
trunk.linked = src // link the pipe trunk to self
|
||||
|
||||
/obj/machinery/disposal/deliveryChute/interact()
|
||||
return
|
||||
|
||||
/obj/machinery/disposal/deliveryChute/update()
|
||||
return
|
||||
|
||||
/obj/machinery/disposal/deliveryChute/Bumped(var/atom/movable/AM) //Go straight into the chute
|
||||
if(istype(AM, /obj/projectile) || istype(AM, /obj/effect) || istype(AM, /obj/vehicle/sealed/mecha)) return
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
if(AM.loc.y != src.loc.y+1) return
|
||||
if(EAST)
|
||||
if(AM.loc.x != src.loc.x+1) return
|
||||
if(SOUTH)
|
||||
if(AM.loc.y != src.loc.y-1) return
|
||||
if(WEST)
|
||||
if(AM.loc.x != src.loc.x-1) return
|
||||
|
||||
// if(istype(AM, has_buckled_mobs()) return // I dont know what im doing @ktoma36
|
||||
|
||||
if(istype(AM, /obj))
|
||||
var/obj/O = AM
|
||||
O.loc = src
|
||||
else if(istype(AM, /mob))
|
||||
var/mob/M = AM
|
||||
M.loc = src
|
||||
src.flush()
|
||||
|
||||
/obj/machinery/disposal/deliveryChute/flush()
|
||||
flushing = 1
|
||||
flick("intake-closing", src)
|
||||
var/obj/structure/disposalholder/H = new() // virtual holder object which actually
|
||||
// travels through the pipes.
|
||||
air_contents = new() // new empty gas resv.
|
||||
|
||||
sleep(10)
|
||||
playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0)
|
||||
sleep(5) // wait for animation to finish
|
||||
|
||||
H.init(src) // copy the contents of disposer to holder
|
||||
|
||||
H.start(src) // start the holder processing movement
|
||||
flushing = 0
|
||||
// now reset disposal state
|
||||
flush = 0
|
||||
if(mode == 2) // if was ready,
|
||||
mode = 1 // switch to charging
|
||||
update()
|
||||
return
|
||||
|
||||
/obj/machinery/disposal/deliveryChute/attackby(var/obj/item/I, var/mob/user)
|
||||
if(!I || !user)
|
||||
return
|
||||
|
||||
if(I.is_screwdriver())
|
||||
if(c_mode==0)
|
||||
c_mode=1
|
||||
playsound(src.loc, I.tool_sound, 50, 1)
|
||||
to_chat(user, "You remove the screws around the power connection.")
|
||||
return
|
||||
else if(c_mode==1)
|
||||
c_mode=0
|
||||
playsound(src.loc, I.tool_sound, 50, 1)
|
||||
to_chat(user, "You attach the screws around the power connection.")
|
||||
return
|
||||
else if(istype(I, /obj/item/weldingtool) && c_mode==1)
|
||||
var/obj/item/weldingtool/W = I
|
||||
if(W.remove_fuel(0,user))
|
||||
playsound(src.loc, W.tool_sound, 50, 1)
|
||||
to_chat(user, "You start slicing the floorweld off the delivery chute.")
|
||||
if(do_after(user,20 * W.tool_speed))
|
||||
if(!src || !W.isOn()) return
|
||||
to_chat(user, "You sliced the floorweld off the delivery chute.")
|
||||
var/obj/structure/disposalconstruct/C = new (src.loc)
|
||||
C.ptype = 8 // 8 = Delivery chute
|
||||
C.update()
|
||||
C.anchored = 1
|
||||
C.density = 1
|
||||
qdel(src)
|
||||
return
|
||||
else
|
||||
to_chat(user, "You need more welding fuel to complete this task.")
|
||||
return
|
||||
|
||||
/obj/machinery/disposal/deliveryChute/Destroy()
|
||||
if(trunk)
|
||||
trunk.linked = null
|
||||
..()
|
||||
@@ -0,0 +1,74 @@
|
||||
// the disposal outlet machine
|
||||
// todo: /obj/machinery/disposal/outlet
|
||||
|
||||
/obj/structure/disposaloutlet
|
||||
name = "disposal outlet"
|
||||
desc = "An outlet for the pneumatic disposal system."
|
||||
icon = 'icons/obj/pipes/disposal.dmi'
|
||||
icon_state = "outlet"
|
||||
density = 1
|
||||
anchored = 1
|
||||
var/active = 0
|
||||
var/turf/target // this will be where the output objects are 'thrown' to.
|
||||
var/mode = 0
|
||||
|
||||
/obj/structure/disposaloutlet/LateInitialize()
|
||||
target = get_ranged_target_turf(src, dir, 10)
|
||||
var/obj/structure/disposalpipe/trunk/trunk = locate() in loc
|
||||
if(trunk)
|
||||
trunk.linked = src // link the pipe trunk to self
|
||||
|
||||
// expel the contents of the holder object, then delete it
|
||||
// called when the holder exits the outlet
|
||||
/obj/structure/disposaloutlet/proc/expel(obj/structure/disposalholder/H)
|
||||
|
||||
target = get_ranged_target_turf(src, dir, 10)
|
||||
flick("outlet-open", src)
|
||||
playsound(src, 'sound/machines/warning-buzzer.ogg', 50, 0, 0)
|
||||
sleep(20) //wait until correct animation frame
|
||||
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
|
||||
|
||||
if(H)
|
||||
for(var/atom/movable/AM in H)
|
||||
AM.forceMove(src.loc)
|
||||
AM.pipe_eject(dir)
|
||||
if(!istype(AM,/mob/living/silicon/robot/drone)) //Drones keep smashing windows from being fired out of chutes. Bad for the station. ~Z
|
||||
spawn(5)
|
||||
AM.throw_at_old(target, 3, 1)
|
||||
H.vent_gas(src.loc)
|
||||
qdel(H)
|
||||
|
||||
/obj/structure/disposaloutlet/attackby(obj/item/I, mob/user)
|
||||
if(!I || !user)
|
||||
return
|
||||
src.add_fingerprint(user, 0, I)
|
||||
if(I.is_screwdriver())
|
||||
if(mode==0)
|
||||
mode=1
|
||||
to_chat(user, "You remove the screws around the power connection.")
|
||||
playsound(src, I.tool_sound, 50, 1)
|
||||
return
|
||||
else if(mode==1)
|
||||
mode=0
|
||||
to_chat(user, "You attach the screws around the power connection.")
|
||||
playsound(src, I.tool_sound, 50, 1)
|
||||
return
|
||||
else if(istype(I, /obj/item/weldingtool) && mode==1)
|
||||
var/obj/item/weldingtool/W = I
|
||||
if(W.remove_fuel(0,user))
|
||||
playsound(src, W.tool_sound, 100, 1)
|
||||
to_chat(user, "You start slicing the floorweld off the disposal outlet.")
|
||||
if(do_after(user,20 * W.tool_speed))
|
||||
if(!src || !W.isOn()) return
|
||||
to_chat(user, "You sliced the floorweld off the disposal outlet.")
|
||||
var/obj/structure/disposalconstruct/C = new (src.loc)
|
||||
src.transfer_fingerprints_to(C)
|
||||
C.ptype = 7 // 7 = outlet
|
||||
C.update()
|
||||
C.anchored = 1
|
||||
C.density = 1
|
||||
qdel(src)
|
||||
return
|
||||
else
|
||||
to_chat(user, "You need more welding fuel to complete this task.")
|
||||
return
|
||||
@@ -0,0 +1,364 @@
|
||||
// Disposal pipe construction
|
||||
// This is the pipe that you drag around, not the attached ones.
|
||||
|
||||
/obj/structure/disposalconstruct
|
||||
name = "disposal pipe segment"
|
||||
desc = "A huge pipe segment used for constructing disposal systems."
|
||||
icon = 'icons/obj/pipes/disposal.dmi'
|
||||
icon_state = "conpipe-s"
|
||||
anchored = 0
|
||||
density = 0
|
||||
pressure_resistance = 5*ONE_ATMOSPHERE
|
||||
materials_base = list(MAT_STEEL = 1850)
|
||||
var/sortType = ""
|
||||
var/ptype = 0
|
||||
var/subtype = 0
|
||||
var/dpdir = 0 // directions as disposalpipe
|
||||
var/base_state = "pipe-s"
|
||||
|
||||
/obj/structure/disposalconstruct/Initialize(mapload, newtype, newdir, flipped, newsubtype)
|
||||
. = ..(mapload, )
|
||||
ptype = newtype
|
||||
dir = newdir
|
||||
if(ptype == DISPOSAL_PIPE_STRAIGHT && (dir in GLOB.cornerdirs))
|
||||
ptype = DISPOSAL_PIPE_CORNER
|
||||
switch(dir)
|
||||
if(NORTHWEST)
|
||||
dir = WEST
|
||||
if(NORTHEAST)
|
||||
dir = NORTH
|
||||
if(SOUTHWEST)
|
||||
dir = SOUTH
|
||||
if(SOUTHEAST)
|
||||
dir = EAST
|
||||
|
||||
switch(ptype)
|
||||
if(DISPOSAL_PIPE_BIN, DISPOSAL_PIPE_OUTLET, DISPOSAL_PIPE_CHUTE)
|
||||
density = 1
|
||||
if(DISPOSAL_PIPE_SORTER, DISPOSAL_PIPE_SORTER_FLIPPED)
|
||||
subtype = newsubtype
|
||||
|
||||
if(flipped)
|
||||
do_a_flip()
|
||||
else
|
||||
update() // do_a_flip() calls update anyway, so, lazy way of catching unupdated pipe!
|
||||
|
||||
/obj/structure/disposalconstruct/proc/update()
|
||||
// todo: rework this..
|
||||
update_icon()
|
||||
|
||||
// update iconstate and dpdir due to dir and type
|
||||
/obj/structure/disposalconstruct/update_icon()
|
||||
. = ..()
|
||||
var/flip = turn(dir, 180)
|
||||
var/left = turn(dir, 90)
|
||||
var/right = turn(dir, -90)
|
||||
|
||||
switch(ptype)
|
||||
if(DISPOSAL_PIPE_STRAIGHT)
|
||||
base_state = "pipe-s"
|
||||
dpdir = dir | flip
|
||||
if(DISPOSAL_PIPE_CORNER)
|
||||
base_state = "pipe-c"
|
||||
dpdir = dir | right
|
||||
if(DISPOSAL_PIPE_JUNCTION)
|
||||
base_state = "pipe-j1"
|
||||
dpdir = dir | right | flip
|
||||
if(DISPOSAL_PIPE_JUNCTION_FLIPPED)
|
||||
base_state = "pipe-j2"
|
||||
dpdir = dir | left | flip
|
||||
if(DISPOSAL_PIPE_JUNCTION_Y)
|
||||
base_state = "pipe-y"
|
||||
dpdir = dir | left | right
|
||||
if(DISPOSAL_PIPE_TRUNK)
|
||||
base_state = "pipe-t"
|
||||
dpdir = dir
|
||||
// disposal bin has only one dir, thus we don't need to care about setting it
|
||||
if(DISPOSAL_PIPE_BIN)
|
||||
if(anchored)
|
||||
base_state = "disposal"
|
||||
else
|
||||
base_state = "condisposal"
|
||||
|
||||
if(DISPOSAL_PIPE_OUTLET)
|
||||
base_state = "outlet"
|
||||
dpdir = dir
|
||||
|
||||
if(DISPOSAL_PIPE_CHUTE)
|
||||
base_state = "intake"
|
||||
dpdir = dir
|
||||
|
||||
if(DISPOSAL_PIPE_SORTER)
|
||||
base_state = "pipe-j1s"
|
||||
dpdir = dir | right | flip
|
||||
|
||||
if(DISPOSAL_PIPE_SORTER_FLIPPED)
|
||||
base_state = "pipe-j2s"
|
||||
dpdir = dir | left | flip
|
||||
///// Z-Level stuff
|
||||
if(DISPOSAL_PIPE_UPWARD)
|
||||
base_state = "pipe-u"
|
||||
dpdir = dir
|
||||
if(DISPOSAL_PIPE_DOWNWARD)
|
||||
base_state = "pipe-d"
|
||||
dpdir = dir
|
||||
///// Z-Level stuff
|
||||
if(DISPOSAL_PIPE_TAGGER)
|
||||
base_state = "pipe-tagger"
|
||||
dpdir = dir | flip
|
||||
if(DISPOSAL_PIPE_TAGGER_PARTIAL)
|
||||
base_state = "pipe-tagger-partial"
|
||||
dpdir = dir | flip
|
||||
|
||||
///// Z-Level stuff
|
||||
if(!(ptype in list(DISPOSAL_PIPE_BIN, DISPOSAL_PIPE_OUTLET, DISPOSAL_PIPE_CHUTE, DISPOSAL_PIPE_UPWARD, DISPOSAL_PIPE_DOWNWARD, DISPOSAL_PIPE_TAGGER, DISPOSAL_PIPE_TAGGER_PARTIAL)))
|
||||
///// Z-Level stuff
|
||||
icon_state = "con[base_state]"
|
||||
else
|
||||
icon_state = base_state
|
||||
|
||||
if(invisibility) // if invisible, fade icon
|
||||
alpha = 128
|
||||
else
|
||||
alpha = 255
|
||||
//otherwise burying half-finished pipes under floors causes them to half-fade
|
||||
|
||||
// flip and rotate verbs
|
||||
/obj/structure/disposalconstruct/verb/rotate()
|
||||
set category = VERB_CATEGORY_OBJECT
|
||||
set name = "Rotate Pipe"
|
||||
set src in view(1)
|
||||
|
||||
if(usr.stat)
|
||||
return
|
||||
|
||||
if(anchored)
|
||||
to_chat(usr, "You must unfasten the pipe before rotating it.")
|
||||
return
|
||||
|
||||
setDir(turn(dir, -90))
|
||||
update()
|
||||
|
||||
/obj/structure/disposalconstruct/verb/flip()
|
||||
set category = VERB_CATEGORY_OBJECT
|
||||
set name = "Flip Pipe"
|
||||
set src in view(1)
|
||||
if(usr.stat)
|
||||
return
|
||||
|
||||
if(anchored)
|
||||
to_chat(usr, "You must unfasten the pipe before flipping it.")
|
||||
return
|
||||
|
||||
do_a_flip()
|
||||
|
||||
/obj/structure/disposalconstruct/proc/do_a_flip()
|
||||
setDir(turn(dir, 180))
|
||||
switch(ptype)
|
||||
if(DISPOSAL_PIPE_JUNCTION)
|
||||
ptype = DISPOSAL_PIPE_JUNCTION_FLIPPED
|
||||
if(DISPOSAL_PIPE_JUNCTION_FLIPPED)
|
||||
ptype = DISPOSAL_PIPE_JUNCTION
|
||||
if(DISPOSAL_PIPE_SORTER)
|
||||
ptype = DISPOSAL_PIPE_SORTER_FLIPPED
|
||||
if(DISPOSAL_PIPE_SORTER_FLIPPED)
|
||||
ptype = DISPOSAL_PIPE_SORTER
|
||||
|
||||
update()
|
||||
|
||||
// returns the type path of disposalpipe corresponding to this item dtype
|
||||
/obj/structure/disposalconstruct/proc/dpipetype()
|
||||
switch(ptype)
|
||||
if(DISPOSAL_PIPE_STRAIGHT,DISPOSAL_PIPE_CORNER)
|
||||
return /obj/structure/disposalpipe/segment
|
||||
if(DISPOSAL_PIPE_JUNCTION,DISPOSAL_PIPE_JUNCTION_FLIPPED,DISPOSAL_PIPE_JUNCTION_Y)
|
||||
return /obj/structure/disposalpipe/junction
|
||||
if(DISPOSAL_PIPE_TRUNK)
|
||||
return /obj/structure/disposalpipe/trunk
|
||||
if(DISPOSAL_PIPE_BIN)
|
||||
return /obj/machinery/disposal
|
||||
if(DISPOSAL_PIPE_OUTLET)
|
||||
return /obj/structure/disposaloutlet
|
||||
if(DISPOSAL_PIPE_CHUTE)
|
||||
return /obj/machinery/disposal/deliveryChute
|
||||
if(DISPOSAL_PIPE_SORTER)
|
||||
switch(subtype)
|
||||
if(DISPOSAL_SORT_NORMAL)
|
||||
return /obj/structure/disposalpipe/sortjunction
|
||||
if(DISPOSAL_SORT_WILDCARD)
|
||||
return /obj/structure/disposalpipe/sortjunction/wildcard
|
||||
if(DISPOSAL_SORT_UNTAGGED)
|
||||
return /obj/structure/disposalpipe/sortjunction/untagged
|
||||
if(DISPOSAL_PIPE_SORTER_FLIPPED)
|
||||
switch(subtype)
|
||||
if(DISPOSAL_SORT_NORMAL)
|
||||
return /obj/structure/disposalpipe/sortjunction/flipped
|
||||
if(DISPOSAL_SORT_WILDCARD)
|
||||
return /obj/structure/disposalpipe/sortjunction/wildcard/flipped
|
||||
if(DISPOSAL_SORT_UNTAGGED)
|
||||
return /obj/structure/disposalpipe/sortjunction/untagged/flipped
|
||||
///// Z-Level stuff
|
||||
if(DISPOSAL_PIPE_UPWARD)
|
||||
return /obj/structure/disposalpipe/up
|
||||
if(DISPOSAL_PIPE_DOWNWARD)
|
||||
return /obj/structure/disposalpipe/down
|
||||
///// Z-Level stuff
|
||||
if(DISPOSAL_PIPE_TAGGER)
|
||||
return /obj/structure/disposalpipe/tagger
|
||||
if(DISPOSAL_PIPE_TAGGER_PARTIAL)
|
||||
return /obj/structure/disposalpipe/tagger/partial
|
||||
return
|
||||
|
||||
|
||||
|
||||
// attackby item
|
||||
// wrench: (un)anchor
|
||||
// weldingtool: convert to real pipe
|
||||
|
||||
/obj/structure/disposalconstruct/attackby(var/obj/item/I, var/mob/user)
|
||||
var/nicetype = "pipe"
|
||||
var/ispipe = 0 // Indicates if we should change the level of this pipe
|
||||
add_fingerprint(user, 0, I)
|
||||
switch(ptype)
|
||||
if(DISPOSAL_PIPE_BIN)
|
||||
nicetype = "disposal bin"
|
||||
if(DISPOSAL_PIPE_OUTLET)
|
||||
nicetype = "disposal outlet"
|
||||
if(DISPOSAL_PIPE_CHUTE)
|
||||
nicetype = "delivery chute"
|
||||
if(DISPOSAL_PIPE_SORTER, DISPOSAL_PIPE_SORTER_FLIPPED)
|
||||
switch(subtype)
|
||||
if(DISPOSAL_SORT_NORMAL)
|
||||
nicetype = "sorting pipe"
|
||||
if(DISPOSAL_SORT_WILDCARD)
|
||||
nicetype = "wildcard sorting pipe"
|
||||
if(DISPOSAL_SORT_UNTAGGED)
|
||||
nicetype = "untagged sorting pipe"
|
||||
ispipe = 1
|
||||
if(DISPOSAL_PIPE_TAGGER)
|
||||
nicetype = "tagging pipe"
|
||||
ispipe = 1
|
||||
if(DISPOSAL_PIPE_TAGGER_PARTIAL)
|
||||
nicetype = "partial tagging pipe"
|
||||
ispipe = 1
|
||||
else
|
||||
nicetype = "pipe"
|
||||
ispipe = 1
|
||||
|
||||
var/turf/T = src.loc
|
||||
if(!T.is_plating())
|
||||
to_chat(user, "You can only attach the [nicetype] if the floor plating is removed.")
|
||||
return
|
||||
|
||||
var/obj/structure/disposalpipe/CP = locate() in T
|
||||
|
||||
if(I.is_wrench())
|
||||
if(anchored)
|
||||
anchored = 0
|
||||
if(ispipe)
|
||||
set_hides_underfloor(OBJ_UNDERFLOOR_NEVER)
|
||||
density = 0
|
||||
else
|
||||
density = 1
|
||||
to_chat(user, "You detach the [nicetype] from the underfloor.")
|
||||
else
|
||||
if(ptype == DISPOSAL_PIPE_BIN || ptype == DISPOSAL_PIPE_OUTLET || ptype == DISPOSAL_PIPE_CHUTE) // Disposal or outlet
|
||||
if(CP) // There's something there
|
||||
if(!istype(CP,/obj/structure/disposalpipe/trunk))
|
||||
to_chat(user, "The [nicetype] requires a trunk underneath it in order to work.")
|
||||
return
|
||||
else // Nothing under, fuck.
|
||||
to_chat(user, "The [nicetype] requires a trunk underneath it in order to work.")
|
||||
return
|
||||
else
|
||||
if(CP)
|
||||
update()
|
||||
var/pdir = CP.dpdir
|
||||
if(istype(CP, /obj/structure/disposalpipe/broken))
|
||||
pdir = CP.dir
|
||||
if(pdir & dpdir)
|
||||
to_chat(user, "There is already a [nicetype] at that location.")
|
||||
return
|
||||
|
||||
anchored = 1
|
||||
if(ispipe)
|
||||
set_hides_underfloor(OBJ_UNDERFLOOR_ALWAYS)
|
||||
density = 0
|
||||
else
|
||||
density = 1 // We don't want disposal bins or outlets to go density 0
|
||||
to_chat(user, "You attach the [nicetype] to the underfloor.")
|
||||
playsound(loc, I.tool_sound, 100, 1)
|
||||
update()
|
||||
|
||||
else if(istype(I, /obj/item/weldingtool))
|
||||
if(anchored)
|
||||
var/obj/item/weldingtool/W = I
|
||||
if(W.remove_fuel(0,user))
|
||||
playsound(src, W.tool_sound, 100, 1)
|
||||
to_chat(user, "Welding the [nicetype] in place.")
|
||||
if(do_after(user, 20 * W.tool_speed))
|
||||
if(!src || !W.isOn()) return
|
||||
to_chat(user, "The [nicetype] has been welded in place!")
|
||||
update() // TODO: Make this neat
|
||||
if(ispipe) // Pipe
|
||||
|
||||
var/pipetype = dpipetype()
|
||||
var/obj/structure/disposalpipe/P = new pipetype(src.loc)
|
||||
src.transfer_fingerprints_to(P)
|
||||
P.base_icon_state = base_state
|
||||
P.setDir(dir)
|
||||
P.dpdir = dpdir
|
||||
P.updateicon()
|
||||
|
||||
//Needs some special treatment ;)
|
||||
if(ptype==DISPOSAL_PIPE_SORTER || ptype==DISPOSAL_PIPE_SORTER_FLIPPED)
|
||||
var/obj/structure/disposalpipe/sortjunction/SortP = P
|
||||
SortP.sortType = sortType
|
||||
SortP.updatedir()
|
||||
SortP.updatedesc()
|
||||
SortP.updatename()
|
||||
|
||||
else if(ptype==DISPOSAL_PIPE_BIN)
|
||||
var/obj/machinery/disposal/P = new /obj/machinery/disposal(src.loc)
|
||||
src.transfer_fingerprints_to(P)
|
||||
P.mode = 0 // start with pump off
|
||||
|
||||
else if(ptype==DISPOSAL_PIPE_OUTLET)
|
||||
|
||||
var/obj/structure/disposaloutlet/P = new /obj/structure/disposaloutlet(src.loc)
|
||||
src.transfer_fingerprints_to(P)
|
||||
P.setDir(dir)
|
||||
var/obj/structure/disposalpipe/trunk/Trunk = CP
|
||||
Trunk.linked = P
|
||||
|
||||
else if(ptype==DISPOSAL_PIPE_CHUTE)
|
||||
|
||||
var/obj/machinery/disposal/deliveryChute/P = new /obj/machinery/disposal/deliveryChute(src.loc)
|
||||
src.transfer_fingerprints_to(P)
|
||||
P.setDir(dir)
|
||||
|
||||
qdel(src)
|
||||
return
|
||||
else
|
||||
to_chat(user, "You need more welding fuel to complete this task.")
|
||||
return
|
||||
else
|
||||
to_chat(user, "You need to attach it to the plating first!")
|
||||
return
|
||||
|
||||
/obj/structure/disposalconstruct/proc/is_pipe()
|
||||
return (ptype != DISPOSAL_PIPE_BIN && ptype != DISPOSAL_PIPE_OUTLET && ptype != DISPOSAL_PIPE_CHUTE)
|
||||
|
||||
//helper proc that makes sure you can place the construct (i.e no dense objects stacking)
|
||||
/obj/structure/disposalconstruct/proc/can_place()
|
||||
if(is_pipe())
|
||||
return TRUE
|
||||
|
||||
for(var/obj/structure/disposalconstruct/DC in get_turf(src))
|
||||
if(DC == src)
|
||||
continue
|
||||
|
||||
if(!DC.is_pipe()) //there's already a chute/outlet/bin there
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
@@ -0,0 +1,150 @@
|
||||
// virtual disposal object
|
||||
// travels through pipes in lieu of actual items
|
||||
// contents will be items flushed by the disposal
|
||||
// this allows the gas flushed to be tracked
|
||||
|
||||
// todo: /atom/movable/disposal_holder
|
||||
/obj/structure/disposalholder
|
||||
invisibility = 101
|
||||
var/datum/gas_mixture/gas = null // gas used to flush, will appear at exit point
|
||||
var/active = 0 // true if the holder is moving, otherwise inactive
|
||||
dir = 0
|
||||
var/count = 2048 //*** can travel 2048 steps before going inactive (in case of loops)
|
||||
var/destinationTag = "" // changes if contains a delivery container
|
||||
var/tomail = 0 //changes if contains wrapped package
|
||||
var/hasmob = 0 //If it contains a mob
|
||||
|
||||
var/partialTag = "" //set by a partial tagger the first time round, then put in destinationTag if it goes through again.
|
||||
|
||||
/obj/structure/disposalholder/Destroy()
|
||||
QDEL_NULL(gas)
|
||||
active = 0
|
||||
return ..()
|
||||
|
||||
// initialize a holder from the contents of a disposal unit
|
||||
/obj/structure/disposalholder/proc/init(var/obj/machinery/disposal/D, var/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.
|
||||
|
||||
//Check for any living mobs trigger hasmob.
|
||||
//hasmob effects whether the package goes to cargo or its tagged destination.
|
||||
for(var/mob/living/M in D)
|
||||
if(M && M.stat != 2 && !istype(M,/mob/living/silicon/robot/drone))
|
||||
hasmob = 1
|
||||
|
||||
//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)
|
||||
for(var/obj/O in D)
|
||||
if(O.contents)
|
||||
for(var/mob/living/M in O.contents)
|
||||
if(M && M.stat != 2 && !istype(M,/mob/living/silicon/robot/drone))
|
||||
hasmob = 1
|
||||
|
||||
// now everything inside the disposal gets put into the holder
|
||||
// note AM since can contain mobs or objs
|
||||
for(var/atom/movable/AM in D)
|
||||
AM.forceMove(src)
|
||||
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
|
||||
//Drones can mail themselves through maint.
|
||||
if(istype(AM, /mob/living/silicon/robot/drone))
|
||||
var/mob/living/silicon/robot/drone/drone = AM
|
||||
src.destinationTag = drone.mail_destination
|
||||
|
||||
// start the movement process
|
||||
// argument is the disposal unit the holder started in
|
||||
/obj/structure/disposalholder/proc/start(var/obj/machinery/disposal/D)
|
||||
if(!D.trunk)
|
||||
D.expel(src) // no trunk connected, so expel immediately
|
||||
return
|
||||
|
||||
forceMove(D.trunk)
|
||||
active = 1
|
||||
setDir(DOWN)
|
||||
spawn(1)
|
||||
move() // spawn off the movement process
|
||||
|
||||
// movement process, persists while holder is moving through pipes
|
||||
/obj/structure/disposalholder/proc/move()
|
||||
var/obj/structure/disposalpipe/last
|
||||
// todo: while this is fucking awful?
|
||||
while(active)
|
||||
sleep(1) // was 1
|
||||
if(!loc) return // check if we got GC'd
|
||||
|
||||
if(hasmob && prob(3))
|
||||
for(var/mob/living/H in src)
|
||||
if(!istype(H,/mob/living/silicon/robot/drone)) //Drones use the mailing code to move through the disposal system,
|
||||
H.take_overall_damage(20, 0, weapon_descriptor = "blunt trauma")//horribly maim any living creature jumping down disposals. c'est la vie
|
||||
|
||||
var/obj/structure/disposalpipe/curr = loc
|
||||
last = curr
|
||||
curr = curr.transfer(src)
|
||||
|
||||
if(!loc) return //side effects
|
||||
|
||||
if(!curr)
|
||||
last.expel(src, loc, dir)
|
||||
|
||||
//
|
||||
if(!(count--))
|
||||
active = 0
|
||||
|
||||
// find the turf which should contain the next pipe
|
||||
/obj/structure/disposalholder/proc/nextloc()
|
||||
return get_step(loc,dir)
|
||||
|
||||
// find a matching pipe on a turf
|
||||
/obj/structure/disposalholder/proc/findpipe(var/turf/T)
|
||||
|
||||
if(!T)
|
||||
return null
|
||||
|
||||
var/fdir = turn(dir, 180) // flip the movement direction
|
||||
for(var/obj/structure/disposalpipe/P in T)
|
||||
if(fdir & P.dpdir) // find pipe direction mask that matches flipped dir
|
||||
return P
|
||||
// if no matching pipe, return null
|
||||
return null
|
||||
|
||||
// merge two holder objects
|
||||
// used when a a holder meets a stuck holder
|
||||
/obj/structure/disposalholder/proc/merge(var/obj/structure/disposalholder/other)
|
||||
for(var/atom/movable/AM in other)
|
||||
AM.forceMove(src) // move everything in other holder to this one
|
||||
if(ismob(AM))
|
||||
var/mob/M = AM
|
||||
M.update_perspective()
|
||||
qdel(other)
|
||||
|
||||
/obj/structure/disposalholder/proc/settag(var/new_tag)
|
||||
destinationTag = new_tag
|
||||
|
||||
/obj/structure/disposalholder/proc/setpartialtag(var/new_tag)
|
||||
if(partialTag == new_tag)
|
||||
destinationTag = new_tag
|
||||
partialTag = ""
|
||||
else
|
||||
partialTag = new_tag
|
||||
|
||||
// called when player tries to move while in a pipe
|
||||
/obj/structure/disposalholder/relaymove(mob/user as mob)
|
||||
if(!istype(user,/mob/living))
|
||||
return
|
||||
|
||||
var/mob/living/U = user
|
||||
if (U.stat || U.last_special <= world.time)
|
||||
return
|
||||
U.last_special = world.time+100
|
||||
|
||||
if(loc)
|
||||
for (var/mob/M in hearers(src.loc.loc))
|
||||
to_chat(M, "<FONT size=[max(0, 5 - get_dist(src, M))]>CLONG, clong!</FONT>")
|
||||
playsound(src, 'sound/effects/clang.ogg', 50, 0, 0)
|
||||
|
||||
// called to vent all gas in holder to a location
|
||||
/obj/structure/disposalholder/proc/vent_gas(var/atom/location)
|
||||
location.assume_air(gas) // vent all gas to turf
|
||||
@@ -0,0 +1,265 @@
|
||||
// Disposal pipes
|
||||
/// todo: /obj/structure/disposal_pipe
|
||||
/obj/structure/disposalpipe
|
||||
icon = 'icons/obj/pipes/disposal.dmi'
|
||||
name = "disposal pipe"
|
||||
desc = "An underfloor disposal pipe."
|
||||
anchored = 1
|
||||
density = 0
|
||||
hides_underfloor = OBJ_UNDERFLOOR_ALWAYS
|
||||
dir = 0 // dir will contain dominant direction for junction pipes
|
||||
plane = TURF_PLANE
|
||||
layer = DISPOSAL_LAYER // slightly lower than wires and other pipes.
|
||||
|
||||
integrity = 100
|
||||
integrity_max = 100
|
||||
|
||||
#ifdef IN_MAP_EDITOR // Display disposal pipes etc. above walls in map editors.
|
||||
alpha = 128 // Set for the benefit of mapping.
|
||||
#endif
|
||||
|
||||
/// Bitmask of pipe directions.
|
||||
var/dpdir = 0
|
||||
var/sortType = ""
|
||||
var/subtype = 0
|
||||
// new pipe, set the icon_state as on map
|
||||
|
||||
/obj/structure/disposalpipe/Initialize(mapload, dir)
|
||||
. = ..()
|
||||
base_icon_state = icon_state
|
||||
if(!isnull(dir))
|
||||
setDir(dir)
|
||||
|
||||
// pipe is deleted
|
||||
// ensure if holder is present, it is expelled
|
||||
/obj/structure/disposalpipe/Destroy()
|
||||
var/obj/structure/disposalholder/H = locate() in src
|
||||
if(H)
|
||||
// holder was present
|
||||
H.active = 0
|
||||
var/turf/T = src.loc
|
||||
if(T.density)
|
||||
// deleting pipe is inside a dense turf (wall)
|
||||
// this is unlikely, but just dump out everything into the turf in case
|
||||
|
||||
for(var/atom/movable/AM in H)
|
||||
AM.forceMove(T)
|
||||
AM.pipe_eject(0)
|
||||
qdel(H)
|
||||
..()
|
||||
return
|
||||
|
||||
// otherwise, do normal expel from turf
|
||||
if(H)
|
||||
expel(H, T, 0)
|
||||
..()
|
||||
|
||||
// returns the direction of the next pipe object, given the entrance dir
|
||||
// by default, returns the bitmask of remaining directions
|
||||
/obj/structure/disposalpipe/proc/nextdir(var/fromdir)
|
||||
return dpdir & (~turn(fromdir, 180))
|
||||
|
||||
// transfer the holder through this pipe segment
|
||||
// overriden for special behaviour
|
||||
//
|
||||
/obj/structure/disposalpipe/proc/transfer(var/obj/structure/disposalholder/H)
|
||||
var/nextdir = nextdir(H.dir)
|
||||
H.setDir(nextdir)
|
||||
var/turf/T = H.nextloc()
|
||||
var/obj/structure/disposalpipe/P = H.findpipe(T)
|
||||
|
||||
if(P)
|
||||
// find other holder in next loc, if inactive merge it with current
|
||||
var/obj/structure/disposalholder/H2 = locate() in P
|
||||
if(H2 && !H2.active)
|
||||
H.merge(H2)
|
||||
|
||||
H.forceMove(P)
|
||||
else // if wasn't a pipe, then set loc to turf
|
||||
H.forceMove(T)
|
||||
return null
|
||||
|
||||
return P
|
||||
|
||||
// update actual icon_state depending on visibility
|
||||
// if invisible, append "f" to icon_state to show faded version
|
||||
// this will be revealed if a T-scanner is used
|
||||
// if visible, use regular icon_state
|
||||
/obj/structure/disposalpipe/proc/updateicon()
|
||||
icon_state = base_icon_state
|
||||
|
||||
// expel the held objects into a turf
|
||||
// called when there is a break in the pipe
|
||||
/obj/structure/disposalpipe/proc/expel(var/obj/structure/disposalholder/H, var/turf/T, var/direction)
|
||||
if(!istype(H))
|
||||
return
|
||||
|
||||
// Empty the holder if it is expelled into a dense turf.
|
||||
// Leaving it intact and sitting in a wall is stupid.
|
||||
if(T.density)
|
||||
for(var/atom/movable/AM in H)
|
||||
AM.loc = T
|
||||
AM.pipe_eject(0)
|
||||
qdel(H)
|
||||
return
|
||||
|
||||
if(!T.is_plating() && istype(T,/turf/simulated/floor)) //intact floor, pop the tile
|
||||
var/turf/simulated/floor/F = T
|
||||
F.break_tile()
|
||||
new /obj/item/stack/tile(H) // add to holder so it will be thrown with other stuff
|
||||
|
||||
var/turf/target
|
||||
if(direction) // direction is specified
|
||||
if(istype(T, /turf/space)) // if ended in space, then range is unlimited
|
||||
target = get_edge_target_turf(T, direction)
|
||||
else // otherwise limit to 10 tiles
|
||||
target = get_ranged_target_turf(T, direction, 10)
|
||||
|
||||
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
|
||||
if(H)
|
||||
for(var/atom/movable/AM in H)
|
||||
AM.forceMove(T)
|
||||
AM.pipe_eject(direction)
|
||||
spawn(1)
|
||||
if(AM)
|
||||
AM.throw_at_old(target, 100, 1)
|
||||
H.vent_gas(T)
|
||||
qdel(H)
|
||||
|
||||
else // no specified direction, so throw in random direction
|
||||
|
||||
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
|
||||
if(H)
|
||||
for(var/atom/movable/AM in H)
|
||||
target = get_offset_target_turf(T, rand(5)-rand(5), rand(5)-rand(5))
|
||||
|
||||
AM.forceMove(T)
|
||||
AM.pipe_eject(0)
|
||||
spawn(1)
|
||||
if(AM)
|
||||
AM.throw_at_old(target, 5, 1)
|
||||
|
||||
H.vent_gas(T) // all gas vent to turf
|
||||
qdel(H)
|
||||
|
||||
/obj/structure/disposalpipe/deconstructed(method)
|
||||
. = ..()
|
||||
src.invisibility = 101 // make invisible (since we won't delete the pipe immediately)
|
||||
var/obj/structure/disposalholder/H = locate() in src
|
||||
if(H)
|
||||
// holder was present
|
||||
H.active = 0
|
||||
var/turf/T = src.loc
|
||||
if(T.density)
|
||||
// broken pipe is inside a dense turf (wall)
|
||||
// this is unlikely, but just dump out everything into the turf in case
|
||||
|
||||
for(var/atom/movable/AM in H)
|
||||
AM.forceMove(T)
|
||||
AM.pipe_eject(0)
|
||||
qdel(H)
|
||||
return
|
||||
|
||||
// otherwise, do normal expel from turf
|
||||
if(H)
|
||||
expel(H, T, 0)
|
||||
return ..()
|
||||
|
||||
/obj/structure/disposalpipe/drop_products(method, atom/where)
|
||||
. = ..()
|
||||
if(method != ATOM_DECONSTRUCT_DISASSEMBLED)
|
||||
new /obj/structure/disposalpipe/broken(where, dir)
|
||||
|
||||
//attack by item
|
||||
//weldingtool: unfasten and convert to obj/disposalconstruct
|
||||
|
||||
/obj/structure/disposalpipe/attackby(var/obj/item/I, var/mob/user)
|
||||
|
||||
var/turf/T = src.loc
|
||||
if(!T.is_plating())
|
||||
return // prevent interaction with T-scanner revealed pipes
|
||||
src.add_fingerprint(user, 0, I)
|
||||
if(istype(I, /obj/item/weldingtool))
|
||||
var/obj/item/weldingtool/W = I
|
||||
|
||||
if(W.remove_fuel(0,user))
|
||||
playsound(src, W.tool_sound, 50, 1)
|
||||
// check if anything changed over 2 seconds
|
||||
var/turf/uloc = user.loc
|
||||
var/atom/wloc = W.loc
|
||||
to_chat(user, "Slicing the disposal pipe.")
|
||||
sleep(30)
|
||||
if(!W.isOn()) return
|
||||
if(user.loc == uloc && wloc == W.loc)
|
||||
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
|
||||
|
||||
// called when pipe is cut with welder
|
||||
/obj/structure/disposalpipe/proc/welded()
|
||||
|
||||
var/obj/structure/disposalconstruct/C = new (src.loc)
|
||||
switch(base_icon_state)
|
||||
if("pipe-s")
|
||||
C.ptype = 0
|
||||
if("pipe-c")
|
||||
C.ptype = 1
|
||||
if("pipe-j1")
|
||||
C.ptype = 2
|
||||
if("pipe-j2")
|
||||
C.ptype = 3
|
||||
if("pipe-y")
|
||||
C.ptype = 4
|
||||
if("pipe-t")
|
||||
C.ptype = 5
|
||||
if("pipe-j1s")
|
||||
C.ptype = 9
|
||||
C.sortType = sortType
|
||||
if("pipe-j2s")
|
||||
C.ptype = 10
|
||||
C.sortType = sortType
|
||||
///// Z-Level stuff
|
||||
if("pipe-u")
|
||||
C.ptype = 11
|
||||
if("pipe-d")
|
||||
C.ptype = 12
|
||||
///// Z-Level stuff
|
||||
if("pipe-tagger")
|
||||
C.ptype = 13
|
||||
if("pipe-tagger-partial")
|
||||
C.ptype = 14
|
||||
C.subtype = src.subtype
|
||||
src.transfer_fingerprints_to(C)
|
||||
C.setDir(dir)
|
||||
C.density = 0
|
||||
C.anchored = 1
|
||||
C.update()
|
||||
|
||||
qdel(src)
|
||||
|
||||
// pipe is deleted
|
||||
// ensure if holder is present, it is expelled
|
||||
/obj/structure/disposalpipe/Destroy()
|
||||
var/obj/structure/disposalholder/H = locate() in src
|
||||
if(H)
|
||||
// holder was present
|
||||
H.active = 0
|
||||
var/turf/T = src.loc
|
||||
if(T.density)
|
||||
// deleting pipe is inside a dense turf (wall)
|
||||
// this is unlikely, but just dump out everything into the turf in case
|
||||
|
||||
for(var/atom/movable/AM in H)
|
||||
AM.forceMove(T)
|
||||
AM.pipe_eject(0)
|
||||
qdel(H)
|
||||
..()
|
||||
return
|
||||
|
||||
// otherwise, do normal expel from turf
|
||||
if(H)
|
||||
expel(H, T, 0)
|
||||
..()
|
||||
@@ -0,0 +1,13 @@
|
||||
// a broken pipe
|
||||
/obj/structure/disposalpipe/broken
|
||||
icon_state = "pipe-b"
|
||||
dpdir = 0 // broken pipes have dpdir=0 so they're not found as 'real' pipes
|
||||
// i.e. will be treated as an empty turf
|
||||
desc = "A broken piece of disposal pipe."
|
||||
|
||||
// called when welded
|
||||
// for broken pipe, remove and turn into scrap
|
||||
/obj/structure/disposalpipe/broken/welded()
|
||||
// var/obj/item/scrap/S = new(src.loc)
|
||||
// S.set_components(200,0,0)
|
||||
qdel(src)
|
||||
@@ -0,0 +1,48 @@
|
||||
/obj/structure/disposalpipe/down
|
||||
icon_state = "pipe-d"
|
||||
|
||||
/obj/structure/disposalpipe/down/New()
|
||||
..()
|
||||
dpdir = dir
|
||||
return
|
||||
|
||||
/obj/structure/disposalpipe/down/nextdir(fromdir)
|
||||
var/nextdir
|
||||
if(fromdir == 12)
|
||||
nextdir = dir
|
||||
else
|
||||
nextdir = 11
|
||||
return nextdir
|
||||
|
||||
/obj/structure/disposalpipe/down/transfer(obj/structure/disposalholder/H)
|
||||
var/nextdir = nextdir(H.dir)
|
||||
H.dir = nextdir
|
||||
|
||||
var/turf/T
|
||||
var/obj/structure/disposalpipe/P
|
||||
|
||||
if(nextdir == 11)
|
||||
T = get_vertical_step(src, DOWN)
|
||||
if(!T)
|
||||
H.forceMove(src.loc)
|
||||
return
|
||||
else
|
||||
for(var/obj/structure/disposalpipe/up/F in T)
|
||||
P = F
|
||||
|
||||
else
|
||||
T = get_step(src.loc, H.dir)
|
||||
P = H.findpipe(T)
|
||||
|
||||
if(P)
|
||||
// find other holder in next loc, if inactive merge it with current
|
||||
var/obj/structure/disposalholder/H2 = locate() in P
|
||||
if(H2 && !H2.active)
|
||||
H.merge(H2)
|
||||
|
||||
H.forceMove(P)
|
||||
else // if wasn't a pipe, then set loc to turf
|
||||
H.forceMove(T)
|
||||
return null
|
||||
|
||||
return P
|
||||
@@ -0,0 +1,45 @@
|
||||
/obj/structure/disposalpipe/junction/yjunction
|
||||
icon_state = "pipe-y"
|
||||
|
||||
//a three-way junction with dir being the dominant direction
|
||||
/obj/structure/disposalpipe/junction
|
||||
icon_state = "pipe-j1"
|
||||
|
||||
/obj/structure/disposalpipe/junction/New()
|
||||
..()
|
||||
if(icon_state == "pipe-j1")
|
||||
dpdir = dir | turn(dir, -90) | turn(dir,180)
|
||||
else if(icon_state == "pipe-j2")
|
||||
dpdir = dir | turn(dir, 90) | turn(dir,180)
|
||||
else // pipe-y
|
||||
dpdir = dir | turn(dir,90) | turn(dir, -90)
|
||||
|
||||
// next direction to move
|
||||
// if coming in from secondary dirs, then next is primary dir
|
||||
// if coming in from primary dir, then next is equal chance of other dirs
|
||||
/obj/structure/disposalpipe/junction/nextdir(var/fromdir)
|
||||
var/flipdir = turn(fromdir, 180)
|
||||
if(flipdir != dir) // came from secondary dir
|
||||
return dir // so exit through primary
|
||||
else // came from primary
|
||||
// so need to choose either secondary exit
|
||||
var/mask = ..(fromdir)
|
||||
|
||||
// find a bit which is set
|
||||
var/setbit = 0
|
||||
if(mask & NORTH)
|
||||
setbit = NORTH
|
||||
else if(mask & SOUTH)
|
||||
setbit = SOUTH
|
||||
else if(mask & EAST)
|
||||
setbit = EAST
|
||||
else
|
||||
setbit = WEST
|
||||
|
||||
if(prob(50)) // 50% chance to choose the found bit or the other one
|
||||
return setbit
|
||||
else
|
||||
return mask & (~setbit)
|
||||
|
||||
/obj/structure/disposalpipe/junction/flipped //for easier and cleaner mapping
|
||||
icon_state = "pipe-j2"
|
||||
@@ -0,0 +1,10 @@
|
||||
// a straight or bent segment
|
||||
/obj/structure/disposalpipe/segment
|
||||
icon_state = "pipe-s"
|
||||
|
||||
/obj/structure/disposalpipe/segment/New()
|
||||
..()
|
||||
if(icon_state == "pipe-s")
|
||||
dpdir = dir | turn(dir, 180)
|
||||
else
|
||||
dpdir = dir | turn(dir, -90)
|
||||
@@ -0,0 +1,116 @@
|
||||
//a three-way junction that sorts objects
|
||||
/obj/structure/disposalpipe/sortjunction
|
||||
name = "sorting junction"
|
||||
icon_state = "pipe-j1s"
|
||||
desc = "An underfloor disposal pipe with a package sorting mechanism."
|
||||
|
||||
var/posdir = 0
|
||||
var/negdir = 0
|
||||
var/sortdir = 0
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/proc/updatedesc()
|
||||
desc = initial(desc)
|
||||
if(sortType)
|
||||
desc += "\nIt's filtering objects with the '[sortType]' tag."
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/proc/updatename()
|
||||
if(sortType)
|
||||
name = "[initial(name)] ([sortType])"
|
||||
else
|
||||
name = initial(name)
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/proc/updatedir()
|
||||
posdir = dir
|
||||
negdir = turn(posdir, 180)
|
||||
|
||||
if(icon_state == "pipe-j1s")
|
||||
sortdir = turn(posdir, -90)
|
||||
else if(icon_state == "pipe-j2s")
|
||||
sortdir = turn(posdir, 90)
|
||||
|
||||
dpdir = sortdir | posdir | negdir
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/New()
|
||||
. = ..()
|
||||
if(sortType) GLOB.tagger_locations |= sortType
|
||||
|
||||
updatedir()
|
||||
updatename()
|
||||
updatedesc()
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/attackby(obj/item/I, mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(istype(I, /obj/item/destTagger))
|
||||
var/obj/item/destTagger/O = I
|
||||
|
||||
if(O.currTag)// Tag set
|
||||
sortType = O.currTag
|
||||
playsound(src.loc, 'sound/machines/twobeep.ogg', 100, 1)
|
||||
to_chat(user, "<font color=#4F49AF>Changed filter to '[sortType]'.</font>")
|
||||
updatename()
|
||||
updatedesc()
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/proc/divert_check(checkTag)
|
||||
return sortType == checkTag
|
||||
|
||||
// next direction to move
|
||||
// if coming in from negdir, then next is primary dir or sortdir
|
||||
// if coming in from posdir, then flip around and go back to posdir
|
||||
// if coming in from sortdir, go to posdir
|
||||
/obj/structure/disposalpipe/sortjunction/nextdir(fromdir, sortTag)
|
||||
if(fromdir != sortdir) // probably came from the negdir
|
||||
if(divert_check(sortTag))
|
||||
return sortdir
|
||||
else
|
||||
return posdir
|
||||
else // came from sortdir
|
||||
// so go with the flow to positive direction
|
||||
return posdir
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/transfer(var/obj/structure/disposalholder/H)
|
||||
var/nextdir = nextdir(H.dir, H.destinationTag)
|
||||
H.setDir(nextdir)
|
||||
var/turf/T = H.nextloc()
|
||||
var/obj/structure/disposalpipe/P = H.findpipe(T)
|
||||
|
||||
if(P)
|
||||
// find other holder in next loc, if inactive merge it with current
|
||||
var/obj/structure/disposalholder/H2 = locate() in P
|
||||
if(H2 && !H2.active)
|
||||
H.merge(H2)
|
||||
|
||||
H.forceMove(P)
|
||||
else // if wasn't a pipe, then set loc to turf
|
||||
H.forceMove(T)
|
||||
return null
|
||||
|
||||
return P
|
||||
|
||||
//a three-way junction that filters all wrapped and tagged items
|
||||
/obj/structure/disposalpipe/sortjunction/wildcard
|
||||
name = "wildcard sorting junction"
|
||||
desc = "An underfloor disposal pipe which filters all wrapped and tagged items."
|
||||
subtype = 1
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/wildcard/divert_check(checkTag)
|
||||
return checkTag != ""
|
||||
|
||||
//junction that filters all untagged items
|
||||
/obj/structure/disposalpipe/sortjunction/untagged
|
||||
name = "untagged sorting junction"
|
||||
desc = "An underfloor disposal pipe which filters all untagged items."
|
||||
subtype = 2
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/untagged/divert_check(checkTag)
|
||||
return checkTag == ""
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/flipped //for easier and cleaner mapping
|
||||
icon_state = "pipe-j2s"
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/wildcard/flipped
|
||||
icon_state = "pipe-j2s"
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/untagged/flipped
|
||||
icon_state = "pipe-j2s"
|
||||
@@ -0,0 +1,50 @@
|
||||
/obj/structure/disposalpipe/tagger
|
||||
name = "package tagger"
|
||||
icon_state = "pipe-tagger"
|
||||
var/sort_tag = ""
|
||||
var/partial = 0
|
||||
|
||||
/obj/structure/disposalpipe/tagger/proc/updatedesc()
|
||||
desc = initial(desc)
|
||||
if(sort_tag)
|
||||
desc += "\nIt's tagging objects with the '[sort_tag]' tag."
|
||||
|
||||
/obj/structure/disposalpipe/tagger/proc/updatename()
|
||||
if(sort_tag)
|
||||
name = "[initial(name)] ([sort_tag])"
|
||||
else
|
||||
name = initial(name)
|
||||
|
||||
/obj/structure/disposalpipe/tagger/New()
|
||||
. = ..()
|
||||
dpdir = dir | turn(dir, 180)
|
||||
if(sort_tag) GLOB.tagger_locations |= sort_tag
|
||||
updatename()
|
||||
updatedesc()
|
||||
|
||||
/obj/structure/disposalpipe/tagger/attackby(obj/item/I, mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(istype(I, /obj/item/destTagger))
|
||||
var/obj/item/destTagger/O = I
|
||||
|
||||
if(O.currTag)// Tag set
|
||||
sort_tag = O.currTag
|
||||
playsound(src.loc, 'sound/machines/twobeep.ogg', 100, 1)
|
||||
to_chat(user, "<font color=#4F49AF>Changed tag to '[sort_tag]'.</font>")
|
||||
updatename()
|
||||
updatedesc()
|
||||
|
||||
/obj/structure/disposalpipe/tagger/transfer(obj/structure/disposalholder/H)
|
||||
if(sort_tag)
|
||||
if(partial)
|
||||
H.setpartialtag(sort_tag)
|
||||
else
|
||||
H.settag(sort_tag)
|
||||
return ..()
|
||||
|
||||
/obj/structure/disposalpipe/tagger/partial //needs two passes to tag
|
||||
name = "partial package tagger"
|
||||
icon_state = "pipe-tagger-partial"
|
||||
partial = 1
|
||||
@@ -0,0 +1,99 @@
|
||||
//a trunk joining to a disposal bin or outlet on the same turf
|
||||
/obj/structure/disposalpipe/trunk
|
||||
icon_state = "pipe-t"
|
||||
var/obj/linked // the linked obj/machinery/disposal or obj/disposaloutlet
|
||||
|
||||
/obj/structure/disposalpipe/trunk/Initialize(mapload)
|
||||
. = ..()
|
||||
dpdir = dir
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/structure/disposalpipe/trunk/LateInitialize()
|
||||
. = ..()
|
||||
getlinked()
|
||||
/obj/structure/disposalpipe/trunk/proc/getlinked()
|
||||
linked = null
|
||||
var/obj/machinery/disposal/D = locate() in src.loc
|
||||
if(D)
|
||||
linked = D
|
||||
if (!D.trunk)
|
||||
D.trunk = src
|
||||
|
||||
var/obj/structure/disposaloutlet/O = locate() in src.loc
|
||||
if(O)
|
||||
linked = O
|
||||
return
|
||||
|
||||
// Override attackby so we disallow trunkremoval when somethings ontop
|
||||
/obj/structure/disposalpipe/trunk/attackby(obj/item/I, mob/user)
|
||||
|
||||
//Disposal bins or chutes
|
||||
/*
|
||||
These shouldn't be required
|
||||
var/obj/machinery/disposal/D = locate() in src.loc
|
||||
if(D && D.anchored)
|
||||
return
|
||||
|
||||
//Disposal outlet
|
||||
var/obj/structure/disposaloutlet/O = locate() in src.loc
|
||||
if(O && O.anchored)
|
||||
return
|
||||
*/
|
||||
|
||||
//Disposal constructors
|
||||
var/obj/structure/disposalconstruct/C = locate() in src.loc
|
||||
if(C && C.anchored)
|
||||
return
|
||||
|
||||
var/turf/T = src.loc
|
||||
if(!T.is_plating())
|
||||
return // prevent interaction with T-scanner revealed pipes
|
||||
src.add_fingerprint(user, 0, I)
|
||||
if(istype(I, /obj/item/weldingtool))
|
||||
var/obj/item/weldingtool/W = I
|
||||
|
||||
if(W.remove_fuel(0,user))
|
||||
playsound(src, W.tool_sound, 100, 1)
|
||||
// check if anything changed over 2 seconds
|
||||
var/turf/uloc = user.loc
|
||||
var/atom/wloc = W.loc
|
||||
to_chat(user, "Slicing the disposal pipe.")
|
||||
sleep(30)
|
||||
if(!W.isOn()) return
|
||||
if(user.loc == uloc && wloc == W.loc)
|
||||
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
|
||||
|
||||
// would transfer to next pipe segment, but we are in a trunk
|
||||
// if not entering from disposal bin,
|
||||
// transfer to linked object (outlet or bin)
|
||||
|
||||
/obj/structure/disposalpipe/trunk/transfer(var/obj/structure/disposalholder/H)
|
||||
|
||||
if(H.dir == DOWN) // we just entered from a disposer
|
||||
return ..() // so do base transfer proc
|
||||
// otherwise, go to the linked object
|
||||
if(linked)
|
||||
var/obj/structure/disposaloutlet/O = linked
|
||||
if(istype(O) && (H))
|
||||
O.expel(H) // expel at outlet
|
||||
else
|
||||
var/obj/machinery/disposal/D = linked
|
||||
if(H)
|
||||
D.expel(H) // expel at disposal
|
||||
else
|
||||
if(H)
|
||||
src.expel(H, src.loc, 0) // expel at turf
|
||||
return null
|
||||
|
||||
// nextdir
|
||||
|
||||
/obj/structure/disposalpipe/trunk/nextdir(var/fromdir)
|
||||
if(fromdir == DOWN)
|
||||
return dir
|
||||
else
|
||||
return 0
|
||||
@@ -0,0 +1,48 @@
|
||||
/obj/structure/disposalpipe/up
|
||||
icon_state = "pipe-u"
|
||||
|
||||
/obj/structure/disposalpipe/up/New()
|
||||
..()
|
||||
dpdir = dir
|
||||
return
|
||||
|
||||
/obj/structure/disposalpipe/up/nextdir(fromdir)
|
||||
var/nextdir
|
||||
if(fromdir == 11)
|
||||
nextdir = dir
|
||||
else
|
||||
nextdir = 12
|
||||
return nextdir
|
||||
|
||||
/obj/structure/disposalpipe/up/transfer(var/obj/structure/disposalholder/H)
|
||||
var/nextdir = nextdir(H.dir)
|
||||
H.setDir(nextdir)
|
||||
|
||||
var/turf/T
|
||||
var/obj/structure/disposalpipe/P
|
||||
|
||||
if(nextdir == 12)
|
||||
T = get_vertical_step(src, UP)
|
||||
if(!T)
|
||||
H.forceMove(loc)
|
||||
return
|
||||
else
|
||||
for(var/obj/structure/disposalpipe/down/F in T)
|
||||
P = F
|
||||
|
||||
else
|
||||
T = get_step(src.loc, H.dir)
|
||||
P = H.findpipe(T)
|
||||
|
||||
if(P)
|
||||
// find other holder in next loc, if inactive merge it with current
|
||||
var/obj/structure/disposalholder/H2 = locate() in P
|
||||
if(H2 && !H2.active)
|
||||
H.merge(H2)
|
||||
|
||||
H.forceMove(P)
|
||||
else // if wasn't a pipe, then set loc to turf
|
||||
H.forceMove(T)
|
||||
return null
|
||||
|
||||
return P
|
||||
@@ -0,0 +1,93 @@
|
||||
// todo: /obj/item/package_wrapper
|
||||
/obj/item/packageWrap
|
||||
name = "package wrapper"
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "deliveryPaper"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
var/amount = 25
|
||||
|
||||
/obj/item/packageWrap/afterattack(atom/movable/target, mob/user, clickchain_flags, list/params)
|
||||
if(!(clickchain_flags & CLICKCHAIN_HAS_PROXIMITY)) return
|
||||
if(!istype(target)) //this really shouldn't be necessary (but it is). -Pete
|
||||
return
|
||||
if(istype(target, /obj/item/smallDelivery) || istype(target,/obj/structure/bigDelivery) \
|
||||
|| istype(target, /obj/item/gift) || istype(target, /obj/item/evidencebag))
|
||||
return
|
||||
if(target.anchored)
|
||||
return
|
||||
if(target in user)
|
||||
return
|
||||
if(user in target) //no wrapping closets that you are inside - it's not physically possible
|
||||
return
|
||||
|
||||
user.attack_log += "\[[time_stamp()]\] <font color=#4F49AF>Has used [name] on \ref[target]</font>"
|
||||
|
||||
|
||||
if (istype(target, /obj/item) && !(istype(target, /obj/item/storage) && !istype(target,/obj/item/storage/box)))
|
||||
var/obj/item/O = target
|
||||
if (src.amount > 1)
|
||||
var/obj/item/smallDelivery/P = new /obj/item/smallDelivery(get_turf(O.loc)) //Aaannd wrap it up!
|
||||
if(!istype(O.loc, /turf))
|
||||
if(user.client)
|
||||
user.client.screen -= O
|
||||
P.wrapped = O
|
||||
O.forceMove(P)
|
||||
P.set_weight_class(O.w_class)
|
||||
var/i = round(O.get_weight_class())
|
||||
if(i in list(1,2,3,4,5))
|
||||
P.icon_state = "deliverycrate[i]"
|
||||
switch(i)
|
||||
if(1) P.name = "tiny parcel"
|
||||
if(3) P.name = "normal-sized parcel"
|
||||
if(4) P.name = "large parcel"
|
||||
if(5) P.name = "huge parcel"
|
||||
if(i < 1)
|
||||
P.icon_state = "deliverycrate1"
|
||||
P.name = "tiny parcel"
|
||||
if(i > 5)
|
||||
P.icon_state = "deliverycrate5"
|
||||
P.name = "huge parcel"
|
||||
P.add_fingerprint(usr)
|
||||
O.add_fingerprint(usr)
|
||||
src.add_fingerprint(usr)
|
||||
src.amount -= 1
|
||||
user.visible_message("\The [user] wraps \a [target] with \a [src].",\
|
||||
"<span class='notice'>You wrap \the [target], leaving [amount] units of paper on \the [src].</span>",\
|
||||
"You hear someone taping paper around a small object.")
|
||||
else if (istype(target, /obj/structure/closet/crate))
|
||||
var/obj/structure/closet/crate/O = target
|
||||
if (src.amount > 3 && !O.opened)
|
||||
var/obj/structure/bigDelivery/P = new /obj/structure/bigDelivery(get_turf(O.loc))
|
||||
P.icon_state = "deliverycrate"
|
||||
P.wrapped = O
|
||||
O.loc = P
|
||||
src.amount -= 3
|
||||
user.visible_message("\The [user] wraps \a [target] with \a [src].",\
|
||||
"<span class='notice'>You wrap \the [target], leaving [amount] units of paper on \the [src].</span>",\
|
||||
"You hear someone taping paper around a large object.")
|
||||
else if(src.amount < 3)
|
||||
to_chat(user, "<span class='warning'>You need more paper.</span>")
|
||||
else if (istype (target, /obj/structure/closet))
|
||||
var/obj/structure/closet/O = target
|
||||
if (src.amount > 3 && !O.opened)
|
||||
var/obj/structure/bigDelivery/P = new /obj/structure/bigDelivery(get_turf(O.loc))
|
||||
P.wrapped = O
|
||||
O.sealed = 1
|
||||
O.loc = P
|
||||
src.amount -= 3
|
||||
user.visible_message("\The [user] wraps \a [target] with \a [src].",\
|
||||
"<span class='notice'>You wrap \the [target], leaving [amount] units of paper on \the [src].</span>",\
|
||||
"You hear someone taping paper around a large object.")
|
||||
else if(src.amount < 3)
|
||||
to_chat(user, "<span class='warning'>You need more paper.</span>")
|
||||
else
|
||||
to_chat(user, "<font color=#4F49AF>The object you are trying to wrap is unsuitable for the sorting machinery!</font>")
|
||||
if (src.amount <= 0)
|
||||
new /obj/item/c_tube( src.loc )
|
||||
qdel(src)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/item/packageWrap/examine(mob/user, dist)
|
||||
. = ..()
|
||||
. += "<font color=#4F49AF>There are [amount] units of package wrap left!</font>"
|
||||
@@ -0,0 +1,118 @@
|
||||
// todo: /obj/structure/large_parcel
|
||||
/obj/structure/bigDelivery
|
||||
desc = "A big wrapped package."
|
||||
name = "large parcel"
|
||||
icon = 'icons/obj/storage.dmi'
|
||||
icon_state = "deliverycloset"
|
||||
var/obj/wrapped = null
|
||||
density = 1
|
||||
var/sortTag = null
|
||||
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
|
||||
var/examtext = null
|
||||
var/nameset = 0
|
||||
var/label_y
|
||||
var/label_x
|
||||
var/tag_x
|
||||
|
||||
/obj/structure/bigDelivery/Destroy()
|
||||
if(wrapped) //sometimes items can disappear. For example, bombs. --rastaf0
|
||||
wrapped.forceMove(get_turf(src))
|
||||
if(istype(wrapped, /obj/structure/closet))
|
||||
var/obj/structure/closet/O = wrapped
|
||||
O.sealed = 0
|
||||
wrapped = null
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/atom/movable/AM in contents)
|
||||
AM.forceMove(T)
|
||||
return ..()
|
||||
|
||||
/obj/structure/bigDelivery/attack_hand(mob/user, list/params)
|
||||
unwrap()
|
||||
|
||||
/obj/structure/bigDelivery/proc/unwrap()
|
||||
// Destroy will drop our wrapped object on the turf, so let it.
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/bigDelivery/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/destTagger))
|
||||
var/obj/item/destTagger/O = W
|
||||
if(O.currTag)
|
||||
if(src.sortTag != O.currTag)
|
||||
to_chat(user, "<span class='notice'>You have labeled the destination as [O.currTag].</span>")
|
||||
if(!src.sortTag)
|
||||
src.sortTag = O.currTag
|
||||
update_icon()
|
||||
else
|
||||
src.sortTag = O.currTag
|
||||
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The package is already labeled for [O.currTag].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to set a destination first!</span>")
|
||||
|
||||
else if(istype(W, /obj/item/pen))
|
||||
switch(alert("What would you like to alter?",,"Title","Description", "Cancel"))
|
||||
if("Title")
|
||||
var/str = sanitizeSafe(input(usr,"Label text?","Set label",""), MAX_NAME_LEN)
|
||||
if(!str || !length(str))
|
||||
to_chat(user, "<span class='warning'> Invalid text.</span>")
|
||||
return
|
||||
user.visible_message("\The [user] titles \the [src] with \a [W], marking down: \"[str]\"",\
|
||||
"<span class='notice'>You title \the [src]: \"[str]\"</span>",\
|
||||
"You hear someone scribbling a note.")
|
||||
name = "[name] ([str])"
|
||||
if(!examtext && !nameset)
|
||||
nameset = 1
|
||||
update_icon()
|
||||
else
|
||||
nameset = 1
|
||||
if("Description")
|
||||
var/str = sanitize(input(usr,"Label text?","Set label",""))
|
||||
if(!str || !length(str))
|
||||
to_chat(user, "<font color='red'>Invalid text.</font>")
|
||||
return
|
||||
if(!examtext && !nameset)
|
||||
examtext = str
|
||||
update_icon()
|
||||
else
|
||||
examtext = str
|
||||
user.visible_message("\The [user] labels \the [src] with \a [W], scribbling down: \"[examtext]\"",\
|
||||
"<span class='notice'>You label \the [src]: \"[examtext]\"</span>",\
|
||||
"You hear someone scribbling a note.")
|
||||
return
|
||||
|
||||
/obj/structure/bigDelivery/update_icon()
|
||||
cut_overlays()
|
||||
if(nameset || examtext)
|
||||
var/image/I = new/image('icons/obj/storage.dmi',"delivery_label")
|
||||
if(icon_state == "deliverycloset")
|
||||
I.pixel_x = 2
|
||||
if(label_y == null)
|
||||
label_y = rand(-6, 11)
|
||||
I.pixel_y = label_y
|
||||
else if(icon_state == "deliverycrate")
|
||||
if(label_x == null)
|
||||
label_x = rand(-8, 6)
|
||||
I.pixel_x = label_x
|
||||
I.pixel_y = -3
|
||||
add_overlay(I)
|
||||
if(sortTag)
|
||||
var/image/I = new/image('icons/obj/storage.dmi',"delivery_tag")
|
||||
if(icon_state == "deliverycloset")
|
||||
if(tag_x == null)
|
||||
tag_x = rand(-2, 3)
|
||||
I.pixel_x = tag_x
|
||||
I.pixel_y = 9
|
||||
else if(icon_state == "deliverycrate")
|
||||
if(tag_x == null)
|
||||
tag_x = rand(-8, 6)
|
||||
I.pixel_x = tag_x
|
||||
I.pixel_y = -3
|
||||
add_overlay(I)
|
||||
|
||||
/obj/structure/bigDelivery/examine(mob/user, dist)
|
||||
. = ..()
|
||||
if(sortTag)
|
||||
. += "<span class='notice'>It is labeled \"[sortTag]\"</span>"
|
||||
if(examtext)
|
||||
. += "<span class='notice'>It has a note attached which reads, \"[examtext]\"</span>"
|
||||
@@ -0,0 +1,107 @@
|
||||
// todo: /obj/item/small_parcel
|
||||
/obj/item/smallDelivery
|
||||
desc = "A small wrapped package."
|
||||
name = "small parcel"
|
||||
icon = 'icons/obj/storage.dmi'
|
||||
icon_state = "deliverycrate3"
|
||||
drop_sound = 'sound/items/drop/cardboardbox.ogg'
|
||||
pickup_sound = 'sound/items/pickup/cardboardbox.ogg'
|
||||
var/obj/item/wrapped = null
|
||||
var/sortTag = null
|
||||
var/examtext = null
|
||||
var/nameset = 0
|
||||
var/tag_x
|
||||
|
||||
/obj/item/smallDelivery/attack_self(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if (wrapped) //sometimes items can disappear. For example, bombs. --rastaf0
|
||||
if(ishuman(user))
|
||||
user.put_in_hands_or_drop(wrapped)
|
||||
else
|
||||
wrapped.forceMove(drop_location())
|
||||
wrapped = null
|
||||
|
||||
qdel(src)
|
||||
|
||||
/obj/item/smallDelivery/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/destTagger))
|
||||
var/obj/item/destTagger/O = W
|
||||
if(O.currTag)
|
||||
if(src.sortTag != O.currTag)
|
||||
to_chat(user, "<span class='notice'>You have labeled the destination as [O.currTag].</span>")
|
||||
if(!src.sortTag)
|
||||
src.sortTag = O.currTag
|
||||
update_icon()
|
||||
else
|
||||
src.sortTag = O.currTag
|
||||
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The package is already labeled for [O.currTag].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to set a destination first!</span>")
|
||||
|
||||
else if(istype(W, /obj/item/pen))
|
||||
switch(alert("What would you like to alter?",,"Title","Description", "Cancel"))
|
||||
if("Title")
|
||||
var/str = sanitizeSafe(input(usr,"Label text?","Set label",""), MAX_NAME_LEN)
|
||||
if(!str || !length(str))
|
||||
to_chat(user, "<span class='warning'> Invalid text.</span>")
|
||||
return
|
||||
user.visible_message("\The [user] titles \the [src] with \a [W], marking down: \"[str]\"",\
|
||||
"<span class='notice'>You title \the [src]: \"[str]\"</span>",\
|
||||
"You hear someone scribbling a note.")
|
||||
name = "[name] ([str])"
|
||||
if(!examtext && !nameset)
|
||||
nameset = 1
|
||||
update_icon()
|
||||
else
|
||||
nameset = 1
|
||||
|
||||
if("Description")
|
||||
var/str = sanitize(input(usr,"Label text?","Set label",""))
|
||||
if(!str || !length(str))
|
||||
to_chat(user, "<font color='red'>Invalid text.</font>")
|
||||
return
|
||||
if(!examtext && !nameset)
|
||||
examtext = str
|
||||
update_icon()
|
||||
else
|
||||
examtext = str
|
||||
user.visible_message("\The [user] labels \the [src] with \a [W], scribbling down: \"[examtext]\"",\
|
||||
"<span class='notice'>You label \the [src]: \"[examtext]\"</span>",\
|
||||
"You hear someone scribbling a note.")
|
||||
return
|
||||
|
||||
/obj/item/smallDelivery/update_icon()
|
||||
cut_overlays()
|
||||
if((nameset || examtext) && icon_state != "deliverycrate1")
|
||||
var/image/I = new/image('icons/obj/storage.dmi',"delivery_label")
|
||||
if(icon_state == "deliverycrate5")
|
||||
I.pixel_y = -1
|
||||
add_overlay(I)
|
||||
if(sortTag)
|
||||
var/image/I = new/image('icons/obj/storage.dmi',"delivery_tag")
|
||||
switch(icon_state)
|
||||
if("deliverycrate1")
|
||||
I.pixel_y = -5
|
||||
if("deliverycrate2")
|
||||
I.pixel_y = -2
|
||||
if("deliverycrate3")
|
||||
I.pixel_y = 0
|
||||
if("deliverycrate4")
|
||||
if(tag_x == null)
|
||||
tag_x = rand(0,5)
|
||||
I.pixel_x = tag_x
|
||||
I.pixel_y = 3
|
||||
if("deliverycrate5")
|
||||
I.pixel_y = -3
|
||||
add_overlay(I)
|
||||
|
||||
/obj/item/smallDelivery/examine(mob/user, dist)
|
||||
. = ..()
|
||||
if(sortTag)
|
||||
. += "<span class='notice'>It is labeled \"[sortTag]\"</span>"
|
||||
if(examtext)
|
||||
. += "<span class='notice'>It has a note attached which reads, \"[examtext]\"</span>"
|
||||
Reference in New Issue
Block a user