Initial Commit

This commit is contained in:
Tobba
2016-03-06 20:52:14 +01:00
commit b181d0b552
4325 changed files with 579453 additions and 0 deletions
+459
View File
@@ -0,0 +1,459 @@
// converyor belt
// moves items/mobs/movables in set direction every ptick
/obj/machinery/conveyor
icon = 'icons/obj/recycling.dmi'
icon_state = "conveyor0"
name = "conveyor belt"
desc = "A conveyor belt."
anchored = 1
power_usage = 100
layer = 2.5
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/basedir // this is the default (forward) direction, set by the map dir
// note dir var can vary when the direction changes
var/list/affecting // the list of all items that will be moved this ptick
var/id = "" // the control ID - must match controller ID
// following two only used if a diverter is present
var/divert = 0 // if non-zero, direction to divert items
var/divdir = 0 // if diverting, will be conveyer dir needed to divert (otherwise dense)
var/move_lag = 4
var/obj/machinery/conveyor/next_conveyor = null
/obj/machinery/conveyor/north
dir = NORTH
/obj/machinery/conveyor/south
dir = SOUTH
/obj/machinery/conveyor/east
dir = EAST
/obj/machinery/conveyor/west
dir = WEST
// create a conveyor
/obj/machinery/conveyor/New()
..()
basedir = dir
setdir()
// set the dir and target turf depending on the operating direction
/obj/machinery/conveyor/proc/setdir()
if(operating == -1)
dir = turn(basedir,180)
else
dir = basedir
next_conveyor = locate(/obj/machinery/conveyor) in get_step(src,dir)
update()
// update the icon depending on the operating condition
/obj/machinery/conveyor/proc/update()
if(stat & BROKEN)
icon_state = "conveyor-b"
operating = 0
if(!operable)
operating = 0
if(!operating)
for(var/atom/movable/A in loc.contents)
walk(A, 0)
icon_state = "conveyor[(operating != 0) && !(stat & NOPOWER)]"
// machine process
// move items to the target location
/obj/machinery/conveyor/process()
if(stat & (BROKEN | NOPOWER))
return
if(!operating)
return
if(!loc)
return
..()
for(var/atom/movable/A in loc.contents)
move_thing(A)
/obj/machinery/conveyor/proc/move_thing(var/atom/movable/A)
if(isobserver(A))
return
if(istype(A, /obj/machinery/bot) && A:on) //They drive against the motion of the conveyor, ok.
return
if(istype(A, /obj/critter) && A:flying) //They are flying above it, ok.
return
var/movedir = dir // base movement dir
if(divert && dir==divdir) // update if diverter present
movedir = divert
if(!A.anchored)
/* if (A.l_move_time == world.timeofday)
continue // already moved by another conveyor
*/
var/mob/M = A
if(istype(M) && M.buckled == src)
walk(M, dir, move_lag)
else
walk(A, movedir, move_lag)
/obj/machinery/conveyor/HasEntered(var/atom/movable/AM, /atom/oldloc)
..()
if(stat & (BROKEN | NOPOWER))
return
if(!operating)
return
if(!loc)
return
//DEBUG("[AM] entered conveyor at [showCoords(src.x, src.y, src.z)] and is being moved.")
move_thing(AM)
/obj/machinery/conveyor/HasExited(var/atom/movable/AM, var/atom/newloc)
..()
if(stat & (BROKEN | NOPOWER))
return
if(!operating)
return
if(!loc)
return
if(next_conveyor && next_conveyor.loc == newloc)
//Ok, they will soon walk() according to the new conveyor
//DEBUG("[AM] exited conveyor at [showCoords(src.x, src.y, src.z)] onto another conveyor! Wow!.")
var/mob/M = AM
if(istype(M) && M.buckled == src) //Transfer the buckle
M.buckled = next_conveyor
if(!next_conveyor.operating)
walk(AM, 0)
return
else
//Stop walking, we left the belt
//DEBUG("[AM] exited conveyor at [showCoords(src.x, src.y, src.z)] onto the cold, hard floor.")
var/mob/M = AM
if(istype(M) && M.buckled == src) //Unbuckle
M.buckled = null
new /obj/item/cable_coil/cut(M.loc)
walk(AM, 0)
// attack with item, place item on conveyor
/obj/machinery/conveyor/attackby(var/obj/item/I, mob/user)
if(istype(I, /obj/item/grab)) // special handling if grabbing a mob
var/obj/item/grab/G = I
G.affecting.Move(src.loc)
qdel(G)
return
else if(istype(I, /obj/item/cable_coil)) // if cable, see if a mob is present
var/mob/M = locate() in src.loc
if(M)
if (M == user)
src.visible_message("<span style=\"color:blue\">[M] ties \himself to the conveyor.</span>")
// note don't check for lying if self-tying
else
if(M.lying)
user.visible_message("<span style=\"color:blue\">[M] has been tied to the conveyor by [user].</span>", "<span style=\"color:blue\">You tie [M] to the converyor!</span>")
else
boutput(user, "<span style=\"color:blue\">[M] must be lying down to be tied to the converyor!</span>")
return
M.buckled = src
src.add_fingerprint(user)
I:use(1)
M.lying = 1
M.set_clothing_icon_dirty()
return
// else if no mob in loc, then allow coil to be placed
else if(istype(I, /obj/item/wirecutters))
var/mob/M = locate() in src.loc
if(M && M.buckled == src)
M.buckled = null
src.add_fingerprint(user)
if (M == user)
src.visible_message("<span style=\"color:blue\">[M] cuts \himself free from the conveyor.</span>")
else
src.visible_message("<span style=\"color:blue\">[M] had been cut free from the conveyor by [user].</span>")
return
else if(istype(I, /obj/item/ore_scoop))
// this is handled in the ore scoop's afterattack proc
return
// otherwise drop and place on conveyor
if (istype(user, /mob/living/silicon))
return
user.drop_item()
if(I && I.loc) I.set_loc(src.loc)
return
// attack with hand, move pulled object onto conveyor
/obj/machinery/conveyor/attack_hand(mob/user as mob)
if ((!( user.canmove ) || user.restrained() || !( user.pulling )))
return
if (user.pulling.anchored)
return
if ((user.pulling.loc != user.loc && get_dist(user, user.pulling) > 1))
return
if (ismob(user.pulling))
var/mob/M = user.pulling
M.pulling = null
step(user.pulling, get_dir(user.pulling.loc, src))
user.pulling = null
else
step(user.pulling, get_dir(user.pulling.loc, src))
user.pulling = null
return
// 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, basedir)
if(C)
C.set_operable(basedir, id, 0)
C = locate() in get_step(src, turn(basedir,180))
if(C)
C.set_operable(turn(basedir,180), id, 0)
//set the operable var if ID matches, propagating in the given direction
/obj/machinery/conveyor/proc/set_operable(stepdir, match_id, op)
if(id != match_id)
return
operable = op
update()
var/obj/machinery/conveyor/C = locate() in get_step(src, stepdir)
if(C)
C.set_operable(stepdir, id, op)
/obj/machinery/conveyor/power_change()
..()
update()
// converyor diverter
// extendable arm that can be switched so items on the conveyer are diverted sideways
// situate in same turf as conveyor
// only works if belts is running proper direction
//
//
/obj/machinery/diverter
icon = 'icons/obj/recycling.dmi'
icon_state = "diverter0"
name = "diverter"
desc = "A diverter arm for a conveyor belt."
anchored = 1
layer = FLY_LAYER
var/obj/machinery/conveyor/conv // the conveyor this diverter works on
var/deployed = 0 // true if diverter arm is extended
var/operating = 0 // true if arm is extending/contracting
var/divert_to // the dir that diverted items will be moved
var/divert_from // the dir items must be moving to divert
// create a diverter
// set up divert_to and divert_from directions depending on dir state
/obj/machinery/diverter/New()
..()
switch(dir)
if(NORTH)
divert_to = WEST // stuff will be moved to the west
divert_from = NORTH // if entering from the north
if(SOUTH)
divert_to = EAST
divert_from = NORTH
if(EAST)
divert_to = EAST
divert_from = SOUTH
if(WEST)
divert_to = WEST
divert_from = SOUTH
if(NORTHEAST)
divert_to = NORTH
divert_from = EAST
if(NORTHWEST)
divert_to = NORTH
divert_from = WEST
if(SOUTHEAST)
divert_to = SOUTH
divert_from = EAST
if(SOUTHWEST)
divert_to = SOUTH
divert_from = WEST
spawn(2)
// wait for map load then find the conveyor in this turf
conv = locate() in src.loc
if(conv) // divert_from dir must match possible conveyor movement
if(conv.basedir != divert_from && conv.basedir != turn(divert_from,180) )
qdel(src) // if no dir match, then delete self
set_divert()
update()
// update the icon state depending on whether the diverter is extended
/obj/machinery/diverter/proc/update()
icon_state = "diverter[deployed]"
// call to set the diversion vars of underlying conveyor
/obj/machinery/diverter/proc/set_divert()
if(conv)
if(deployed)
conv.divert = divert_to
conv.divdir = divert_from
else
conv.divert= 0
// *** TESTING click to toggle
/obj/machinery/diverter/Click()
toggle()
// toggle between arm deployed and not deployed, showing animation
//
/obj/machinery/diverter/proc/toggle()
if( stat & (NOPOWER|BROKEN))
return
if(operating)
return
use_power(50)
operating = 1
if(deployed)
flick("diverter10",src)
icon_state = "diverter0"
sleep(10)
deployed = 0
else
flick("diverter01",src)
icon_state = "diverter1"
sleep(10)
deployed = 1
operating = 0
update()
set_divert()
// don't allow movement into the 'backwards' direction if deployed
/obj/machinery/diverter/CanPass(atom/movable/O, var/turf/target)
var/direct = get_dir(O, target)
if(direct == divert_to) // prevent movement through body of diverter
return 0
if(!deployed)
return 1
return(direct != turn(divert_from,180))
// don't allow movement through the arm if deployed
/obj/machinery/diverter/CheckExit(atom/movable/O, var/turf/target)
var/direct = get_dir(O, target)
if(direct == turn(divert_to,180)) // prevent movement through body of diverter
return 0
if(!deployed)
return 1
return(direct != divert_from)
// 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/id = "" // must match conveyor IDs to control them
var/list/conveyors // the list of converyors that are controlled by this switch
anchored = 1
/obj/machinery/conveyor_switch/New()
..()
update()
spawn(5) // allow map load
conveyors = list()
for(var/obj/machinery/conveyor/C in machines)
if(C.id == id)
conveyors += C
mechanics = new(src)
mechanics.master = src
mechanics.addInput("trigger", "trigger")
/obj/machinery/conveyor_switch/proc/trigger(var/inp)
attack_hand(usr) //bit of a hack but hey.
return
// 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.setdir()
// attack with hand, switch position
/obj/machinery/conveyor_switch/attack_hand(mob/user)
if(position == 0)
if(last_pos < 0)
position = 1
last_pos = 0
else
position = -1
last_pos = 0
else
last_pos = position
position = 0
operated = 1
update()
// find any switches with same id as this one, and set their positions to match us
for(var/obj/machinery/conveyor_switch/S in machines)
if(S.id == src.id)
S.position = position
S.update()
if(mechanics) mechanics.fireOutgoing(mechanics.newSignal("switchTriggered"))
+69
View File
@@ -0,0 +1,69 @@
/obj/machinery/crusher
name = "Crusher Unit"
desc = "Breaks things down into metal/glass/waste"
density = 1
icon = 'icons/obj/scrap.dmi'
icon_state = "Crusher_1"
layer = MOB_LAYER + 1
anchored = 1.0
mats = 20
is_syndicate = 1
var/active = 0
/obj/machinery/crusher/Bumped(atom/AM)
var/tm_amt = 0
var/tg_amt = 0
var/tw_amt = 0
var/bblood = 0
if(istype(AM,/obj/item/scrap))
return
if(world.timeofday - AM.last_bumped <= 60)
return
if(ismob(AM))
var/mob/M = AM
for(var/obj/O in M.contents)
if(isobj(O))
tm_amt += O.m_amt
tg_amt += O.g_amt
tw_amt += O.w_amt
if(iscarbon(M))
tw_amt += 5000
bblood = 2
else if(issilicon(M))
tm_amt += 5000
tg_amt += 1000
qdel(O)
logTheThing("combat", M, null, "is ground up in a crusher at [log_loc(src)].")
M.gib()
else if(isobj(AM))
var/obj/B = AM
tm_amt += B.m_amt
tg_amt += B.g_amt
tw_amt += B.w_amt
for(var/obj/O in AM.contents)
if(isobj(O))
tm_amt += O.m_amt
tg_amt += O.g_amt
tw_amt += O.w_amt
qdel(O)
else
return
for(var/mob/M in oviewers())
if(M.client)
boutput(M, "<span style=\"color:red\">You hear a grinding sound!</span>")
var/obj/item/scrap/S = new(get_turf(src))
S.blood = bblood
S.set_components(tm_amt,tg_amt,tw_amt)
qdel(AM)
// step(S,2)
return
/obj/machinery/crusher/process()
..()
if(stat & (NOPOWER|BROKEN)) return
use_power(500)
@@ -0,0 +1,217 @@
// Disposal pipe construction
/obj/disposalconstruct
name = "disposal pipe segment"
desc = "A huge pipe segment used for constructing disposal systems."
icon = 'icons/obj/disposal.dmi'
icon_state = "conpipe-s"
anchored = 0
density = 1
pressure_resistance = 5*ONE_ATMOSPHERE
m_amt = 1850
level = 2
var/ptype = 0
// 0=straight, 1=bent, 2=junction-j1, 3=junction-j2, 4=junction-y, 5=trunk, 6 & 7=switching junction, 8 & 9=mob filter junction, 10 = loafer, 11 = mechanics controlled junction
var/dpdir = 0 // directions as disposalpipe
var/base_state = "pipe-s"
var/mail_tag = null //For pipes that use mail filtering
var/filter_type = null //For pipes that filter objects passing through.
// update iconstate and dpdir due to dir and type
proc/update()
var/flip = turn(dir, 180)
var/left = turn(dir, 90)
var/right = turn(dir, -90)
switch(ptype)
if(0)
base_state = "pipe-s"
dpdir = dir | flip
if(1)
base_state = "pipe-c"
dpdir = dir | right
if(2)
base_state = "pipe-j1"
dpdir = dir | right | flip
if(3)
base_state = "pipe-j2"
dpdir = dir | left | flip
if(4)
base_state = "pipe-y"
dpdir = dir | left | right
if(5)
base_state = "pipe-t"
dpdir = dir
if(6,8)
base_state = "pipe-sj1"
dpdir = dir
if(7,9)
base_state = "pipe-sj2"
dpdir = dir
if(10)
base_state = "pipe-loaf0"
dpdir = dir
if(11)
base_state = "pipe-mech"
dpdir = dir | left | flip
if(12)
base_state = "pipe-mechsense"
dpdir = dir | flip
icon_state = "con[base_state]"
if(invisibility) // if invisible, fade icon
icon -= rgb(0,0,0,128)
// hide called by levelupdate if turf intact status changes
// change visibility status and force update of icon
hide(var/intact)
invisibility = (intact && level==1) ? 101: 0 // hide if floor is intact
update()
// flip and rotate verbs
verb/rotate()
set name = "Rotate Pipe"
set src in view(1)
set category = "Local"
if(usr.stat)
return
if(anchored)
boutput(usr, "You must unfasten the pipe before rotating it.")
dir = turn(dir, -90)
update()
verb/flip()
set name = "Flip Pipe"
set src in view(1)
set category = "Local"
if(usr.stat)
return
if(anchored)
boutput(usr, "You must unfasten the pipe before flipping it.")
dir = turn(dir, 180)
if(ptype == 2)
ptype = 3
else if(ptype == 3)
ptype = 2
update()
// returns the type path of disposalpipe corresponding to this item dtype
proc/dpipetype()
switch(ptype)
if(0,1)
return /obj/disposalpipe/segment
if(2,3,4)
return /obj/disposalpipe/junction
if(5)
return /obj/disposalpipe/trunk
if(6,7)
return /obj/disposalpipe/switch_junction
if(8,9)
return /obj/disposalpipe/switch_junction/biofilter
if(10)
return /obj/disposalpipe/loafer
if(11)
return /obj/disposalpipe/mechanics_switch
if(12)
return /obj/disposalpipe/mechanics_sensor
return
// attackby item
// wrench: (un)anchor
// weldingtool: convert to real pipe
attackby(var/obj/item/I, var/mob/user)
var/turf/T = src.loc
if(T.intact)
boutput(user, "You can only attach the pipe if the floor plating is removed.")
return
var/obj/disposalpipe/CP = locate() in T
if(CP)
update()
var/pdir = CP.dpdir
if(istype(CP, /obj/disposalpipe/broken))
pdir = CP.dir
if(pdir & dpdir)
boutput(user, "There is already a pipe at that location.")
return
if(istype(I, /obj/item/wrench))
if(anchored)
anchored = 0
level = 2
density = 1
boutput(user, "You detach the pipe from the underfloor.")
else
anchored = 1
level = 1
density = 0
boutput(user, "You attach the pipe to the underfloor.")
playsound(src.loc, "sound/items/Ratchet.ogg", 100, 1)
else if(istype(I, /obj/item/weldingtool))
var/obj/item/weldingtool/W = I
if(W.welding)
if(W.get_fuel() > 2)
W.use_fuel(2)
playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
// check if anything changed over 2 seconds
var/turf/uloc = user.loc
var/atom/wloc = W.loc
var/turf/ploc = loc
boutput(user, "You begin welding [src] in place.")
sleep(20)
if(user.loc == uloc && wloc == W.loc)
// REALLY? YOU DON'T FUCKING CARE ABOUT THE LOCATION OF THE PIPE? GET FUCKED <CODER>
if (ploc != loc)
boutput(user, "<span style='color:red'>As you try to weld the pipe to a completely different floor than it was originally placed on it breaks!</span>")
ploc = loc
spawn(0)
robogibs(ploc)
//if (isrestrictedz(ploc.z))
//explosion_new(src, ploc, 3) // okay yes we don't need to explode people for this
qdel(src)
return
update()
var/pipetype = dpipetype()
var/obj/disposalpipe/P = new pipetype(src.loc)
P.base_icon_state = base_state
P.dir = dir
P.dpdir = dpdir
P.mail_tag = mail_tag
P.updateicon()
boutput(user, "You weld [P] in place.")
qdel(src)
else
boutput(user, "You must stay still while welding.")
return
else
boutput(user, "You need more welding fuel to complete this task.")
return
/obj/disposalconstruct/mechanics
name = "controlled pipe junction"
ptype = 11
base_state = "pipe-mech"
icon_state = "conpipe-mech"
/obj/disposalconstruct/mechanics_sensor
name = "sensor pipe"
ptype = 12
base_state = "pipe-mechsense"
icon_state = "pipe-mechsense"
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,537 @@
// 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
name = "disposal unit"
desc = "A pneumatic waste disposal unit."
icon = 'icons/obj/disposal.dmi'
icon_state = "disposal"
anchored = 1
density = 1
flags = NOSPLASH
var/datum/gas_mixture/air_contents // internal reservoir
var/mode = 1 // item mode 0=off 1=charging 2=charged
var/flush = 0 // true if flush handle is pulled
var/obj/disposalpipe/trunk/trunk = null // the attached pipe trunk
var/flushing = 0 // true if flushing in progress
var/icon_style = "disposal"
var/handle_state = null // this is the overlay added when the handle is in the normal position (for the small chutes, mainly this can be ignored otherwise)
var/image/handle_image = null
mats = 20 // whats the point of letting people build trunk pipes if they cant build new disposals?
power_usage = 100
// create a new disposal
// find the attached trunk (if present) and init gas resvr.
New()
..()
spawn(5)
if (src)
trunk = locate() in src.loc
if(!trunk)
mode = 0
flush = 0
else
trunk.linked = src // link the pipe trunk to self
initair()
update()
disposing()
if(air_contents)
pool(air_contents)
air_contents = null
..()
proc/initair()
air_contents = unpool(/datum/gas_mixture)
air_contents.volume = 255
air_contents.nitrogen = 16.5
air_contents.oxygen = 4.4
air_contents.temperature = 293.15
// attack by item places it in to disposal
attackby(var/obj/item/I, var/mob/user)
if(stat & BROKEN)
return
if (istype(I,/obj/item/electronics/scanner))
user.visible_message("<span style=\"color:red\"><B>[user] hits [src] with [I]!</B></span>")
return
if (istype(I,/obj/item/satchel/))
var/action = input(usr, "What do you want to do with the satchel?") in list("Empty it into the Chute","Place it in the Chute","Never Mind")
if (!action || action == "Never Mind") return
if (get_dist(src,user) > 1)
boutput(user, "<span style=\"color:red\">You need to be closer to the chute to do that.</span>")
return
if (action == "Empty it into the Chute")
var/obj/item/satchel/S = I
for(var/obj/item/O in S.contents) O.set_loc(src)
S.satchel_updateicon()
user.visible_message("<b>[user.name]</b> dumps out [S] into [src].")
return
if (issilicon(user))
boutput(user, "<span style=\"color:red\">You can't put that in the trash when it's attached to you!</span>")
return
var/obj/item/grab/G = I
if(istype(G)) // handle grabbed mob
if (ismob(G.affecting))
var/mob/GM = G.affecting
if (istype(src, /obj/machinery/disposal/mail) && !GM.canRideMailchutes())
boutput(user, "<span style=\"color:red\">That won't fit!</span>")
return
GM.set_loc(src)
user.visible_message("<span style=\"color:red\"><b>[user.name] stuffs [GM.name] into [src]!</b></span>")
qdel(G)
logTheThing("combat", user, GM, "places %target% into [src] at [log_loc(src)].")
actions.interrupt(G.affecting, INTERRUPT_MOVE)
actions.interrupt(user, INTERRUPT_ACT)
else
if (!user.drop_item())
return
I.set_loc(src)
boutput(user, "You place \the [I] into the [src].")
user.show_message("[user.name] places \the [I] into the [src].")
actions.interrupt(user, INTERRUPT_ACT)
update()
// mouse drop another mob or self
//
MouseDrop_T(mob/target, mob/user)
//jesus fucking christ
if (!istype(target) || target.buckled || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || user.paralysis || user.stunned || user.weakened || istype(user, /mob/living/silicon/ai) || istype(target, /mob/living/silicon/ai))
return
if (istype(src, /obj/machinery/disposal/mail) && istype(target, /mob/living))
//Is this mob allowed to ride mailchutes?
if (!target.canRideMailchutes())
boutput(user, "<span style=\"color:red\">That won't fit!</span>")
return
var/msg
var/turf/Q = target.loc
sleep (5)
if(target == user && !user.stat) // if drop self, then climbed in
// must be awake
msg = "[user.name] climbs into the [src]."
boutput(user, "You climb into the [src].")
else if(target != user && !user.restrained() && Q == target.loc)
msg = "[user.name] stuffs [target.name] into the [src]!"
boutput(user, "You stuff [target.name] into the [src]!")
logTheThing("combat", user, target, "places %target% into [src] at [log_loc(src)].")
else
return
actions.interrupt(target, INTERRUPT_MOVE)
actions.interrupt(user, INTERRUPT_ACT)
target.set_loc(src)
if (msg)
src.visible_message(msg)
update()
return
hitby(MO as mob|obj)
// This feature interferes with mail delivery, i.e. objects bouncing back into the chute.
// Leaves people wondering where the stuff is, assuming they received a PDA alert at all.
if (istype(src, /obj/machinery/disposal/mail))
return ..()
if(istype(MO, /obj/item))
var/obj/item/I = MO
if(prob(20)) //It might land!
I.set_loc(get_turf(src))
if(prob(30)) //It landed cleanly!
I.set_loc(src)
src.visible_message("<span style=\"color:red\">\The [I] lands cleanly in \the [src]!</span>")
else //Aaaa the tension!
src.visible_message("<span style=\"color:red\">\The [I] teeters on the edge of \the [src]!</span>")
var/delay = rand(5, 15)
spawn(0)
var/in_x = I.pixel_x
for(var/d = 0; d < delay; d++)
if(I) I.pixel_x = in_x + rand(-1, 1)
sleep(1)
if(I) I.pixel_x = in_x
sleep(delay)
if(I && I.loc == src.loc)
if(prob(40)) //It goes in!
src.visible_message("<span style=\"color:red\">\The [I] slips into \the [src]!</span>")
I.set_loc(src)
else
src.visible_message("<span style=\"color:red\">\The [I] slips off of the edge of \the [src]!</span>")
else if (ishuman(MO))
var/mob/living/carbon/human/H = MO
H.set_loc(get_turf(src))
if(prob(30))
H.visible_message("<span style=\"color:red\"><B>[H] falls into the disposal outlet!</B></span>")
logTheThing("combat", H, null, "is thrown into a [src.name] at [log_loc(src)].")
H.set_loc(src)
if(prob(20))
src.visible_message("<span style=\"color:red\"><B><I>...accidentally hitting the handle!</I></B></span>")
H.show_text("<B><I>...accidentally hitting the handle!</I></B>", "red")
flush = 1
update()
else
return ..()
// can breath normally in the disposal
alter_health()
return get_turf(src)
// attempt to move while inside
relaymove(mob/user as mob)
if(user.stat || src.flushing)
return
src.go_out(user)
return
// leave the disposal
proc/go_out(mob/user)
user.set_loc(src.loc)
user.weakened = max(user.weakened, 2)
update()
return
// ai as human but can't flush
attack_ai(mob/user as mob)
interact(user, 1)
// human interact with machine
attack_hand(mob/user as mob)
interact(user, 0)
proc/interact(mob/user, var/ai=0)
src.add_fingerprint(user)
if(stat & BROKEN)
user.machine = null
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>"
if (!air_contents)
initair()
var/per = 100* air_contents.return_pressure() / (2*ONE_ATMOSPHERE)
dat += "Pressure: [round(per, 1)]%<BR></body>"
user.machine = src
user << browse(dat, "window=disposal;size=360x170")
onclose(user, "disposal")
// handle machine interaction
Topic(href, href_list)
..()
src.add_fingerprint(usr)
if(stat & BROKEN)
DEBUG("[src] is broken")
return
if(usr.stat || usr.restrained() || src.flushing)
DEBUG("[src] is flushing/usr.stat returned with someting/usr is restrained")
return
if (in_range(src, usr) && isturf(src.loc))
DEBUG("in range of [src] and it is on a turf")
usr.machine = src
if(href_list["close"])
DEBUG("closed [src]")
usr.machine = null
usr << browse(null, "window=disposal")
return
if(href_list["pump"])
if(text2num(href_list["pump"]))
DEBUG("[src] pump engaged")
power_usage = 600
mode = 1
else
DEBUG("[src] pump disengaged")
power_usage = 100
mode = 0
update()
if(href_list["handle"])
DEBUG("[src] handle")
flush = text2num(href_list["handle"])
update()
if(href_list["eject"])
DEBUG("[src] eject")
eject()
else
if (!isturf(src.loc))
DEBUG("[src]'s loc is not a turf: [src.loc]")
if (!in_range(src, usr))
DEBUG("[src] and [usr] are too far apart: [src] [log_loc(src)], [usr] [log_loc(usr)]")
usr << browse(null, "window=disposal")
usr.machine = null
return
return
// eject the contents of the disposal unit
proc/eject()
for(var/atom/movable/AM in src)
AM.set_loc(src.loc)
AM.pipe_eject(0)
update()
// update the icon & overlays to reflect mode & status
proc/update()
if (stat & BROKEN)
icon_state = "disposal-broken"
ClearAllOverlays()
mode = 0
flush = 0
return
// flush handle
if (flush)
if (!src.handle_image)
src.handle_image = image(src.icon, "[icon_style]-over-handle")
else if (!src.handle_state)
src.handle_image.icon_state = "[icon_style]-over-handle"
UpdateOverlays(src.handle_image, "handle")
else
if (src.handle_state)
if (!src.handle_image)
src.handle_image = image(src.icon, src.handle_state)
else
src.handle_image.icon_state = src.handle_state
UpdateOverlays(src.handle_image, "handle")
else
UpdateOverlays(null, "handle", 0, 1)
// only handle is shown if no power
if (stat & NOPOWER)
return
// check for items in disposal - occupied light
if (contents.len > 0)
var/image/I = GetOverlayImage("content_light")
if (!I)
I = image(src.icon, "dispover-full")
UpdateOverlays(I, "content_light")
else
UpdateOverlays(null, "content_light", 0, 1)
// charging and ready light
var/image/I = GetOverlayImage("status")
if (!I)
I = image(src.icon, "dispover-charge")
switch (mode)
if (1)
I.icon_state = "dispover-charge"
if (2)
I.icon_state = "dispover-ready"
else
I = null
UpdateOverlays(I, "status", 0, 1)
/*
if(mode == 1)
overlays += image('icons/obj/disposal.dmi', "dispover-charge")
else if(mode == 2)
overlays += image('icons/obj/disposal.dmi', "dispover-ready")
*/
// timed process
// charge the gas reservoir and perform flush if ready
process()
if(stat & BROKEN) // nothing can happen if broken
return
..()
src.updateDialog()
if(flush && air_contents.return_pressure() >= 2*ONE_ATMOSPHERE) // flush can happen even without power
spawn(0) //Quit holding up the process you fucker
flush()
if(stat & NOPOWER) // won't charge if no power
return
if (!loc) 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()
if (!air_contents)
air_contents = unpool(/datum/gas_mixture)
var/pressure_delta = (ONE_ATMOSPHERE*2.1) - 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)
// if full enough, switch to ready mode
if(air_contents.return_pressure() >= 2*ONE_ATMOSPHERE)
mode = 2
power_usage = 100
update()
return
// perform a flush
proc/flush()
flushing = 1
flick("[icon_style]-flush", src)
var/obj/disposalholder/H = new() // virtual holder object which actually
// travels through the pipes.
H.init(src) // copy the contents of disposer to holder
air_contents.zero()
sleep(10)
playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0)
sleep(5) // wait for animation to finish
H.start(src) // start the holder processing movement
flushing = 0
// now reset disposal state
flush = 0
if(mode == 2) // if was ready,
mode = 1 // switch to charging
power_usage = 600
update()
return
// called when area power changes
power_change()
..() // do default setting/reset of stat NOPOWER bit
update() // update icon
return
// called when holder is expelled from a disposal
// should usually only occur if the pipe network is modified
proc/expel(var/obj/disposalholder/H)
var/turf/target
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
for(var/atom/movable/AM in H)
target = get_offset_target_turf(src.loc, rand(5)-rand(5), rand(5)-rand(5))
AM.set_loc(src.loc)
AM.pipe_eject(0)
spawn(1)
if(AM)
AM.throw_at(target, 5, 1)
H.vent_gas(loc)
qdel(H)
suicide(var/mob/user as mob)
if(src.mode != 2 || !hasvar(user,"organHolder")) return 0
user.visible_message("<span style=\"color:red\"><b>[user] sticks \his head into the [src.name] and pulls the flush!</b></span>")
var/obj/head = user:organHolder.drop_organ("head")
head.set_loc(src)
src.flush()
playsound(src.loc, 'sound/effects/bloody_stab.ogg', 50, 1)
new /obj/decal/cleanable/blood(user.loc)
user.updatehealth()
spawn(100)
if (user)
user.suiciding = 0
return 1
/obj/machinery/disposal/small
icon = 'icons/obj/disposal_small.dmi'
handle_state = "dispover-handle"
density = 0
north
dir = NORTH
east
dir = EAST
south
dir = SOUTH
west
dir = WEST
/obj/machinery/disposal/brig
name = "brig chute"
icon_state = "brigchute"
desc = "A pneumatic delivery chute for sending things directly to the brig."
icon_style = "brig"
/obj/machinery/disposal/morgue
name = "morgue chute"
icon_state = "morguechute"
desc = "A pneumatic delivery chute for sending things directly to the morgue."
icon_style = "morgue"
/obj/machinery/disposal/alert_a_chump
var/message = null
var/mailgroup = null
var/net_id = null
var/frequency = 1149
var/datum/radio_frequency/radio_connection
New()
..()
spawn(8)
if(radio_controller)
radio_connection = radio_controller.add_object(src, "[frequency]")
if(!src.net_id)
src.net_id = generate_net_id(src)
expel(var/obj/disposalholder/H)
..(H)
if (message && mailgroup && radio_connection)
var/datum/signal/newsignal = get_free_signal()
newsignal.source = src
newsignal.transmission_method = TRANSMISSION_RADIO
newsignal.data["command"] = "text_message"
newsignal.data["sender_name"] = "CHUTE-MAILBOT"
newsignal.data["message"] = "[message]"
newsignal.data["address_1"] = "00000000"
newsignal.data["group"] = mailgroup
newsignal.data["sender"] = src.net_id
radio_connection.post_signal(src, newsignal)
File diff suppressed because it is too large Load Diff
+294
View File
@@ -0,0 +1,294 @@
// The scrap item
// a single object type represents all combinations of size and composition of scrap
//
/obj/item/scrap
name = "scrap"
icon = 'icons/obj/scrap.dmi'
icon_state = "1metal0"
item_state = "scrap-metal"
desc = "A piece of scrap"
var/classtext = ""
throwforce = 10.0
m_amt = 1
g_amt = 1
w_amt = 1
var/size = 1 // 1=piece, 2= few pieces, 3=small pile, 4=large pile
var/blood = 0 // 0=none, 1=blood-stained, 2=bloody
throw_speed = 1
throw_range = 4
w_class = 1
flags = FPRINT | TABLEPASS | CONDUCT
#define MAX_SCRAP 15000 // maximum content amount of a scrap pile
/obj/item/scrap/New()
src.verbs -= /atom/movable/verb/pull
..()
update()
// return a copy
/obj/item/scrap/proc/copy()
var/obj/item/scrap/ret = new()
ret.set_components(m_amt, g_amt, w_amt)
return ret
// set the metal, glass and waste content
/obj/item/scrap/proc/set_components(var/m, var/g, var/w)
m_amt = m
g_amt = g
w_amt = w
update()
// returns the total amount of scrap in this pile
/obj/item/scrap/proc/total()
var/V = (m_amt + g_amt + w_amt)
return V
// sets the size, appearance, and description of the scrap depending on component amounts
/obj/item/scrap/proc/update()
var/total = total()
// determine size of pile
if(total<=400)
size = 1
else if(total<=1600)
size = 2
else
size = 3
w_class = size
var/sizetext = ""
switch(size)
if(1)
sizetext = "A piece of"
if(2)
sizetext = "A few pieces of"
if(3)
sizetext = "A pile of"
// determine bloodiness
var/bloodtext = ""
switch(blood)
if(0)
bloodtext = ""
if(1)
bloodtext = "blood-stained "
if(2)
bloodtext = "bloody "
// find mixture and composition
var/class = 0 // 0 = mixed, 1=mostly. 2=pure
var/major = "waste" // the major component type
var/max = 0
if(m_amt > max)
max = m_amt
else if(g_amt > max)
max = g_amt
else if(w_amt > max)
max = w_amt
if(max == total)
class = 2 // pure
else if(max/total > 0.6)
class = 1 // mostly
else
class = 0 // mixed
if(class>0)
var/remain = total - max
if(m_amt > remain)
major = "metal"
else if(g_amt > remain)
major = "glass"
else
major = "waste"
if(class == 1)
desc = "[sizetext] mostly [major] [bloodtext]scrap."
classtext = "mostly [major] [bloodtext]"
else
desc = "[sizetext] [bloodtext][major] scrap."
classtext = "[bloodtext][major] "
icon_state = "[size][major][blood]"
else
desc = "[sizetext] [bloodtext]mixed scrap."
classtext = "[bloodtext]mixed"
icon_state = "[size]mixed[blood]"
if(size==0)
pixel_x = rand(-5,5)
pixel_y = rand(-5,5)
else
pixel_x = 0
pixel_y = 0
// clear or set conduction flag depending on whether scrap is mostly metal
if(major=="metal")
flags |= CONDUCT
else
flags &= ~CONDUCT
item_state = "scrap-[major]"
// add a scrap item to this one
// if the resulting pile is too big, transfer only what will fit
// otherwise add them and deleted the added pile
/obj/item/scrap/proc/add_scrap(var/obj/item/scrap/other, var/limit = MAX_SCRAP)
var/total = total()
var/other_total = other.total()
if(total <= 0)
qdel(src)
return
if(other_total <= 0)
qdel(other)
return
if( (total + other_total) <= limit)
m_amt += other.m_amt
g_amt += other.g_amt
w_amt += other.w_amt
blood = (total*blood + other_total*other.blood) / (total + other_total)
qdel(other)
else
var/space = limit - total
var/m = round(other.m_amt/other_total*space, 1)
var/g = round(other.g_amt/other_total*space, 1)
var/w = round(other.w_amt/other_total*space, 1)
m_amt += m
g_amt += g
w_amt += w
other.m_amt -= m
other.g_amt -= g
other.w_amt -= w
var/other_trans = m + g + w
other.update()
blood = (total*blood + other_trans*other.blood) / (total + other_trans)
blood = round(blood,1)
src.update()
// limit this pile to maximum size
// return any remainder as a new scrap item (or null if none)
// note return item is not necessarily smaller than max size
/obj/item/scrap/proc/remainder(var/limit = MAX_SCRAP)
var/total = total()
if(total > limit)
var/m = round( m_amt/total * limit, 1)
var/g = round( g_amt/total * limit, 1)
var/w = round( w_amt/total * limit, 1)
var/obj/item/scrap/S = new()
S.set_components(m_amt - m,g_amt - g,w_amt - w)
src.set_components(m,g,w)
return S
return null
// if other pile of scrap tries to enter the same turf, then add that pile to this one
/obj/item/scrap/CanPass(var/obj/item/scrap/O)
if(istype(O))
src.add_scrap(O)
// if(O)
// return 0 // O still exists if not all could be transfered, so block it
return 1
/obj/item/scrap/proc/to_text()
return "[m_amt],[g_amt],[w_amt] ([total()])"
// attack with hand removes a single piece from a pile <-- This makes it uselessssss
/*/obj/item/scrap/attack_hand(mob/user)
add_fingerprint(user)
if(src.is_single_piece())
return ..(user)
var/obj/item/scrap/S = src.get_single_piece()
S.attack_hand(user)
return
*/
/obj/item/scrap/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/scrap))
var/obj/item/scrap/S = I
if( (S.total()+src.total() ) > MAX_SCRAP )
boutput(user, "The pile is full.")
return
if(ismob(src.loc)) // can't combine scrap in hand
return
src.add_scrap(S)
// when dropped, try to make a pile if scrap is already there
/obj/item/scrap/dropped()
spawn(2) // delay to allow drop postprocessing (since src may be destroyed)
for(var/obj/item/scrap/S in oview(0,src)) // excludes src itself
S.add_scrap(src)
// return true if this is a single piece of scrap
// must be total<=400 and of single composition
/obj/item/scrap/proc/is_single_piece()
if(total() > 400)
return 0
var/empty = (m_amt == 0) + (g_amt == 0) + (w_amt == 0)
return (empty==2) // must be 2 components with zero amount
// get a single piece of scrap from a pile
/obj/item/scrap/proc/get_single_piece()
var/obj/item/scrap/S = new()
var/cmp = pick(m_amt;1 , g_amt;2, w_amt;3)
var/amount = 400
switch(cmp)
if(1)
if(m_amt < amount)
amount = m_amt
S.set_components(amount, 0, 0)
src.set_components(m_amt - amount, g_amt, w_amt)
if(2)
if(g_amt < amount)
amount = g_amt
S.set_components(0, amount, 0)
src.set_components(m_amt, g_amt - amount, w_amt)
if(3)
if(w_amt < amount)
amount = w_amt
S.set_components(0, 0, amount)
src.set_components(m_amt, g_amt, w_amt - amount)
return S