From 47b32122d4ef7ca7c5f28678c2a8b968d6029f15 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Thu, 7 Aug 2014 19:31:17 -0400 Subject: [PATCH] Updates disposal bin pressurization Also tweaks flasher power use. --- code/ATMOSPHERICS/datum_pipeline.dm | 2 - code/game/machinery/flasher.dm | 2 +- code/modules/recycling/disposal.dm | 865 ++++++++++++++-------------- 3 files changed, 434 insertions(+), 435 deletions(-) diff --git a/code/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm index 4ce388b844..ca06277551 100644 --- a/code/ATMOSPHERICS/datum_pipeline.dm +++ b/code/ATMOSPHERICS/datum_pipeline.dm @@ -202,8 +202,6 @@ datum/pipeline //surface must be the surface area in m^2 proc/radiate_heat_to_space(surface, thermal_conductivity) - var/total_heat_capacity = air.heat_capacity() - //if the h/e pipes radiate less than the AVERAGE_SOLAR_RADIATION, then they will heat up, otherwise they will cool down. It turns out the critical temperature is -26 C var/heat_gain = surface*(AVERAGE_SOLAR_RADIATION - STEFAN_BOLTZMANN_CONSTANT*thermal_conductivity*(air.temperature - COSMIC_RADIATION_TEMPERATURE) ** 4) diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index eff51fc697..88c72ec198 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -64,7 +64,7 @@ playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1) flick("[base_state]_flash", src) src.last_flash = world.time - use_power(1000) + use_power(1500) for (var/mob/O in viewers(src, null)) if (get_dist(src, O) > src.range) diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 0280599d5e..e6fe39f903 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -5,7 +5,9 @@ // Automatically recharges air (unless off), will flush when ready if pre-set // Can hold items and human size things, no other draggables // Toilets are a type of disposal bin for small objects only and work on magic. By magic, I mean torque rotation -#define SEND_PRESSURE 0.05*ONE_ATMOSPHERE +#define SEND_PRESSURE 700 //kPa. 7 bar - Based on existing pneumatic conveyor pressures. +#define PRESSURE_TANK_VOLUME 70 //L - a 0.3 m diameter * 1 m long cylindrical tank. Happens to be the same volume as the regular oxygen tanks, so seems appropriate. +#define PUMP_MAX_FLOW_RATE 50 //L/s - 2 m/s using a 15 cm by 15 cm inlet /obj/machinery/disposal name = "disposal unit" @@ -22,460 +24,459 @@ var/flush_every_ticks = 30 //Every 30 ticks it will look whether it is ready to flush var/flush_count = 0 //this var adds 1 once per tick. When it reaches flush_every_ticks it resets and tries to flush. var/last_sound = 0 - active_power_usage = 600 + active_power_usage = 1500 //the pneumatic pump power. 2 HP ~ 1500W idle_power_usage = 100 - // create a new disposal - // find the attached trunk (if present) and init gas resvr. - New() - ..() - spawn(5) - trunk = locate() in src.loc - if(!trunk) - mode = 0 - flush = 0 - else - trunk.linked = src // link the pipe trunk to self - - air_contents = new/datum/gas_mixture() - //gas.volume = 1.05 * CELLSTANDARD - update() - - - // attack by item places it in to disposal - attackby(var/obj/item/I, var/mob/user) - if(stat & BROKEN || !I || !user) - return - - if(isrobot(user) && !istype(I, /obj/item/weapon/storage/bag/trash)) - return - src.add_fingerprint(user) - if(mode<=0) // It's off - if(istype(I, /obj/item/weapon/screwdriver)) - if(contents.len > 0) - user << "Eject the items first!" - return - if(mode==0) // It's off but still not unscrewed - mode=-1 // Set it to doubleoff l0l - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - user << "You remove the screws around the power connection." - return - else if(mode==-1) - mode=0 - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - user << "You attach the screws around the power connection." - return - else if(istype(I,/obj/item/weapon/weldingtool) && mode==-1) - if(contents.len > 0) - user << "Eject the items first!" - return - var/obj/item/weapon/weldingtool/W = I - if(W.remove_fuel(0,user)) - playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1) - user << "You start slicing the floorweld off the disposal unit." - - if(do_after(user,20)) - if(!src || !W.isOn()) return - user << "You sliced the floorweld off the disposal unit." - var/obj/structure/disposalconstruct/C = new (src.loc) - src.transfer_fingerprints_to(C) - C.ptype = 6 // 6 = disposal unit - C.anchored = 1 - C.density = 1 - C.update() - del(src) - return - else - user << "You need more welding fuel to complete this task." - return - - if(istype(I, /obj/item/weapon/melee/energy/blade)) - user << "You can't place that item inside the disposal unit." - return - - if(istype(I, /obj/item/weapon/storage/bag/trash)) - var/obj/item/weapon/storage/bag/trash/T = I - user << "\blue You empty the bag." - for(var/obj/item/O in T.contents) - T.remove_from_storage(O,src) - T.update_icon() - update() - return - - var/obj/item/weapon/grab/G = I - if(istype(G)) // handle grabbed mob - if(ismob(G.affecting)) - var/mob/GM = G.affecting - for (var/mob/V in viewers(usr)) - V.show_message("[usr] starts putting [GM.name] into the disposal.", 3) - if(do_after(usr, 20)) - if (GM.client) - GM.client.perspective = EYE_PERSPECTIVE - GM.client.eye = src - GM.loc = src - for (var/mob/C in viewers(src)) - C.show_message("\red [GM.name] has been placed in the [src] by [user].", 3) - del(G) - usr.attack_log += text("\[[time_stamp()]\] Has placed [GM.name] ([GM.ckey]) in disposals.") - GM.attack_log += text("\[[time_stamp()]\] Has been placed in disposals by [usr.name] ([usr.ckey])") - msg_admin_attack("[usr] ([usr.ckey]) placed [GM] ([GM.ckey]) in a disposals unit. (JMP)") - return - - if(!I) return - - user.drop_item() - if(I) - I.loc = src - - user << "You place \the [I] into the [src]." - for(var/mob/M in viewers(src)) - if(M == user) - continue - M.show_message("[user.name] places \the [I] into the [src].", 3) - - update() - - // mouse drop another mob or self - // - MouseDrop_T(mob/target, mob/user) - if (!istype(target) || target.buckled || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || istype(user, /mob/living/silicon/ai)) - return - if(isanimal(user) && target != user) return //animals cannot put mobs other than themselves into disposal - src.add_fingerprint(user) - var/target_loc = target.loc - var/msg - for (var/mob/V in viewers(usr)) - if(target == user && !user.stat && !user.weakened && !user.stunned && !user.paralysis) - V.show_message("[usr] starts climbing into the disposal.", 3) - if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis) - if(target.anchored) return - V.show_message("[usr] starts stuffing [target.name] into the disposal.", 3) - if(!do_after(usr, 20)) - return - if(target_loc != target.loc) - return - if(target == user && !user.stat && !user.weakened && !user.stunned && !user.paralysis) // if drop self, then climbed in - // must be awake, not stunned or whatever - msg = "[user.name] climbs into the [src]." - user << "You climb into the [src]." - else if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis) - msg = "[user.name] stuffs [target.name] into the [src]!" - user << "You stuff [target.name] into the [src]!" - - user.attack_log += text("\[[time_stamp()]\] Has placed [target.name] ([target.ckey]) in disposals.") - target.attack_log += text("\[[time_stamp()]\] Has been placed in disposals by [user.name] ([user.ckey])") - msg_admin_attack("[user] ([user.ckey]) placed [target] ([target.ckey]) in a disposals unit. (JMP)") - else - return - if (target.client) - target.client.perspective = EYE_PERSPECTIVE - target.client.eye = src - target.loc = src - - for (var/mob/C in viewers(src)) - if(C == user) - continue - C.show_message(msg, 3) - - update() - 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) - - if (user.client) - user.client.eye = user.client.mob - user.client.perspective = MOB_PERSPECTIVE - user.loc = src.loc - update() - return - - - // monkeys can only pull the flush lever - attack_paw(mob/user as mob) - if(stat & BROKEN) - return - - flush = !flush - 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) - if(user && user.loc == src) - usr << "\red You cannot reach the controls from inside." - return - /* - if(mode==-1) - usr << "\red The disposal units power is disabled." - return - */ - interact(user, 0) - - // user interaction - interact(mob/user, var/ai=0) - - src.add_fingerprint(user) - if(stat & BROKEN) - user.unset_machine() - return - - var/dat = "Waste Disposal UnitWaste Disposal Unit
" - - if(!ai) // AI can't pull flush handle - if(flush) - dat += "Disposal handle: Disengage Engaged" - else - dat += "Disposal handle: Disengaged Engage" - - dat += "

Eject contents
" - - if(mode <= 0) - dat += "Pump: Off On
" - else if(mode == 1) - dat += "Pump: Off On (pressurizing)
" - else - dat += "Pump: Off On (idle)
" - - var/per = 100* air_contents.return_pressure() / (SEND_PRESSURE) - - dat += "Pressure: [round(per, 1)]%
" - - - user.set_machine(src) - user << browse(dat, "window=disposal;size=360x170") - onclose(user, "disposal") - - // handle machine interaction - - Topic(href, href_list) - if(usr.loc == src) - usr << "\red You cannot reach the controls from inside." - return - - if(mode==-1 && !href_list["eject"]) // only allow ejecting if mode is -1 - usr << "\red The disposal units power is disabled." - return - ..() - src.add_fingerprint(usr) - if(stat & BROKEN) - return - if(usr.stat || usr.restrained() || src.flushing) - return - - if (in_range(src, usr) && istype(src.loc, /turf)) - usr.set_machine(src) - - if(href_list["close"]) - usr.unset_machine() - usr << browse(null, "window=disposal") - return - - if(href_list["pump"]) - if(text2num(href_list["pump"])) - mode = 1 - else - mode = 0 - update() - - if(href_list["handle"]) - flush = text2num(href_list["handle"]) - update() - - if(href_list["eject"]) - eject() - else - usr << browse(null, "window=disposal") - usr.unset_machine() - return - return - - // eject the contents of the disposal unit - proc/eject() - for(var/atom/movable/AM in src) - AM.loc = src.loc - AM.pipe_eject(0) - update() - - // update the icon & overlays to reflect mode & status - proc/update() - overlays.Cut() - if(stat & BROKEN) - icon_state = "disposal-broken" +// create a new disposal +// find the attached trunk (if present) and init gas resvr. +/obj/machinery/disposal/New() + ..() + spawn(5) + trunk = locate() in src.loc + if(!trunk) mode = 0 flush = 0 - return + else + trunk.linked = src // link the pipe trunk to self - // flush handle - if(flush) - overlays += image('icons/obj/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) - overlays += image('icons/obj/pipes/disposal.dmi', "dispover-full") - - // charging and ready light - if(mode == 1) - overlays += image('icons/obj/pipes/disposal.dmi', "dispover-charge") - else if(mode == 2) - overlays += image('icons/obj/pipes/disposal.dmi', "dispover-ready") - - // timed process - // charge the gas reservoir and perform flush if ready - process() - use_power = 0 - if(stat & BROKEN) // nothing can happen if broken - return - - if(!air_contents) // Potentially causes a runtime otherwise (if this is really shitty, blame pete //Donkie) - return - - flush_count++ - if( flush_count >= flush_every_ticks ) - if( contents.len ) - if(mode == 2) - spawn(0) - feedback_inc("disposal_auto_flush",1) - flush() - flush_count = 0 - - src.updateDialog() - - if(flush && air_contents.return_pressure() >= SEND_PRESSURE ) // flush can happen even without power - flush() - - if(stat & NOPOWER) // won't charge if no power - return - - use_power = 1 - - if(mode != 1) // if off or ready, no need to charge - return - - // otherwise charge - use_power = 2 - - 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_contents = new/datum/gas_mixture() + air_contents.volume = PRESSURE_TANK_VOLUME + update() - // if full enough, switch to ready mode - if(air_contents.return_pressure() >= SEND_PRESSURE) - mode = 2 - update() +// attack by item places it in to disposal +/obj/machinery/disposal/attackby(var/obj/item/I, var/mob/user) + if(stat & BROKEN || !I || !user) return - // perform a flush - proc/flush() + if(isrobot(user) && !istype(I, /obj/item/weapon/storage/bag/trash)) + return + src.add_fingerprint(user) + if(mode<=0) // It's off + if(istype(I, /obj/item/weapon/screwdriver)) + if(contents.len > 0) + user << "Eject the items first!" + return + if(mode==0) // It's off but still not unscrewed + mode=-1 // Set it to doubleoff l0l + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + user << "You remove the screws around the power connection." + return + else if(mode==-1) + mode=0 + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + user << "You attach the screws around the power connection." + return + else if(istype(I,/obj/item/weapon/weldingtool) && mode==-1) + if(contents.len > 0) + user << "Eject the items first!" + return + var/obj/item/weapon/weldingtool/W = I + if(W.remove_fuel(0,user)) + playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1) + user << "You start slicing the floorweld off the disposal unit." - flushing = 1 - flick("[icon_state]-flush", src) + if(do_after(user,20)) + if(!src || !W.isOn()) return + user << "You sliced the floorweld off the disposal unit." + var/obj/structure/disposalconstruct/C = new (src.loc) + src.transfer_fingerprints_to(C) + C.ptype = 6 // 6 = disposal unit + C.anchored = 1 + C.density = 1 + C.update() + del(src) + return + else + user << "You need more welding fuel to complete this task." + return - var/wrapcheck = 0 - var/obj/structure/disposalholder/H = new() // virtual holder object which actually - // travels through the pipes. - //Hacky test to get drones to mail themselves through disposals. - for(var/mob/living/silicon/robot/drone/D in src) - wrapcheck = 1 + if(istype(I, /obj/item/weapon/melee/energy/blade)) + user << "You can't place that item inside the disposal unit." + return - for(var/obj/item/smallDelivery/O in src) - wrapcheck = 1 - - if(wrapcheck == 1) - H.tomail = 1 - - - air_contents = new() // new empty gas resv. - - sleep(10) - if(last_sound < world.time + 1) - playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0) - last_sound = world.time - sleep(5) // wait for animation to finish - - - H.init(src) // copy the contents of disposer to holder - - H.start(src) // start the holder processing movement - flushing = 0 - // now reset disposal state - flush = 0 - if(mode == 2) // if was ready, - mode = 1 // switch to charging + if(istype(I, /obj/item/weapon/storage/bag/trash)) + var/obj/item/weapon/storage/bag/trash/T = I + user << "\blue You empty the bag." + for(var/obj/item/O in T.contents) + T.remove_from_storage(O,src) + T.update_icon() update() return - - // called when area power changes - power_change() - ..() // do default setting/reset of stat NOPOWER bit - update() // update icon + var/obj/item/weapon/grab/G = I + if(istype(G)) // handle grabbed mob + if(ismob(G.affecting)) + var/mob/GM = G.affecting + for (var/mob/V in viewers(usr)) + V.show_message("[usr] starts putting [GM.name] into the disposal.", 3) + if(do_after(usr, 20)) + if (GM.client) + GM.client.perspective = EYE_PERSPECTIVE + GM.client.eye = src + GM.loc = src + for (var/mob/C in viewers(src)) + C.show_message("\red [GM.name] has been placed in the [src] by [user].", 3) + del(G) + usr.attack_log += text("\[[time_stamp()]\] Has placed [GM.name] ([GM.ckey]) in disposals.") + GM.attack_log += text("\[[time_stamp()]\] Has been placed in disposals by [usr.name] ([usr.ckey])") + msg_admin_attack("[usr] ([usr.ckey]) placed [GM] ([GM.ckey]) in a disposals unit. (JMP)") return + if(!I) return - // called when holder is expelled from a disposal - // should usually only occur if the pipe network is modified - proc/expel(var/obj/structure/disposalholder/H) + user.drop_item() + if(I) + I.loc = 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)) + user << "You place \the [I] into the [src]." + for(var/mob/M in viewers(src)) + if(M == user) + continue + M.show_message("[user.name] places \the [I] into the [src].", 3) - AM.loc = src.loc - AM.pipe_eject(0) - if(!istype(AM,/mob/living/silicon/robot/drone)) //Poor drones kept smashing windows and taking system damage being fired out of disposals. ~Z - spawn(1) - if(AM) - AM.throw_at(target, 5, 1) + update() - H.vent_gas(loc) - del(H) +// mouse drop another mob or self +// +/obj/machinery/disposal/MouseDrop_T(mob/target, mob/user) + if (!istype(target) || target.buckled || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || istype(user, /mob/living/silicon/ai)) + return + if(isanimal(user) && target != user) return //animals cannot put mobs other than themselves into disposal + src.add_fingerprint(user) + var/target_loc = target.loc + var/msg + for (var/mob/V in viewers(usr)) + if(target == user && !user.stat && !user.weakened && !user.stunned && !user.paralysis) + V.show_message("[usr] starts climbing into the disposal.", 3) + if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis) + if(target.anchored) return + V.show_message("[usr] starts stuffing [target.name] into the disposal.", 3) + if(!do_after(usr, 20)) + return + if(target_loc != target.loc) + return + if(target == user && !user.stat && !user.weakened && !user.stunned && !user.paralysis) // if drop self, then climbed in + // must be awake, not stunned or whatever + msg = "[user.name] climbs into the [src]." + user << "You climb into the [src]." + else if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis) + msg = "[user.name] stuffs [target.name] into the [src]!" + user << "You stuff [target.name] into the [src]!" - CanPass(atom/movable/mover, turf/target, height=0, air_group=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 - for(var/mob/M in viewers(src)) - M.show_message("\the [I] lands in \the [src].", 3) - else - for(var/mob/M in viewers(src)) - M.show_message("\the [I] bounces off of \the [src]'s rim!.", 3) - return 0 + user.attack_log += text("\[[time_stamp()]\] Has placed [target.name] ([target.ckey]) in disposals.") + target.attack_log += text("\[[time_stamp()]\] Has been placed in disposals by [user.name] ([user.ckey])") + msg_admin_attack("[user] ([user.ckey]) placed [target] ([target.ckey]) in a disposals unit. (JMP)") + else + return + if (target.client) + target.client.perspective = EYE_PERSPECTIVE + target.client.eye = src + target.loc = src + + for (var/mob/C in viewers(src)) + if(C == user) + continue + C.show_message(msg, 3) + + update() + return + +// can breath normally in the disposal +/obj/machinery/disposal/alter_health() + return get_turf(src) + +// attempt to move while inside +/obj/machinery/disposal/relaymove(mob/user as mob) + if(user.stat || src.flushing) + return + src.go_out(user) + return + +// leave the disposal +/obj/machinery/disposal/proc/go_out(mob/user) + + if (user.client) + user.client.eye = user.client.mob + user.client.perspective = MOB_PERSPECTIVE + user.loc = src.loc + update() + return + + +// monkeys can only pull the flush lever +/obj/machinery/disposal/attack_paw(mob/user as mob) + if(stat & BROKEN) + return + + flush = !flush + update() + return + +// ai as human but can't flush +/obj/machinery/disposal/attack_ai(mob/user as mob) + interact(user, 1) + +// human interact with machine +/obj/machinery/disposal/attack_hand(mob/user as mob) + if(user && user.loc == src) + usr << "\red You cannot reach the controls from inside." + return + /* + if(mode==-1) + usr << "\red The disposal units power is disabled." + return + */ + interact(user, 0) + +// user interaction +/obj/machinery/disposal/interact(mob/user, var/ai=0) + + src.add_fingerprint(user) + if(stat & BROKEN) + user.unset_machine() + return + + var/dat = "Waste Disposal UnitWaste Disposal Unit
" + + if(!ai) // AI can't pull flush handle + if(flush) + dat += "Disposal handle: Disengage Engaged" else - return ..(mover, target, height, air_group) + dat += "Disposal handle: Disengaged Engage" + + dat += "

Eject contents
" + + if(mode <= 0) + dat += "Pump: Off On
" + else if(mode == 1) + dat += "Pump: Off On (pressurizing)
" + else + dat += "Pump: Off On (idle)
" + + var/per = 100* air_contents.return_pressure() / (SEND_PRESSURE) + + dat += "Pressure: [round(per, 1)]%
" + + + user.set_machine(src) + user << browse(dat, "window=disposal;size=360x170") + onclose(user, "disposal") + +// handle machine interaction + +/obj/machinery/disposal/Topic(href, href_list) + if(usr.loc == src) + usr << "\red You cannot reach the controls from inside." + return + + if(mode==-1 && !href_list["eject"]) // only allow ejecting if mode is -1 + usr << "\red The disposal units power is disabled." + return + ..() + src.add_fingerprint(usr) + if(stat & BROKEN) + return + if(usr.stat || usr.restrained() || src.flushing) + return + + if (in_range(src, usr) && istype(src.loc, /turf)) + usr.set_machine(src) + + if(href_list["close"]) + usr.unset_machine() + usr << browse(null, "window=disposal") + return + + if(href_list["pump"]) + if(text2num(href_list["pump"])) + mode = 1 + else + mode = 0 + update() + + if(href_list["handle"]) + flush = text2num(href_list["handle"]) + update() + + if(href_list["eject"]) + eject() + else + usr << browse(null, "window=disposal") + usr.unset_machine() + return + return + +// eject the contents of the disposal unit +/obj/machinery/disposal/proc/eject() + for(var/atom/movable/AM in src) + AM.loc = src.loc + AM.pipe_eject(0) + update() + +// update the icon & overlays to reflect mode & status +/obj/machinery/disposal/proc/update() + overlays.Cut() + if(stat & BROKEN) + icon_state = "disposal-broken" + mode = 0 + flush = 0 + return + + // flush handle + if(flush) + overlays += image('icons/obj/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) + overlays += image('icons/obj/pipes/disposal.dmi', "dispover-full") + + // charging and ready light + if(mode == 1) + overlays += image('icons/obj/pipes/disposal.dmi', "dispover-charge") + else if(mode == 2) + overlays += image('icons/obj/pipes/disposal.dmi', "dispover-ready") + +// timed process +// charge the gas reservoir and perform flush if ready +/obj/machinery/disposal/process() + if(!air_contents || (stat & BROKEN)) // nothing can happen if broken + update_use_power(0) + return + + flush_count++ + if( flush_count >= flush_every_ticks ) + if( contents.len ) + if(mode == 2) + spawn(0) + feedback_inc("disposal_auto_flush",1) + flush() + flush_count = 0 + + src.updateDialog() + + if(flush && air_contents.return_pressure() >= SEND_PRESSURE ) // flush can happen even without power + flush() + + if(mode != 1) // if off or ready, no need to charge + update_use_power(1) + return + + // otherwise charge + src.pressurize() + + // if full enough, switch to ready mode + if(air_contents.return_pressure() >= SEND_PRESSURE) + mode = 2 + update() + return + +/obj/machinery/disposal/proc/pressurize() + if(stat & NOPOWER) // won't charge if no power + update_use_power(0) + return + + var/atom/L = loc // recharging from loc turf + var/datum/gas_mixture/env = L.return_air() + + var/power_draw = -1 + if(env && env.temperature > 0) + var/transfer_moles = (PUMP_MAX_FLOW_RATE/env.volume)*env.total_moles //group_multiplier is divided out here + power_draw = pump_gas(src, env, air_contents, transfer_moles, active_power_usage) + + if (power_draw < 0) + //update_use_power(0) + use_power = 1 //don't force update - easier on CPU + else + handle_power_draw(power_draw) + +// perform a flush +/obj/machinery/disposal/proc/flush() + + flushing = 1 + flick("[icon_state]-flush", src) + + var/wrapcheck = 0 + var/obj/structure/disposalholder/H = new() // virtual holder object which actually + // travels through the pipes. + //Hacky test to get drones to mail themselves through disposals. + for(var/mob/living/silicon/robot/drone/D in src) + wrapcheck = 1 + + for(var/obj/item/smallDelivery/O in src) + wrapcheck = 1 + + if(wrapcheck == 1) + H.tomail = 1 + + + air_contents = new() // new empty gas resv. + + sleep(10) + if(last_sound < world.time + 1) + playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0) + last_sound = world.time + sleep(5) // wait for animation to finish + + + H.init(src) // copy the contents of disposer to holder + + H.start(src) // start the holder processing movement + flushing = 0 + // now reset disposal state + flush = 0 + if(mode == 2) // if was ready, + mode = 1 // switch to charging + update() + return + + +// called when area power changes +/obj/machinery/disposal/power_change() + ..() // do default setting/reset of stat NOPOWER bit + update() // update icon + return + + +// called when holder is expelled from a disposal +// should usually only occur if the pipe network is modified +/obj/machinery/disposal/proc/expel(var/obj/structure/disposalholder/H) + + var/turf/target + playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) + if(H) // Somehow, someone managed to flush a window which broke mid-transit and caused the disposal to go in an infinite loop trying to expel null, hopefully this fixes it + for(var/atom/movable/AM in H) + target = get_offset_target_turf(src.loc, rand(5)-rand(5), rand(5)-rand(5)) + + AM.loc = src.loc + AM.pipe_eject(0) + if(!istype(AM,/mob/living/silicon/robot/drone)) //Poor drones kept smashing windows and taking system damage being fired out of disposals. ~Z + spawn(1) + if(AM) + AM.throw_at(target, 5, 1) + + H.vent_gas(loc) + del(H) + +/obj/machinery/disposal/CanPass(atom/movable/mover, turf/target, height=0, air_group=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 + for(var/mob/M in viewers(src)) + M.show_message("\the [I] lands in \the [src].", 3) + else + for(var/mob/M in viewers(src)) + M.show_message("\the [I] bounces off of \the [src]'s rim!.", 3) + return 0 + else + return ..(mover, target, height, air_group) // virtual disposal object // travels through pipes in lieu of actual items