initial commit - cross reference with 5th port - obviously has compile errors

This commit is contained in:
LetterJay
2016-07-03 02:17:19 -05:00
commit 35a1723e98
4355 changed files with 2221257 additions and 0 deletions
+340
View File
@@ -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)
+544
View File
@@ -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
+168
View File
@@ -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)