initial commit - cross reference with 5th port - obviously has compile errors
This commit is contained in:
@@ -0,0 +1,340 @@
|
||||
//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.
|
||||
|
||||
/obj/machinery/conveyor
|
||||
icon = 'icons/obj/recycling.dmi'
|
||||
icon_state = "conveyor0"
|
||||
name = "conveyor belt"
|
||||
desc = "A conveyor belt."
|
||||
anchored = 1
|
||||
var/operating = 0 // 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/list/affecting // the list of all items that will be moved this ptick
|
||||
var/id = "" // the control ID - must match controller ID
|
||||
var/verted = 1 // set to -1 to have the conveyour belt be inverted, so you can use the other corner icons
|
||||
speed_process = 1
|
||||
|
||||
/obj/machinery/conveyor/centcom_auto
|
||||
id = "round_end_belt"
|
||||
|
||||
|
||||
// Auto conveyour is always on unless unpowered
|
||||
|
||||
/obj/machinery/conveyor/auto/New(loc, newdir)
|
||||
..(loc, newdir)
|
||||
operating = 1
|
||||
update_move_direction()
|
||||
|
||||
/obj/machinery/conveyor/auto/update()
|
||||
if(stat & BROKEN)
|
||||
icon_state = "conveyor-broken"
|
||||
operating = 0
|
||||
return
|
||||
else if(!operable)
|
||||
operating = 0
|
||||
else if(stat & NOPOWER)
|
||||
operating = 0
|
||||
else
|
||||
operating = 1
|
||||
icon_state = "conveyor[operating * verted]"
|
||||
|
||||
// create a conveyor
|
||||
/obj/machinery/conveyor/New(loc, newdir)
|
||||
..(loc)
|
||||
if(newdir)
|
||||
setDir(newdir)
|
||||
update_move_direction()
|
||||
|
||||
/obj/machinery/conveyor/proc/update_move_direction()
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
forwards = NORTH
|
||||
backwards = SOUTH
|
||||
if(SOUTH)
|
||||
forwards = SOUTH
|
||||
backwards = NORTH
|
||||
if(EAST)
|
||||
forwards = EAST
|
||||
backwards = WEST
|
||||
if(WEST)
|
||||
forwards = WEST
|
||||
backwards = EAST
|
||||
if(NORTHEAST)
|
||||
forwards = EAST
|
||||
backwards = SOUTH
|
||||
if(NORTHWEST)
|
||||
forwards = NORTH
|
||||
backwards = EAST
|
||||
if(SOUTHEAST)
|
||||
forwards = SOUTH
|
||||
backwards = WEST
|
||||
if(SOUTHWEST)
|
||||
forwards = WEST
|
||||
backwards = NORTH
|
||||
if(verted == -1)
|
||||
var/temp = forwards
|
||||
forwards = backwards
|
||||
backwards = temp
|
||||
if(operating == 1)
|
||||
movedir = forwards
|
||||
else
|
||||
movedir = backwards
|
||||
update()
|
||||
|
||||
/obj/machinery/conveyor/proc/update()
|
||||
if(stat & BROKEN)
|
||||
icon_state = "conveyor-broken"
|
||||
operating = 0
|
||||
return
|
||||
if(!operable)
|
||||
operating = 0
|
||||
if(stat & NOPOWER)
|
||||
operating = 0
|
||||
icon_state = "conveyor[operating * verted]"
|
||||
|
||||
// machine process
|
||||
// move items to the target location
|
||||
/obj/machinery/conveyor/process()
|
||||
if(stat & (BROKEN | NOPOWER))
|
||||
return
|
||||
if(!operating)
|
||||
return
|
||||
use_power(100)
|
||||
|
||||
affecting = loc.contents - src // moved items will be all in loc
|
||||
sleep(1)
|
||||
for(var/atom/movable/A in affecting)
|
||||
if(!A.anchored)
|
||||
if(A.loc == src.loc) // prevents the object from being affected if it's not currently here.
|
||||
step(A,movedir)
|
||||
CHECK_TICK
|
||||
|
||||
// attack with item, place item on conveyor
|
||||
/obj/machinery/conveyor/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/weapon/crowbar))
|
||||
if(!(stat & BROKEN))
|
||||
var/obj/item/conveyor_construct/C = new/obj/item/conveyor_construct(src.loc)
|
||||
C.id = id
|
||||
transfer_fingerprints_to(C)
|
||||
user << "<span class='notice'>You remove the conveyor belt.</span>"
|
||||
qdel(src)
|
||||
|
||||
else if(istype(I, /obj/item/weapon/wrench))
|
||||
if(!(stat & BROKEN))
|
||||
playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
setDir(turn(dir,-45))
|
||||
update_move_direction()
|
||||
user << "<span class='notice'>You rotate [src].</span>"
|
||||
|
||||
else if(user.a_intent != "harm")
|
||||
if(user.drop_item())
|
||||
I.loc = src.loc
|
||||
else
|
||||
return ..()
|
||||
|
||||
// attack with hand, move pulled object onto conveyor
|
||||
/obj/machinery/conveyor/attack_hand(mob/user)
|
||||
user.Move_Pulled(src)
|
||||
|
||||
|
||||
// make the conveyor broken
|
||||
// also propagate inoperability to any connected conveyor with the same ID
|
||||
/obj/machinery/conveyor/proc/broken()
|
||||
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/verb/destroy()
|
||||
set src in view()
|
||||
src.broken()
|
||||
*/
|
||||
|
||||
/obj/machinery/conveyor/power_change()
|
||||
..()
|
||||
update()
|
||||
|
||||
// the conveyor control switch
|
||||
//
|
||||
//
|
||||
|
||||
/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/convdir = 0 // 0 is two way switch, 1 and -1 means one way
|
||||
|
||||
var/id = "" // must match conveyor IDs to control them
|
||||
|
||||
var/list/conveyors // the list of converyors that are controlled by this switch
|
||||
anchored = 1
|
||||
speed_process = 1
|
||||
|
||||
|
||||
|
||||
/obj/machinery/conveyor_switch/New(newloc, newid)
|
||||
..(newloc)
|
||||
if(!id)
|
||||
id = newid
|
||||
update()
|
||||
|
||||
spawn(5) // allow map load
|
||||
conveyors = list()
|
||||
for(var/obj/machinery/conveyor/C in 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()
|
||||
if(!operated)
|
||||
return
|
||||
operated = 0
|
||||
|
||||
for(var/obj/machinery/conveyor/C in conveyors)
|
||||
C.operating = position
|
||||
C.update_move_direction()
|
||||
CHECK_TICK
|
||||
|
||||
// attack with hand, switch position
|
||||
/obj/machinery/conveyor_switch/attack_hand(mob/user)
|
||||
add_fingerprint(user)
|
||||
if(position == 0)
|
||||
if(convdir) //is it a oneway switch
|
||||
position = convdir
|
||||
else
|
||||
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 machines)
|
||||
if(S.id == src.id)
|
||||
S.position = position
|
||||
S.update()
|
||||
CHECK_TICK
|
||||
|
||||
/obj/machinery/conveyor_switch/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/weapon/crowbar))
|
||||
var/obj/item/conveyor_switch_construct/C = new/obj/item/conveyor_switch_construct(src.loc)
|
||||
C.id = id
|
||||
transfer_fingerprints_to(C)
|
||||
user << "<span class='notice'>You deattach the conveyor switch.</span>"
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/conveyor_switch/oneway
|
||||
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."
|
||||
|
||||
//
|
||||
// CONVEYOR CONSTRUCTION STARTS HERE
|
||||
//
|
||||
|
||||
/obj/item/conveyor_construct
|
||||
icon = 'icons/obj/recycling.dmi'
|
||||
icon_state = "conveyor0"
|
||||
name = "conveyor belt assembly"
|
||||
desc = "A conveyor belt assembly."
|
||||
w_class = 4
|
||||
var/id = "" //inherited by the belt
|
||||
|
||||
/obj/item/conveyor_construct/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(I, /obj/item/conveyor_switch_construct))
|
||||
user << "<span class='notice'>You link the switch to the conveyor belt assembly.</span>"
|
||||
var/obj/item/conveyor_switch_construct/C = I
|
||||
id = C.id
|
||||
|
||||
/obj/item/conveyor_construct/afterattack(atom/A, mob/user, proximity)
|
||||
if(!proximity || user.stat || !istype(A, /turf/open/floor) || istype(A, /area/shuttle))
|
||||
return
|
||||
var/cdir = get_dir(A, user)
|
||||
if(A == user.loc)
|
||||
user << "<span class='notice'>You cannot place a conveyor belt under yourself.</span>"
|
||||
return
|
||||
var/obj/machinery/conveyor/C = new/obj/machinery/conveyor(A,cdir)
|
||||
C.id = id
|
||||
transfer_fingerprints_to(C)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/conveyor_switch_construct
|
||||
name = "conveyor switch assembly"
|
||||
desc = "A conveyor control switch assembly."
|
||||
icon = 'icons/obj/recycling.dmi'
|
||||
icon_state = "switch-off"
|
||||
w_class = 4
|
||||
var/id = "" //inherited by the switch
|
||||
|
||||
/obj/item/conveyor_switch_construct/New()
|
||||
..()
|
||||
id = rand() //this couldn't possibly go wrong
|
||||
|
||||
/obj/item/conveyor_switch_construct/afterattack(atom/A, mob/user, proximity)
|
||||
if(!proximity || user.stat || !istype(A, /turf/open/floor) || istype(A, /area/shuttle))
|
||||
return
|
||||
var/found = 0
|
||||
for(var/obj/machinery/conveyor/C in view())
|
||||
if(C.id == src.id)
|
||||
found = 1
|
||||
break
|
||||
if(!found)
|
||||
user << "\icon[src]<span class=notice>The conveyor switch did not detect any linked conveyor belts in range.</span>"
|
||||
return
|
||||
var/obj/machinery/conveyor_switch/NC = new/obj/machinery/conveyor_switch(A, id)
|
||||
transfer_fingerprints_to(NC)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/paper/conveyor
|
||||
name = "paper- 'Nano-it-up U-build series, #9: Build your very own conveyor belt, in SPACE'"
|
||||
info = "<h1>Congratulations!</h1><p>You are now the proud owner of the best conveyor set available for space mail order! We at Nano-it-up know you love to prepare your own structures without wasting time, so we have devised a special streamlined assembly procedure that puts all other mail-order products to shame!</p><p>Firstly, you need to link the conveyor switch assembly to each of the conveyor belt assemblies. After doing so, you simply need to install the belt assemblies onto the floor, et voila, belt built. Our special Nano-it-up smart switch will detected any linked assemblies as far as the eye can see! This convenience, you can only have it when you Nano-it-up. Stay nano!</p>"
|
||||
@@ -0,0 +1,283 @@
|
||||
// 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/atmospherics/pipes/disposal.dmi'
|
||||
icon_state = "conpipe-s"
|
||||
anchored = 0
|
||||
density = 0
|
||||
pressure_resistance = 5*ONE_ATMOSPHERE
|
||||
level = 2
|
||||
var/ptype = 0
|
||||
|
||||
var/dpdir = 0 // directions as disposalpipe
|
||||
var/base_state = "pipe-s"
|
||||
|
||||
/obj/structure/disposalconstruct/examine(mob/user)
|
||||
..()
|
||||
user << "<span class='notice'>Alt-click to rotate it clockwise.</span>"
|
||||
|
||||
/obj/structure/disposalconstruct/New(var/loc, var/pipe_type, var/direction = 1)
|
||||
..(loc)
|
||||
if(pipe_type)
|
||||
ptype = pipe_type
|
||||
setDir(direction)
|
||||
|
||||
// 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(DISP_PIPE_STRAIGHT)
|
||||
base_state = "pipe-s"
|
||||
dpdir = dir | flip
|
||||
if(DISP_PIPE_BENT)
|
||||
base_state = "pipe-c"
|
||||
dpdir = dir | right
|
||||
if(DISP_JUNCTION)
|
||||
base_state = "pipe-j1"
|
||||
dpdir = dir | right | flip
|
||||
if(DISP_JUNCTION_FLIP)
|
||||
base_state = "pipe-j2"
|
||||
dpdir = dir | left | flip
|
||||
if(DISP_YJUNCTION)
|
||||
base_state = "pipe-y"
|
||||
dpdir = dir | left | right
|
||||
if(DISP_END_TRUNK)
|
||||
base_state = "pipe-t"
|
||||
dpdir = dir
|
||||
// disposal bin has only one dir, thus we don't need to care about setting it
|
||||
if(DISP_END_BIN)
|
||||
if(anchored)
|
||||
base_state = "disposal"
|
||||
else
|
||||
base_state = "condisposal"
|
||||
|
||||
if(DISP_END_OUTLET)
|
||||
base_state = "outlet"
|
||||
dpdir = dir
|
||||
|
||||
if(DISP_END_CHUTE)
|
||||
base_state = "intake"
|
||||
dpdir = dir
|
||||
|
||||
if(DISP_SORTJUNCTION)
|
||||
base_state = "pipe-j1s"
|
||||
dpdir = dir | right | flip
|
||||
|
||||
if(DISP_SORTJUNCTION_FLIP)
|
||||
base_state = "pipe-j2s"
|
||||
dpdir = dir | left | flip
|
||||
|
||||
|
||||
if(is_pipe())
|
||||
icon_state = "con[base_state]"
|
||||
else
|
||||
icon_state = base_state
|
||||
|
||||
// if invisible, fade icon
|
||||
alpha = (invisibility ? 0 : 255)
|
||||
|
||||
// hide called by levelupdate if turf intact status changes
|
||||
// change visibility status and force update of icon
|
||||
/obj/structure/disposalconstruct/hide(var/intact)
|
||||
invisibility = (intact && level==1) ? INVISIBILITY_MAXIMUM: 0 // hide if floor is intact
|
||||
update_icon()
|
||||
|
||||
|
||||
// flip and rotate verbs
|
||||
/obj/structure/disposalconstruct/verb/rotate()
|
||||
set name = "Rotate Pipe"
|
||||
set category = "Object"
|
||||
set src in view(1)
|
||||
|
||||
if(usr.stat || !usr.canmove || usr.restrained())
|
||||
return
|
||||
|
||||
if(anchored)
|
||||
usr << "<span class='warning'>You must unfasten the pipe before rotating it!</span>"
|
||||
return
|
||||
|
||||
setDir(turn(dir, -90))
|
||||
update_icon()
|
||||
|
||||
/obj/structure/disposalconstruct/AltClick(mob/user)
|
||||
..()
|
||||
if(user.incapacitated())
|
||||
user << "<span class='warning'>You can't do that right now!</span>"
|
||||
return
|
||||
if(!in_range(src, user))
|
||||
return
|
||||
else
|
||||
rotate()
|
||||
|
||||
/obj/structure/disposalconstruct/verb/flip()
|
||||
set name = "Flip Pipe"
|
||||
set category = "Object"
|
||||
set src in view(1)
|
||||
if(usr.stat || !usr.canmove || usr.restrained())
|
||||
return
|
||||
|
||||
if(anchored)
|
||||
usr << "<span class='warning'>You must unfasten the pipe before flipping it!</span>"
|
||||
return
|
||||
|
||||
setDir(turn(dir, 180))
|
||||
switch(ptype)
|
||||
if(DISP_JUNCTION)
|
||||
ptype = DISP_JUNCTION_FLIP
|
||||
if(DISP_JUNCTION_FLIP)
|
||||
ptype = DISP_JUNCTION
|
||||
if(DISP_SORTJUNCTION)
|
||||
ptype = DISP_SORTJUNCTION_FLIP
|
||||
if(DISP_SORTJUNCTION_FLIP)
|
||||
ptype = DISP_SORTJUNCTION
|
||||
|
||||
update_icon()
|
||||
|
||||
// returns the type path of disposalpipe corresponding to this item dtype
|
||||
/obj/structure/disposalconstruct/proc/dpipetype()
|
||||
switch(ptype)
|
||||
if(DISP_PIPE_STRAIGHT,DISP_PIPE_BENT)
|
||||
return /obj/structure/disposalpipe/segment
|
||||
if(DISP_JUNCTION, DISP_JUNCTION_FLIP, DISP_YJUNCTION)
|
||||
return /obj/structure/disposalpipe/junction
|
||||
if(DISP_END_TRUNK)
|
||||
return /obj/structure/disposalpipe/trunk
|
||||
if(DISP_END_BIN)
|
||||
return /obj/machinery/disposal/bin
|
||||
if(DISP_END_OUTLET)
|
||||
return /obj/structure/disposaloutlet
|
||||
if(DISP_END_CHUTE)
|
||||
return /obj/machinery/disposal/deliveryChute
|
||||
if(DISP_SORTJUNCTION, DISP_SORTJUNCTION_FLIP)
|
||||
return /obj/structure/disposalpipe/sortjunction
|
||||
return
|
||||
|
||||
|
||||
|
||||
// attackby item
|
||||
// wrench: (un)anchor
|
||||
// weldingtool: convert to real pipe
|
||||
|
||||
/obj/structure/disposalconstruct/attackby(obj/item/I, mob/user, params)
|
||||
var/nicetype = "pipe"
|
||||
var/ispipe = is_pipe() // Indicates if we should change the level of this pipe
|
||||
add_fingerprint(user)
|
||||
switch(ptype)
|
||||
if(DISP_END_BIN)
|
||||
nicetype = "disposal bin"
|
||||
if(DISP_END_OUTLET)
|
||||
nicetype = "disposal outlet"
|
||||
if(DISP_END_CHUTE)
|
||||
nicetype = "delivery chute"
|
||||
if(DISP_SORTJUNCTION, DISP_SORTJUNCTION_FLIP)
|
||||
nicetype = "sorting pipe"
|
||||
else
|
||||
nicetype = "pipe"
|
||||
|
||||
var/turf/T = loc
|
||||
if(T.intact && istype(T, /turf/open/floor))
|
||||
user << "<span class='warning'>You can only attach the [nicetype] if the floor plating is removed!</span>"
|
||||
return
|
||||
|
||||
if(!ispipe && istype(T, /turf/closed/wall))
|
||||
user << "<span class='warning'>You can't build [nicetype]s on walls, only disposal pipes!</span>"
|
||||
return
|
||||
|
||||
var/obj/structure/disposalpipe/CP = locate() in T
|
||||
|
||||
if(istype(I, /obj/item/weapon/wrench))
|
||||
if(anchored)
|
||||
anchored = 0
|
||||
if(ispipe)
|
||||
level = 2
|
||||
density = 0
|
||||
user << "<span class='notice'>You detach the [nicetype] from the underfloor.</span>"
|
||||
else
|
||||
if(!is_pipe()) // Disposal or outlet
|
||||
if(CP) // There's something there
|
||||
if(!istype(CP,/obj/structure/disposalpipe/trunk))
|
||||
user << "<span class='warning'>The [nicetype] requires a trunk underneath it in order to work!</span>"
|
||||
return
|
||||
else // Nothing under, fuck.
|
||||
user << "<span class='warning'>The [nicetype] requires a trunk underneath it in order to work!</span>"
|
||||
return
|
||||
else
|
||||
if(CP)
|
||||
update_icon()
|
||||
var/pdir = CP.dpdir
|
||||
if(istype(CP, /obj/structure/disposalpipe/broken))
|
||||
pdir = CP.dir
|
||||
if(pdir & dpdir)
|
||||
user << "<span class='warning'>There is already a [nicetype] at that location!</span>"
|
||||
return
|
||||
anchored = 1
|
||||
if(ispipe)
|
||||
level = 1 // We don't want disposal bins to disappear under the floors
|
||||
density = 0
|
||||
user << "<span class='notice'>You attach the [nicetype] to the underfloor.</span>"
|
||||
playsound(loc, 'sound/items/Ratchet.ogg', 100, 1)
|
||||
update_icon()
|
||||
|
||||
else if(istype(I, /obj/item/weapon/weldingtool))
|
||||
if(anchored)
|
||||
var/obj/item/weapon/weldingtool/W = I
|
||||
if(W.remove_fuel(0,user))
|
||||
playsound(loc, 'sound/items/Welder2.ogg', 100, 1)
|
||||
user << "<span class='notice'>You start welding the [nicetype] in place...</span>"
|
||||
if(do_after(user, 20/I.toolspeed, target = src))
|
||||
if(!loc || !W.isOn())
|
||||
return
|
||||
user << "<span class='notice'>The [nicetype] has been welded in place.</span>"
|
||||
update_icon() // TODO: Make this neat
|
||||
|
||||
if(ispipe)
|
||||
var/pipetype = dpipetype()
|
||||
var/obj/structure/disposalpipe/P = new pipetype(loc, src)
|
||||
P.updateicon()
|
||||
transfer_fingerprints_to(P)
|
||||
|
||||
if(ptype == DISP_SORTJUNCTION || ptype == DISP_SORTJUNCTION_FLIP)
|
||||
var/obj/structure/disposalpipe/sortjunction/SortP = P
|
||||
SortP.updatedir()
|
||||
|
||||
else if(ptype == DISP_END_BIN)
|
||||
var/obj/machinery/disposal/bin/B = new /obj/machinery/disposal/bin(loc,src)
|
||||
B.mode = 0 // start with pump off
|
||||
transfer_fingerprints_to(B)
|
||||
|
||||
else if(ptype == DISP_END_OUTLET)
|
||||
var/obj/structure/disposaloutlet/P = new /obj/structure/disposaloutlet(loc,src)
|
||||
transfer_fingerprints_to(P)
|
||||
|
||||
else if(ptype == DISP_END_CHUTE)
|
||||
var/obj/machinery/disposal/deliveryChute/P = new /obj/machinery/disposal/deliveryChute(loc,src)
|
||||
transfer_fingerprints_to(P)
|
||||
|
||||
return
|
||||
else
|
||||
user << "<span class='warning'>You need to attach it to the plating first!</span>"
|
||||
return
|
||||
|
||||
/obj/structure/disposalconstruct/proc/is_pipe()
|
||||
return !(ptype >=DISP_END_BIN && ptype <= DISP_END_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 1
|
||||
|
||||
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 0
|
||||
|
||||
return 1
|
||||
@@ -0,0 +1,802 @@
|
||||
|
||||
// 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
|
||||
|
||||
/obj/structure/disposalholder
|
||||
invisibility = INVISIBILITY_MAXIMUM
|
||||
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 = 1000 //*** can travel 1000 steps before going inactive (in case of loops)
|
||||
var/destinationTag = 0 // changes if contains a delivery container
|
||||
var/tomail = 0 //changes if contains wrapped package
|
||||
var/hasmob = 0 //If it contains a mob
|
||||
|
||||
/obj/structure/disposalholder/Destroy()
|
||||
qdel(gas)
|
||||
active = 0
|
||||
return ..()
|
||||
|
||||
// initialize a holder from the contents of a disposal unit
|
||||
/obj/structure/disposalholder/proc/init(obj/machinery/disposal/D)
|
||||
gas = D.air_contents// transfer gas resv. into holder object
|
||||
|
||||
//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.client)
|
||||
M.reset_perspective(src)
|
||||
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)
|
||||
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.loc = 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
|
||||
|
||||
|
||||
// start the movement process
|
||||
// argument is the disposal unit the holder started in
|
||||
/obj/structure/disposalholder/proc/start(obj/machinery/disposal/D)
|
||||
if(!D.trunk)
|
||||
D.expel(src) // no trunk connected, so expel immediately
|
||||
return
|
||||
loc = D.trunk
|
||||
active = 1
|
||||
setDir(DOWN)
|
||||
move()
|
||||
|
||||
return
|
||||
|
||||
// movement process, persists while holder is moving through pipes
|
||||
/obj/structure/disposalholder/proc/move()
|
||||
set waitfor = 0
|
||||
var/obj/structure/disposalpipe/last
|
||||
while(active)
|
||||
var/obj/structure/disposalpipe/curr = loc
|
||||
last = curr
|
||||
curr = curr.transfer(src)
|
||||
if(!curr && active)
|
||||
last.expel(src, loc, dir)
|
||||
|
||||
stoplag()
|
||||
if(!(count--))
|
||||
active = 0
|
||||
return
|
||||
|
||||
// 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(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(obj/structure/disposalholder/other)
|
||||
for(var/atom/movable/AM in other)
|
||||
AM.loc = src // move everything in other holder to this one
|
||||
if(ismob(AM))
|
||||
var/mob/M = AM
|
||||
M.reset_perspective(src) // if a client mob, update eye to follow this holder
|
||||
qdel(other)
|
||||
|
||||
|
||||
// called when player tries to move while in a pipe
|
||||
/obj/structure/disposalholder/relaymove(mob/user)
|
||||
if (user.stat)
|
||||
return
|
||||
if (src.loc)
|
||||
for (var/mob/M in get_hearers_in_view(src.loc.loc))
|
||||
M.show_message("<FONT size=[max(0, 5 - get_dist(src, M))]>CLONG, clong!</FONT>", 2)
|
||||
playsound(src.loc, 'sound/effects/clang.ogg', 50, 0, 0)
|
||||
|
||||
// called to vent all gas in holder to a location
|
||||
/obj/structure/disposalholder/proc/vent_gas(turf/T)
|
||||
T.assume_air(gas)
|
||||
T.air_update_turf()
|
||||
|
||||
/obj/structure/disposalholder/allow_drop()
|
||||
return 1
|
||||
|
||||
// Disposal pipes
|
||||
|
||||
/obj/structure/disposalpipe
|
||||
icon = 'icons/obj/atmospherics/pipes/disposal.dmi'
|
||||
name = "disposal pipe"
|
||||
desc = "An underfloor disposal pipe."
|
||||
anchored = 1
|
||||
density = 0
|
||||
on_blueprints = TRUE
|
||||
level = 1 // underfloor only
|
||||
var/dpdir = 0 // bitmask of pipe directions
|
||||
dir = 0// dir will contain dominant direction for junction pipes
|
||||
var/health = 10 // health points 0-10
|
||||
layer = DISPOSAL_PIPE_LAYER // slightly lower than wires and other pipes
|
||||
var/base_icon_state // initial icon state on map
|
||||
var/obj/structure/disposalconstruct/stored
|
||||
|
||||
// new pipe, set the icon_state as on map
|
||||
/obj/structure/disposalpipe/New(loc,var/obj/structure/disposalconstruct/make_from)
|
||||
..()
|
||||
|
||||
if(make_from && !qdeleted(make_from))
|
||||
base_icon_state = make_from.base_state
|
||||
setDir(make_from.dir)
|
||||
dpdir = make_from.dpdir
|
||||
make_from.loc = src
|
||||
stored = make_from
|
||||
else
|
||||
base_icon_state = icon_state
|
||||
stored = new /obj/structure/disposalconstruct(src,direction=dir)
|
||||
switch(base_icon_state)
|
||||
if("pipe-s")
|
||||
stored.ptype = DISP_PIPE_STRAIGHT
|
||||
if("pipe-c")
|
||||
stored.ptype = DISP_PIPE_BENT
|
||||
if("pipe-j1")
|
||||
stored.ptype = DISP_JUNCTION
|
||||
if("pipe-j2")
|
||||
stored.ptype = DISP_JUNCTION_FLIP
|
||||
if("pipe-y")
|
||||
stored.ptype = DISP_YJUNCTION
|
||||
if("pipe-t")
|
||||
stored.ptype = DISP_END_TRUNK
|
||||
if("pipe-j1s")
|
||||
stored.ptype = DISP_SORTJUNCTION
|
||||
if("pipe-j2s")
|
||||
stored.ptype = DISP_SORTJUNCTION_FLIP
|
||||
return
|
||||
|
||||
|
||||
// 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(src.loc)
|
||||
AM.pipe_eject(0)
|
||||
qdel(H)
|
||||
return ..()
|
||||
|
||||
// otherwise, do normal expel from turf
|
||||
else
|
||||
expel(H, T, 0)
|
||||
return ..()
|
||||
|
||||
// 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(fromdir)
|
||||
return dpdir & (~turn(fromdir, 180))
|
||||
|
||||
// transfer the holder through this pipe segment
|
||||
// overriden for special behaviour
|
||||
//
|
||||
/obj/structure/disposalpipe/proc/transfer(obj/structure/disposalholder/H)
|
||||
var/nextdir = nextdir(H.dir)
|
||||
return transfer_to_dir(H, nextdir)
|
||||
|
||||
/obj/structure/disposalpipe/proc/transfer_to_dir(obj/structure/disposalholder/H, nextdir)
|
||||
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.loc = P
|
||||
return P
|
||||
else // if wasn't a pipe, then they're now in our turf
|
||||
H.loc = get_turf(src)
|
||||
return null
|
||||
|
||||
// update the icon_state to reflect hidden status
|
||||
/obj/structure/disposalpipe/proc/update()
|
||||
var/turf/T = src.loc
|
||||
hide(T.intact && !istype(T,/turf/open/space)) // space never hides pipes
|
||||
|
||||
// hide called by levelupdate if turf intact status changes
|
||||
// change visibility status and force update of icon
|
||||
/obj/structure/disposalpipe/hide(var/intact)
|
||||
invisibility = intact ? INVISIBILITY_MAXIMUM: 0 // hide if floor is intact
|
||||
updateicon()
|
||||
|
||||
// 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()
|
||||
if(invisibility)
|
||||
icon_state = "[base_icon_state]f"
|
||||
else
|
||||
icon_state = base_icon_state
|
||||
return
|
||||
|
||||
|
||||
// expel the held objects into a turf
|
||||
// called when there is a break in the pipe
|
||||
//
|
||||
|
||||
/obj/structure/disposalpipe/proc/expel(obj/structure/disposalholder/H, turf/T, direction)
|
||||
|
||||
var/turf/target
|
||||
|
||||
if(istype(T, /turf/open/floor)) //intact floor, pop the tile
|
||||
var/turf/open/floor/myturf = T
|
||||
if(myturf.builtin_tile)
|
||||
myturf.builtin_tile.loc = T
|
||||
myturf.builtin_tile = null
|
||||
myturf.make_plating()
|
||||
|
||||
if(direction) // direction is specified
|
||||
if(istype(T, /turf/open/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(src.loc)
|
||||
AM.pipe_eject(direction)
|
||||
AM.throw_at_fast(target, 10, 1)
|
||||
|
||||
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(src.loc)
|
||||
AM.pipe_eject(0)
|
||||
AM.throw_at_fast(target, 5, 1)
|
||||
H.vent_gas(T)
|
||||
qdel(H)
|
||||
return
|
||||
|
||||
// call to break the pipe
|
||||
// will expel any holder inside at the time
|
||||
// then delete the pipe
|
||||
// remains : set to leave broken pipe pieces in place
|
||||
/obj/structure/disposalpipe/proc/broken(remains = 0)
|
||||
if(remains)
|
||||
for(var/D in cardinal)
|
||||
if(D & dpdir)
|
||||
var/obj/structure/disposalpipe/broken/P = new(src.loc)
|
||||
P.setDir(D)
|
||||
|
||||
src.invisibility = INVISIBILITY_MAXIMUM // 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(src.loc)
|
||||
AM.pipe_eject(0)
|
||||
qdel(H)
|
||||
return
|
||||
|
||||
// otherwise, do normal expel from turf
|
||||
if(H)
|
||||
expel(H, T, 0)
|
||||
|
||||
spawn(2) // delete pipe after 2 ticks to ensure expel proc finished
|
||||
qdel(src)
|
||||
|
||||
|
||||
// pipe affected by explosion
|
||||
/obj/structure/disposalpipe/ex_act(severity, target)
|
||||
|
||||
//pass on ex_act to our contents before calling it on ourself
|
||||
var/obj/structure/disposalholder/H = locate() in src
|
||||
if(H)
|
||||
H.contents_explosion(severity, target)
|
||||
|
||||
switch(severity)
|
||||
if(1)
|
||||
broken(0)
|
||||
return
|
||||
if(2)
|
||||
health -= rand(5,15)
|
||||
healthcheck()
|
||||
return
|
||||
if(3)
|
||||
health -= rand(0,15)
|
||||
healthcheck()
|
||||
return
|
||||
|
||||
|
||||
// test health for brokenness
|
||||
/obj/structure/disposalpipe/proc/healthcheck()
|
||||
if(health < -2)
|
||||
broken(0)
|
||||
else if(health<1)
|
||||
broken(1)
|
||||
return
|
||||
|
||||
//attack by item
|
||||
//weldingtool: unfasten and convert to obj/disposalconstruct
|
||||
|
||||
/obj/structure/disposalpipe/attackby(obj/item/I, mob/user, params)
|
||||
var/turf/T = src.loc
|
||||
if(T.intact)
|
||||
return // prevent interaction with T-scanner revealed pipes
|
||||
add_fingerprint(user)
|
||||
if(istype(I, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/W = I
|
||||
if(can_be_deconstructed(user))
|
||||
if(W.remove_fuel(0,user))
|
||||
playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
|
||||
user << "<span class='notice'>You start slicing the disposal pipe...</span>"
|
||||
// check if anything changed over 2 seconds
|
||||
if(do_after(user,30, target = src))
|
||||
if(!src || !W.isOn()) return
|
||||
Deconstruct()
|
||||
user << "<span class='notice'>You slice the disposal pipe.</span>"
|
||||
else
|
||||
return ..()
|
||||
|
||||
//checks if something is blocking the deconstruction (e.g. trunk with a bin still linked to it)
|
||||
/obj/structure/disposalpipe/proc/can_be_deconstructed()
|
||||
. = 1
|
||||
|
||||
// called when pipe is cut with welder
|
||||
/obj/structure/disposalpipe/Deconstruct()
|
||||
if(stored)
|
||||
var/turf/T = loc
|
||||
stored.loc = T
|
||||
transfer_fingerprints_to(stored)
|
||||
stored.setDir(dir)
|
||||
stored.density = 0
|
||||
stored.anchored = 1
|
||||
stored.update_icon()
|
||||
..()
|
||||
|
||||
/obj/structure/disposalpipe/singularity_pull(S, current_size)
|
||||
if(current_size >= STAGE_FIVE)
|
||||
Deconstruct()
|
||||
|
||||
// *** TEST verb
|
||||
//client/verb/dispstop()
|
||||
// for(var/obj/structure/disposalholder/H in world)
|
||||
// H.active = 0
|
||||
|
||||
// a straight or bent segment
|
||||
/obj/structure/disposalpipe/segment
|
||||
icon_state = "pipe-s"
|
||||
|
||||
/obj/structure/disposalpipe/segment/New()
|
||||
..()
|
||||
if(stored.ptype == DISP_PIPE_STRAIGHT)
|
||||
dpdir = dir | turn(dir, 180)
|
||||
else
|
||||
dpdir = dir | turn(dir, -90)
|
||||
|
||||
update()
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
//a three-way junction with dir being the dominant direction
|
||||
/obj/structure/disposalpipe/junction
|
||||
icon_state = "pipe-j1"
|
||||
|
||||
/obj/structure/disposalpipe/junction/New()
|
||||
..()
|
||||
switch(stored.ptype)
|
||||
if(DISP_JUNCTION)
|
||||
dpdir = dir | turn(dir, -90) | turn(dir,180)
|
||||
if(DISP_JUNCTION_FLIP)
|
||||
dpdir = dir | turn(dir, 90) | turn(dir,180)
|
||||
if(DISP_YJUNCTION)
|
||||
dpdir = dir | turn(dir,90) | turn(dir, -90)
|
||||
update()
|
||||
return
|
||||
|
||||
|
||||
// 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(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)
|
||||
|
||||
//a three-way junction that sorts objects
|
||||
/obj/structure/disposalpipe/sortjunction
|
||||
desc = "An underfloor disposal pipe with a package sorting mechanism."
|
||||
icon_state = "pipe-j1s"
|
||||
var/sortType = 0
|
||||
// To be set in map editor.
|
||||
// Supports both singular numbers and strings of numbers similar to access level strings.
|
||||
// Look at the list called TAGGERLOCATIONS in /_globalvars/lists/flavor_misc.dm
|
||||
var/list/sortTypes = list()
|
||||
var/posdir = 0
|
||||
var/negdir = 0
|
||||
var/sortdir = 0
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/examine(mob/user)
|
||||
..()
|
||||
if(sortTypes.len>0)
|
||||
user << "It is tagged with the following tags:"
|
||||
for(var/t in sortTypes)
|
||||
user << TAGGERLOCATIONS[t]
|
||||
else
|
||||
user << "It has no sorting tags set."
|
||||
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/proc/updatedir()
|
||||
posdir = dir
|
||||
negdir = turn(posdir, 180)
|
||||
|
||||
if(stored.ptype == DISP_SORTJUNCTION)
|
||||
sortdir = turn(posdir, -90)
|
||||
else
|
||||
icon_state = "pipe-j2s"
|
||||
sortdir = turn(posdir, 90)
|
||||
|
||||
dpdir = sortdir | posdir | negdir
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/New()
|
||||
..()
|
||||
|
||||
// Generate a list of soring tags.
|
||||
if(sortType)
|
||||
if(isnum(sortType))
|
||||
sortTypes |= sortType
|
||||
else if(istext(sortType))
|
||||
var/list/sorts = splittext(sortType,";")
|
||||
for(var/x in sorts)
|
||||
var/n = text2num(x)
|
||||
if(n)
|
||||
sortTypes |= n
|
||||
|
||||
updatedir()
|
||||
update()
|
||||
return
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/device/destTagger))
|
||||
var/obj/item/device/destTagger/O = I
|
||||
|
||||
if(O.currTag > 0)// Tag set
|
||||
if(O.currTag in sortTypes)
|
||||
sortTypes -= O.currTag
|
||||
user << "<span class='notice'>Removed \"[TAGGERLOCATIONS[O.currTag]]\" filter.</span>"
|
||||
else
|
||||
sortTypes |= O.currTag
|
||||
user << "<span class='notice'>Added \"[TAGGERLOCATIONS[O.currTag]]\" filter.</span>"
|
||||
playsound(src.loc, 'sound/machines/twobeep.ogg', 100, 1)
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
// 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)
|
||||
//var/flipdir = turn(fromdir, 180)
|
||||
if(fromdir != sortdir) // probably came from the negdir
|
||||
|
||||
if(sortTag in sortTypes) //if destination matches filtered type...
|
||||
return sortdir // exit through sortdirection
|
||||
else
|
||||
return posdir
|
||||
else // came from sortdir
|
||||
// so go with the flow to positive direction
|
||||
return posdir
|
||||
|
||||
/obj/structure/disposalpipe/sortjunction/transfer(obj/structure/disposalholder/H)
|
||||
var/nextdir = nextdir(H.dir, H.destinationTag)
|
||||
return transfer_to_dir(H, nextdir)
|
||||
|
||||
//a three-way junction that sorts objects destined for the mail office mail table (tomail = 1)
|
||||
/obj/structure/disposalpipe/wrapsortjunction
|
||||
|
||||
desc = "An underfloor disposal pipe which sorts wrapped and unwrapped objects."
|
||||
icon_state = "pipe-j1s"
|
||||
var/posdir = 0
|
||||
var/negdir = 0
|
||||
var/sortdir = 0
|
||||
|
||||
/obj/structure/disposalpipe/wrapsortjunction/New()
|
||||
..()
|
||||
posdir = dir
|
||||
if(stored.ptype == DISP_SORTJUNCTION)
|
||||
sortdir = turn(posdir, -90)
|
||||
negdir = turn(posdir, 180)
|
||||
else
|
||||
icon_state = "pipe-j2s"
|
||||
sortdir = turn(posdir, 90)
|
||||
negdir = turn(posdir, 180)
|
||||
dpdir = sortdir | posdir | negdir
|
||||
|
||||
update()
|
||||
return
|
||||
|
||||
// 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/wrapsortjunction/nextdir(fromdir, istomail)
|
||||
//var/flipdir = turn(fromdir, 180)
|
||||
if(fromdir != sortdir) // probably came from the negdir
|
||||
|
||||
if(istomail) //if destination matches filtered type...
|
||||
return sortdir // exit through sortdirection
|
||||
else
|
||||
return posdir
|
||||
else // came from sortdir
|
||||
// so go with the flow to positive direction
|
||||
return posdir
|
||||
|
||||
/obj/structure/disposalpipe/wrapsortjunction/transfer(obj/structure/disposalholder/H)
|
||||
var/nextdir = nextdir(H.dir, H.tomail)
|
||||
return transfer_to_dir(H, nextdir)
|
||||
|
||||
//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/New()
|
||||
..()
|
||||
dpdir = dir
|
||||
spawn(1)
|
||||
getlinked()
|
||||
|
||||
update()
|
||||
return
|
||||
|
||||
/obj/structure/disposalpipe/trunk/Destroy()
|
||||
if(linked)
|
||||
if(istype(linked, /obj/structure/disposaloutlet))
|
||||
var/obj/structure/disposaloutlet/D = linked
|
||||
D.trunk = null
|
||||
else if(istype(linked, /obj/machinery/disposal))
|
||||
var/obj/machinery/disposal/D = linked
|
||||
D.trunk = null
|
||||
return ..()
|
||||
|
||||
/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
|
||||
|
||||
update()
|
||||
return
|
||||
|
||||
/obj/structure/disposalpipe/trunk/can_be_deconstructed(mob/user)
|
||||
if(linked)
|
||||
user << "<span class='warning'>You need to deconstruct disposal machinery above this pipe!</span>"
|
||||
else
|
||||
. = 1
|
||||
|
||||
// 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(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, get_turf(src), 0) // expel at turf
|
||||
return null
|
||||
|
||||
/obj/structure/disposalpipe/trunk/nextdir(fromdir)
|
||||
if(fromdir == DOWN)
|
||||
return dir
|
||||
else
|
||||
return 0
|
||||
|
||||
// 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."
|
||||
|
||||
/obj/structure/disposalpipe/broken/New()
|
||||
..()
|
||||
update()
|
||||
return
|
||||
|
||||
// the disposal outlet machine
|
||||
|
||||
/obj/structure/disposalpipe/broken/Deconstruct()
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/disposaloutlet
|
||||
name = "disposal outlet"
|
||||
desc = "An outlet for the pneumatic disposal system."
|
||||
icon = 'icons/obj/atmospherics/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/obj/structure/disposalpipe/trunk/trunk = null // the attached pipe trunk
|
||||
var/obj/structure/disposalconstruct/stored
|
||||
var/mode = 0
|
||||
var/start_eject = 0
|
||||
var/eject_range = 2
|
||||
|
||||
/obj/structure/disposaloutlet/New(loc, var/obj/structure/disposalconstruct/make_from)
|
||||
..()
|
||||
|
||||
if(make_from)
|
||||
setDir(make_from.dir)
|
||||
make_from.loc = src
|
||||
stored = make_from
|
||||
else
|
||||
stored = new (src, DISP_END_OUTLET,dir)
|
||||
|
||||
spawn(1)
|
||||
target = get_ranged_target_turf(src, dir, 10)
|
||||
|
||||
trunk = locate() in src.loc
|
||||
if(trunk)
|
||||
trunk.linked = src // link the pipe trunk to self
|
||||
|
||||
/obj/structure/disposaloutlet/Destroy()
|
||||
if(trunk)
|
||||
trunk.linked = null
|
||||
return ..()
|
||||
|
||||
// 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)
|
||||
var/turf/T = get_turf(src)
|
||||
flick("outlet-open", src)
|
||||
if((start_eject + 30) < world.time)
|
||||
start_eject = world.time
|
||||
playsound(src, 'sound/machines/warning-buzzer.ogg', 50, 0, 0)
|
||||
sleep(20)
|
||||
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
|
||||
else
|
||||
sleep(20)
|
||||
if(H)
|
||||
for(var/atom/movable/AM in H)
|
||||
AM.forceMove(T)
|
||||
AM.pipe_eject(dir)
|
||||
AM.throw_at_fast(target, eject_range, 1)
|
||||
|
||||
H.vent_gas(T)
|
||||
qdel(H)
|
||||
return
|
||||
|
||||
/obj/structure/disposaloutlet/attackby(obj/item/I, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if(istype(I, /obj/item/weapon/screwdriver))
|
||||
if(mode==0)
|
||||
mode=1
|
||||
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
|
||||
user << "<span class='notice'>You remove the screws around the power connection.</span>"
|
||||
else if(mode==1)
|
||||
mode=0
|
||||
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
|
||||
user << "<span class='notice'>You attach the screws around the power connection.</span>"
|
||||
|
||||
else if(istype(I,/obj/item/weapon/weldingtool) && mode==1)
|
||||
var/obj/item/weapon/weldingtool/W = I
|
||||
if(W.remove_fuel(0,user))
|
||||
playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
|
||||
user << "<span class='notice'>You start slicing the floorweld off \the [src]...</span>"
|
||||
if(do_after(user,20/I.toolspeed, target = src))
|
||||
if(!src || !W.isOn()) return
|
||||
user << "<span class='notice'>You slice the floorweld off \the [src].</span>"
|
||||
stored.loc = loc
|
||||
src.transfer_fingerprints_to(stored)
|
||||
stored.update_icon()
|
||||
stored.anchored = 0
|
||||
stored.density = 1
|
||||
qdel(src)
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
// 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
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/pipe_eject(direction)
|
||||
var/list/dirs
|
||||
if(direction)
|
||||
dirs = list( direction, turn(direction, -45), turn(direction, 45))
|
||||
else
|
||||
dirs = alldirs.Copy()
|
||||
|
||||
src.streak(dirs)
|
||||
|
||||
/obj/effect/decal/cleanable/robot_debris/gib/pipe_eject(direction)
|
||||
var/list/dirs
|
||||
if(direction)
|
||||
dirs = list( direction, turn(direction, -45), turn(direction, 45))
|
||||
else
|
||||
dirs = alldirs.Copy()
|
||||
|
||||
src.streak(dirs)
|
||||
@@ -0,0 +1,544 @@
|
||||
|
||||
//disposal bin and Delivery chute.
|
||||
|
||||
#define SEND_PRESSURE 0.05*ONE_ATMOSPHERE
|
||||
|
||||
/obj/machinery/disposal
|
||||
icon = 'icons/obj/atmospherics/pipes/disposal.dmi'
|
||||
anchored = 1
|
||||
density = 1
|
||||
on_blueprints = TRUE
|
||||
var/datum/gas_mixture/air_contents // internal reservoir
|
||||
var/mode = 1 // mode -1=screws removed 0=off 1=charging 2=charged
|
||||
var/flush = 0 // true if flush handle is pulled
|
||||
var/obj/structure/disposalpipe/trunk/trunk = null // the attached pipe trunk
|
||||
var/flushing = 0 // 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
|
||||
var/obj/structure/disposalconstruct/stored
|
||||
// create a new disposal
|
||||
// find the attached trunk (if present) and init gas resvr.
|
||||
|
||||
/obj/machinery/disposal/New(loc, var/obj/structure/disposalconstruct/make_from)
|
||||
..()
|
||||
|
||||
if(make_from)
|
||||
setDir(make_from.dir)
|
||||
make_from.loc = 0
|
||||
stored = make_from
|
||||
else
|
||||
stored = new /obj/structure/disposalconstruct(0,DISP_END_BIN,dir)
|
||||
|
||||
trunk_check()
|
||||
|
||||
air_contents = new/datum/gas_mixture()
|
||||
//gas.volume = 1.05 * CELLSTANDARD
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/disposal/proc/trunk_check()
|
||||
trunk = locate() in src.loc
|
||||
if(!trunk)
|
||||
mode = 0
|
||||
flush = 0
|
||||
else
|
||||
mode = initial(mode)
|
||||
flush = initial(flush)
|
||||
trunk.linked = src // link the pipe trunk to self
|
||||
|
||||
/obj/machinery/disposal/Destroy()
|
||||
eject()
|
||||
if(trunk)
|
||||
trunk.linked = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/disposal/singularity_pull(S, current_size)
|
||||
if(current_size >= STAGE_FIVE)
|
||||
Deconstruct()
|
||||
|
||||
/obj/machinery/disposal/initialize()
|
||||
// this will get a copy of the air turf and take a SEND PRESSURE amount of air from it
|
||||
var/atom/L = loc
|
||||
var/datum/gas_mixture/env = new
|
||||
env.copy_from(L.return_air())
|
||||
var/datum/gas_mixture/removed = env.remove(SEND_PRESSURE + 1)
|
||||
air_contents.merge(removed)
|
||||
trunk_check()
|
||||
|
||||
/obj/machinery/disposal/attackby(obj/item/I, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if(mode<=0)
|
||||
if(istype(I, /obj/item/weapon/screwdriver))
|
||||
if(contents.len > 0)
|
||||
user << "<span class='notice'>Eject the items first!</span>"
|
||||
return
|
||||
if(mode==0)
|
||||
mode=-1
|
||||
else
|
||||
mode=0
|
||||
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
|
||||
user << "<span class='notice'>You [mode==0?"attach":"remove"] the screws around the power connection.</span>"
|
||||
return
|
||||
else if(istype(I,/obj/item/weapon/weldingtool) && mode==-1)
|
||||
var/obj/item/weapon/weldingtool/W = I
|
||||
if(W.remove_fuel(0,user))
|
||||
if(contents.len > 0)
|
||||
user << "<span class='notice'>Eject the items first!</span>"
|
||||
return
|
||||
playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
|
||||
user << "<span class='notice'>You start slicing the floorweld off \the [src]...</span>"
|
||||
if(do_after(user,20/I.toolspeed, target = src))
|
||||
if(!W.isOn())
|
||||
return
|
||||
user << "<span class='notice'>You slice the floorweld off \the [src].</span>"
|
||||
Deconstruct()
|
||||
return
|
||||
|
||||
if(user.a_intent != "harm")
|
||||
if(!user.drop_item() || (I.flags & ABSTRACT))
|
||||
return
|
||||
place_item_in_disposal(I, user)
|
||||
update_icon()
|
||||
return 1 //no afterattack
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/disposal/proc/place_item_in_disposal(obj/item/I, mob/user)
|
||||
I.loc = src
|
||||
user.visible_message("[user.name] places \the [I] into \the [src].", \
|
||||
"<span class='notice'>You place \the [I] into \the [src].</span>")
|
||||
|
||||
|
||||
// mouse drop another mob or self
|
||||
|
||||
/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)
|
||||
if(!iscarbon(user) && !user.ventcrawler) //only carbon and ventcrawlers can climb into disposal by themselves.
|
||||
return
|
||||
if(!istype(user.loc, /turf/)) //No magically doing it from inside closets
|
||||
return
|
||||
if(target.buckled || target.has_buckled_mobs())
|
||||
return
|
||||
if(target.mob_size > MOB_SIZE_HUMAN)
|
||||
user << "<span class='warning'>[target] doesn't fit inside [src]!</span>"
|
||||
return
|
||||
add_fingerprint(user)
|
||||
if(user == target)
|
||||
user.visible_message("[user] starts climbing into [src].", \
|
||||
"<span class='notice'>You start climbing into [src]...</span>")
|
||||
else
|
||||
target.visible_message("<span class='danger'>[user] starts putting [target] into [src].</span>", \
|
||||
"<span class='userdanger'>[user] starts putting you into [src]!</span>")
|
||||
if(do_mob(user, target, 20))
|
||||
if (!loc)
|
||||
return
|
||||
target.forceMove(src)
|
||||
if(user == target)
|
||||
user.visible_message("[user] climbs into [src].", \
|
||||
"<span class='notice'>You climb into [src].</span>")
|
||||
else
|
||||
target.visible_message("<span class='danger'>[user] has placed [target] in [src].</span>", \
|
||||
"<span class='userdanger'>[user] has placed [target] in [src].</span>")
|
||||
add_logs(user, target, "stuffed", addition="into [src]")
|
||||
target.LAssailant = user
|
||||
update_icon()
|
||||
|
||||
// can breath normally in the disposal
|
||||
/obj/machinery/disposal/alter_health()
|
||||
return get_turf(src)
|
||||
|
||||
/obj/machinery/disposal/relaymove(mob/user)
|
||||
attempt_escape(user)
|
||||
|
||||
// resist to escape the bin
|
||||
/obj/machinery/disposal/container_resist()
|
||||
attempt_escape(usr)
|
||||
|
||||
/obj/machinery/disposal/proc/attempt_escape(mob/user)
|
||||
if(src.flushing)
|
||||
return
|
||||
go_out(user)
|
||||
return
|
||||
|
||||
// leave the disposal
|
||||
/obj/machinery/disposal/proc/go_out(mob/user)
|
||||
|
||||
user.loc = src.loc
|
||||
user.reset_perspective(null)
|
||||
update_icon()
|
||||
return
|
||||
|
||||
|
||||
// monkeys and xenos can only pull the flush lever
|
||||
/obj/machinery/disposal/attack_paw(mob/user)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
flush = !flush
|
||||
update_icon()
|
||||
|
||||
// ai as human but can't flush
|
||||
/obj/machinery/disposal/attack_ai(mob/user)
|
||||
interact(user, 1)
|
||||
|
||||
// human interact with machine
|
||||
/obj/machinery/disposal/attack_hand(mob/user)
|
||||
if(user && user.loc == src)
|
||||
usr << "<span class='warning'>You cannot reach the controls from inside!</span>"
|
||||
return
|
||||
/*
|
||||
if(mode==-1)
|
||||
usr << "\red The disposal units power is disabled."
|
||||
return
|
||||
*/
|
||||
interact(user, 0)
|
||||
|
||||
// hostile mob escape from disposals
|
||||
/obj/machinery/disposal/attack_animal(mob/living/simple_animal/M)
|
||||
if(M.environment_smash)
|
||||
M.do_attack_animation(src)
|
||||
visible_message("<span class='danger'>[M.name] smashes \the [src] apart!</span>")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
// eject the contents of the disposal unit
|
||||
/obj/machinery/disposal/proc/eject()
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/atom/movable/AM in src)
|
||||
AM.forceMove(T)
|
||||
AM.pipe_eject(0)
|
||||
update_icon()
|
||||
|
||||
// update the icon & overlays to reflect mode & status
|
||||
/obj/machinery/disposal/update_icon()
|
||||
return
|
||||
|
||||
/obj/machinery/disposal/proc/flush()
|
||||
flushing = 1
|
||||
flushAnimation()
|
||||
sleep(10)
|
||||
if(last_sound < world.time + 1)
|
||||
playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0)
|
||||
last_sound = world.time
|
||||
sleep(5)
|
||||
if(qdeleted(src))
|
||||
return
|
||||
var/obj/structure/disposalholder/H = new()
|
||||
newHolderDestination(H)
|
||||
H.init(src)
|
||||
air_contents = new()
|
||||
H.start(src)
|
||||
flushing = 0
|
||||
flush = 0
|
||||
|
||||
/obj/machinery/disposal/proc/newHolderDestination(obj/structure/disposalholder/H)
|
||||
for(var/obj/item/smallDelivery/O in src)
|
||||
H.tomail = 1
|
||||
return
|
||||
|
||||
/obj/machinery/disposal/proc/flushAnimation()
|
||||
flick("[icon_state]-flush", src)
|
||||
|
||||
// called when area power changes
|
||||
/obj/machinery/disposal/power_change()
|
||||
..() // do default setting/reset of stat NOPOWER bit
|
||||
update_icon() // 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/T = get_turf(src)
|
||||
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(T)
|
||||
AM.pipe_eject(0)
|
||||
AM.throw_at_fast(target, 5, 1)
|
||||
|
||||
H.vent_gas(loc)
|
||||
qdel(H)
|
||||
|
||||
/obj/machinery/disposal/Deconstruct()
|
||||
if(stored)
|
||||
var/turf/T = loc
|
||||
stored.loc = T
|
||||
src.transfer_fingerprints_to(stored)
|
||||
stored.anchored = 0
|
||||
stored.density = 1
|
||||
stored.update_icon()
|
||||
..()
|
||||
|
||||
//How disposal handles getting a storage dump from a storage object
|
||||
/obj/machinery/disposal/storage_contents_dump_act(obj/item/weapon/storage/src_object, mob/user)
|
||||
for(var/obj/item/I in src_object)
|
||||
if(user.s_active != src_object)
|
||||
if(I.on_found(user))
|
||||
return
|
||||
src_object.remove_from_storage(I, src)
|
||||
return 1
|
||||
|
||||
|
||||
// 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
|
||||
|
||||
/obj/machinery/disposal/bin
|
||||
name = "disposal unit"
|
||||
desc = "A pneumatic waste disposal unit."
|
||||
icon_state = "disposal"
|
||||
|
||||
// attack by item places it in to disposal
|
||||
/obj/machinery/disposal/bin/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/weapon/storage/bag/trash))
|
||||
var/obj/item/weapon/storage/bag/trash/T = I
|
||||
user << "<span class='warning'>You empty the bag.</span>"
|
||||
for(var/obj/item/O in T.contents)
|
||||
T.remove_from_storage(O,src)
|
||||
T.update_icon()
|
||||
update_icon()
|
||||
else
|
||||
return ..()
|
||||
|
||||
// user interaction
|
||||
/obj/machinery/disposal/bin/interact(mob/user, ai=0)
|
||||
src.add_fingerprint(user)
|
||||
if(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 = Clamp(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 100)
|
||||
|
||||
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/bin/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(usr.loc == src)
|
||||
usr << "<span class='warning'>You cannot reach the controls from inside!</span>"
|
||||
return
|
||||
|
||||
if(mode==-1 && !href_list["eject"]) // only allow ejecting if mode is -1
|
||||
usr << "<span class='danger'>\The [src]'s power is disabled.</span>"
|
||||
return
|
||||
..()
|
||||
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_icon()
|
||||
|
||||
if(href_list["handle"])
|
||||
flush = text2num(href_list["handle"])
|
||||
update_icon()
|
||||
|
||||
if(href_list["eject"])
|
||||
eject()
|
||||
return
|
||||
|
||||
/obj/machinery/disposal/bin/CanPass(atom/movable/mover, turf/target, height=0)
|
||||
if (istype(mover,/obj/item) && mover.throwing)
|
||||
var/obj/item/I = mover
|
||||
if(istype(I, /obj/item/projectile))
|
||||
return
|
||||
if(prob(75))
|
||||
I.loc = src
|
||||
visible_message("<span class='notice'>\the [I] lands in \the [src].</span>")
|
||||
update_icon()
|
||||
else
|
||||
visible_message("<span class='notice'>\the [I] bounces off of \the [src]'s rim!</span>")
|
||||
return 0
|
||||
else
|
||||
return ..(mover, target, height)
|
||||
|
||||
/obj/machinery/disposal/bin/flush()
|
||||
..()
|
||||
if(mode == 2)
|
||||
mode = 1
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/disposal/bin/update_icon()
|
||||
cut_overlays()
|
||||
if(stat & BROKEN)
|
||||
mode = 0
|
||||
flush = 0
|
||||
return
|
||||
|
||||
// flush handle
|
||||
if(flush)
|
||||
add_overlay(image('icons/obj/atmospherics/pipes/disposal.dmi', "dispover-handle"))
|
||||
|
||||
// only handle is shown if no power
|
||||
if(stat & NOPOWER || mode == -1)
|
||||
return
|
||||
|
||||
// check for items in disposal - occupied light
|
||||
if(contents.len > 0)
|
||||
add_overlay(image('icons/obj/atmospherics/pipes/disposal.dmi', "dispover-full"))
|
||||
|
||||
// charging and ready light
|
||||
if(mode == 1)
|
||||
add_overlay(image('icons/obj/atmospherics/pipes/disposal.dmi', "dispover-charge"))
|
||||
else if(mode == 2)
|
||||
add_overlay(image('icons/obj/atmospherics/pipes/disposal.dmi', "dispover-ready"))
|
||||
|
||||
|
||||
// timed process
|
||||
// charge the gas reservoir and perform flush if ready
|
||||
/obj/machinery/disposal/bin/process()
|
||||
if(stat & BROKEN) // nothing can happen if broken
|
||||
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
|
||||
spawn(0)
|
||||
flush()
|
||||
|
||||
if(stat & NOPOWER) // won't charge if no power
|
||||
return
|
||||
|
||||
use_power(100) // base power usage
|
||||
|
||||
if(mode != 1) // if off or ready, no need to charge
|
||||
return
|
||||
|
||||
// otherwise charge
|
||||
use_power(500) // charging power usage
|
||||
|
||||
var/atom/L = loc // recharging from loc turf
|
||||
|
||||
var/datum/gas_mixture/env = L.return_air()
|
||||
var/pressure_delta = (SEND_PRESSURE*1.01) - air_contents.return_pressure()
|
||||
|
||||
if(env.temperature > 0)
|
||||
var/transfer_moles = 0.1 * pressure_delta*air_contents.volume/(env.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
//Actually transfer the gas
|
||||
var/datum/gas_mixture/removed = env.remove(transfer_moles)
|
||||
air_contents.merge(removed)
|
||||
air_update_turf()
|
||||
|
||||
|
||||
// if full enough, switch to ready mode
|
||||
if(air_contents.return_pressure() >= SEND_PRESSURE)
|
||||
mode = 2
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/obj/machinery/disposal/bin/get_remote_view_fullscreens(mob/user)
|
||||
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
|
||||
user.overlay_fullscreen("remote_view", /obj/screen/fullscreen/impaired, 2)
|
||||
|
||||
|
||||
//Delivery Chute
|
||||
|
||||
/obj/machinery/disposal/deliveryChute
|
||||
name = "delivery chute"
|
||||
desc = "A chute for big and small packages alike!"
|
||||
density = 1
|
||||
icon_state = "intake"
|
||||
mode = 0 // the chute doesn't need charging and always works
|
||||
|
||||
/obj/machinery/disposal/deliveryChute/New(loc,var/obj/structure/disposalconstruct/make_from)
|
||||
..()
|
||||
stored.ptype = DISP_END_CHUTE
|
||||
spawn(5)
|
||||
trunk = locate() in loc
|
||||
if(trunk)
|
||||
trunk.linked = src // link the pipe trunk to self
|
||||
|
||||
/obj/machinery/disposal/deliveryChute/place_item_in_disposal(obj/item/I, mob/user)
|
||||
if(I.disposalEnterTry())
|
||||
..()
|
||||
flush()
|
||||
|
||||
/obj/machinery/disposal/deliveryChute/Bumped(atom/movable/AM) //Go straight into the chute
|
||||
if(!AM.disposalEnterTry())
|
||||
return
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
if(AM.loc.y != loc.y+1) return
|
||||
if(EAST)
|
||||
if(AM.loc.x != loc.x+1) return
|
||||
if(SOUTH)
|
||||
if(AM.loc.y != loc.y-1) return
|
||||
if(WEST)
|
||||
if(AM.loc.x != loc.x-1) return
|
||||
|
||||
if(istype(AM, /obj))
|
||||
var/obj/O = AM
|
||||
O.loc = src
|
||||
else if(istype(AM, /mob))
|
||||
var/mob/M = AM
|
||||
if(prob(2)) // to prevent mobs being stuck in infinite loops
|
||||
M << "<span class='warning'>You hit the edge of the chute.</span>"
|
||||
return
|
||||
M.forceMove(src)
|
||||
flush()
|
||||
|
||||
/atom/movable/proc/disposalEnterTry()
|
||||
return 1
|
||||
|
||||
/obj/item/projectile/disposalEnterTry()
|
||||
return
|
||||
|
||||
/obj/effect/disposalEnterTry()
|
||||
return
|
||||
|
||||
/obj/mecha/disposalEnterTry()
|
||||
return
|
||||
|
||||
/obj/machinery/disposal/deliveryChute/newHolderDestination(obj/structure/disposalholder/H)
|
||||
H.destinationTag = 1
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/obj/structure/bigDelivery
|
||||
name = "large parcel"
|
||||
desc = "A big wrapped package."
|
||||
icon = 'icons/obj/storage.dmi'
|
||||
icon_state = "deliverycloset"
|
||||
density = 1
|
||||
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
|
||||
var/giftwrapped = 0
|
||||
var/sortTag = 0
|
||||
|
||||
/obj/structure/bigDelivery/attack_hand(mob/user)
|
||||
playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/bigDelivery/Destroy()
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/atom/movable/AM in contents)
|
||||
AM.loc = T
|
||||
return ..()
|
||||
|
||||
/obj/structure/bigDelivery/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/device/destTagger))
|
||||
var/obj/item/device/destTagger/O = W
|
||||
|
||||
if(sortTag != O.currTag)
|
||||
var/tag = uppertext(TAGGERLOCATIONS[O.currTag])
|
||||
user << "<span class='notice'>*[tag]*</span>"
|
||||
sortTag = O.currTag
|
||||
playsound(loc, 'sound/machines/twobeep.ogg', 100, 1)
|
||||
|
||||
else if(istype(W, /obj/item/weapon/pen))
|
||||
var/str = copytext(sanitize(input(user,"Label text?","Set label","")),1,MAX_NAME_LEN)
|
||||
if(!str || !length(str))
|
||||
user << "<span class='warning'>Invalid text!</span>"
|
||||
return
|
||||
user.visible_message("[user] labels [src] as [str].")
|
||||
name = "[name] ([str])"
|
||||
|
||||
else if(istype(W, /obj/item/stack/wrapping_paper) && !giftwrapped)
|
||||
var/obj/item/stack/wrapping_paper/WP = W
|
||||
if(WP.use(3))
|
||||
user.visible_message("[user] wraps the package in festive paper!")
|
||||
giftwrapped = 1
|
||||
icon_state = "gift[icon_state]"
|
||||
else
|
||||
user << "<span class='warning'>You need more paper!</span>"
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/structure/bigDelivery/relay_container_resist(mob/living/user, obj/O)
|
||||
if(istype(loc, /atom/movable))
|
||||
var/atom/movable/AM = loc //can't unwrap the wrapped container if it's inside something.
|
||||
AM.relay_container_resist(user, O)
|
||||
return
|
||||
user << "<span class='notice'>You lean on the back of [O] and start pushing to rip the wrapping around it.</span>"
|
||||
if(do_after(user, 50, target = O))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src || O.loc != src )
|
||||
return
|
||||
user << "<span class='notice'>You successfully removed [O]'s wrapping !</span>"
|
||||
O.loc = loc
|
||||
playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1)
|
||||
qdel(src)
|
||||
else
|
||||
if(user.loc == src) //so we don't get the message if we resisted multiple times and succeeded.
|
||||
user << "<span class='warning'>You fail to remove [O]'s wrapping!</span>"
|
||||
|
||||
|
||||
|
||||
/obj/item/smallDelivery
|
||||
name = "small parcel"
|
||||
desc = "A small wrapped package."
|
||||
icon = 'icons/obj/storage.dmi'
|
||||
icon_state = "deliverypackage3"
|
||||
var/giftwrapped = 0
|
||||
var/sortTag = 0
|
||||
|
||||
|
||||
/obj/item/smallDelivery/attack_self(mob/user)
|
||||
user.unEquip(src)
|
||||
for(var/X in contents)
|
||||
var/atom/movable/AM = X
|
||||
user.put_in_hands(AM)
|
||||
playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/smallDelivery/attack_self_tk(mob/user)
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
M.unEquip(src)
|
||||
for(var/X in contents)
|
||||
var/atom/movable/AM = X
|
||||
M.put_in_hands(AM)
|
||||
else
|
||||
for(var/X in contents)
|
||||
var/atom/movable/AM = X
|
||||
AM.forceMove(src.loc)
|
||||
playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/smallDelivery/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/device/destTagger))
|
||||
var/obj/item/device/destTagger/O = W
|
||||
|
||||
if(sortTag != O.currTag)
|
||||
var/tag = uppertext(TAGGERLOCATIONS[O.currTag])
|
||||
user << "<span class='notice'>*[tag]*</span>"
|
||||
sortTag = O.currTag
|
||||
playsound(loc, 'sound/machines/twobeep.ogg', 100, 1)
|
||||
|
||||
else if(istype(W, /obj/item/weapon/pen))
|
||||
var/str = copytext(sanitize(input(user,"Label text?","Set label","")),1,MAX_NAME_LEN)
|
||||
if(!str || !length(str))
|
||||
user << "<span class='warning'>Invalid text!</span>"
|
||||
return
|
||||
user.visible_message("[user] labels [src] as [str].")
|
||||
name = "[name] ([str])"
|
||||
|
||||
else if(istype(W, /obj/item/stack/wrapping_paper) && !giftwrapped)
|
||||
var/obj/item/stack/wrapping_paper/WP = W
|
||||
if(WP.use(1))
|
||||
icon_state = "gift[icon_state]"
|
||||
giftwrapped = 1
|
||||
user.visible_message("[user] wraps the package in festive paper!")
|
||||
else
|
||||
user << "<span class='warning'>You need more paper!</span>"
|
||||
|
||||
|
||||
/obj/item/device/destTagger
|
||||
name = "destination tagger"
|
||||
desc = "Used to set the destination of properly wrapped packages."
|
||||
icon_state = "cargotagger"
|
||||
var/currTag = 0
|
||||
//The whole system for the sorttype var is determined based on the order of this list,
|
||||
//disposals must always be 1, since anything that's untagged will automatically go to disposals, or sorttype = 1 --Superxpdude
|
||||
|
||||
//If you don't want to fuck up disposals, add to this list, and don't change the order.
|
||||
//If you insist on changing the order, you'll have to change every sort junction to reflect the new order. --Pete
|
||||
|
||||
w_class = 1
|
||||
item_state = "electronic"
|
||||
flags = CONDUCT
|
||||
slot_flags = SLOT_BELT
|
||||
|
||||
/obj/item/device/destTagger/proc/openwindow(mob/user)
|
||||
var/dat = "<tt><center><h1><b>TagMaster 2.2</b></h1></center>"
|
||||
|
||||
dat += "<table style='width:100%; padding:4px;'><tr>"
|
||||
for (var/i = 1, i <= TAGGERLOCATIONS.len, i++)
|
||||
dat += "<td><a href='?src=\ref[src];nextTag=[i]'>[TAGGERLOCATIONS[i]]</a></td>"
|
||||
|
||||
if(i%4==0)
|
||||
dat += "</tr><tr>"
|
||||
|
||||
dat += "</tr></table><br>Current Selection: [currTag ? TAGGERLOCATIONS[currTag] : "None"]</tt>"
|
||||
|
||||
user << browse(dat, "window=destTagScreen;size=450x350")
|
||||
onclose(user, "destTagScreen")
|
||||
|
||||
/obj/item/device/destTagger/attack_self(mob/user)
|
||||
openwindow(user)
|
||||
return
|
||||
|
||||
/obj/item/device/destTagger/Topic(href, href_list)
|
||||
add_fingerprint(usr)
|
||||
if(href_list["nextTag"])
|
||||
var/n = text2num(href_list["nextTag"])
|
||||
currTag = n
|
||||
openwindow(usr)
|
||||
Reference in New Issue
Block a user