Files
Yogstation/code/modules/recycling/disposal/bin.dm
monster860 bf810f49c2 C++ Monstermos - Putting the 99% LAG FREE in 99% LAG FREE (#7981)
* c++ monstermos

fuck

Fixes the server hemorrhaging memory due to extools not decrementing ref counts

Increases defauilt tank pressure

make space cold or some shit

floor tile rips

Fixes code assuming that the heat capacity is nonzero

🤦

Fixes crash

fixes some bugs

fuck *facepalm*

the fastening

removes Del() in favor of an internal c++ hook

Fixes vent-pump math

* Fix the invisible gases bug

* Linux support

* fix the deploy.sh

* Uses newer BYOND 513 because older one is probably missing an important pattern (it segfaulted on pattern search)

* Updates windows dll to match linux version and cleans up unused BYOND code
2020-04-24 10:29:51 -04:00

502 lines
14 KiB
Plaintext

// Disposal bin and Delivery chute.
#define SEND_PRESSURE (0.05*ONE_ATMOSPHERE)
/obj/machinery/disposal
icon = 'icons/obj/atmospherics/pipes/disposal.dmi'
density = TRUE
armor = list("melee" = 25, "bullet" = 10, "laser" = 10, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30)
max_integrity = 200
resistance_flags = FIRE_PROOF
interaction_flags_machine = INTERACT_MACHINE_OPEN | INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON
obj_flags = CAN_BE_HIT | USES_TGUI
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
var/datum/gas_mixture/air_contents // internal reservoir
var/full_pressure = FALSE
var/pressure_charging = TRUE
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/Initialize(mapload, obj/structure/disposalconstruct/make_from)
. = ..()
if(make_from)
setDir(make_from.dir)
make_from.moveToNullspace()
stored = make_from
pressure_charging = FALSE // newly built disposal bins start with pump off
else
stored = new /obj/structure/disposalconstruct(null, null , SOUTH , FALSE , src)
trunk_check()
air_contents = new /datum/gas_mixture()
//gas.volume = 1.05 * CELLSTANDARD
update_icon()
return INITIALIZE_HINT_LATELOAD //we need turfs to have air
/obj/machinery/disposal/proc/trunk_check()
trunk = locate() in loc
if(!trunk)
pressure_charging = FALSE
flush = FALSE
else
if(initial(pressure_charging))
pressure_charging = TRUE
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/LateInitialize()
//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(!pressure_charging && !full_pressure && !flush)
if(I.tool_behaviour == TOOL_SCREWDRIVER)
panel_open = !panel_open
I.play_tool_sound(src)
to_chat(user, "<span class='notice'>You [panel_open ? "remove":"attach"] the screws around the power connection.</span>")
return
else if(I.tool_behaviour == TOOL_WELDER && panel_open)
if(!I.tool_start_check(user, amount=0))
return
to_chat(user, "<span class='notice'>You start slicing the floorweld off \the [src]...</span>")
if(I.use_tool(src, user, 20, volume=100) && panel_open)
to_chat(user, "<span class='notice'>You slice the floorweld off \the [src].</span>")
deconstruct()
return
if(user.a_intent != INTENT_HARM)
if((I.item_flags & ABSTRACT) || !user.temporarilyRemoveItemFromInventory(I))
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.forceMove(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.
if (iscyborg(user))
var/mob/living/silicon/robot/borg = user
if (!borg.module || !borg.module.canDispose)
return
else
return
if(!isturf(user.loc)) //No magically doing it from inside closets
return
if(target.buckled || target.has_buckled_mobs())
return
if(target.mob_size > MOB_SIZE_HUMAN)
to_chat(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>")
log_combat(user, target, "stuffed", addition="into [src]")
target.LAssailant = user
update_icon()
/obj/machinery/disposal/relaymove(mob/user)
attempt_escape(user)
// resist to escape the bin
/obj/machinery/disposal/container_resist(mob/living/user)
attempt_escape(user)
/obj/machinery/disposal/proc/attempt_escape(mob/user)
if(flushing)
return
go_out(user)
// leave the disposal
/obj/machinery/disposal/proc/go_out(mob/user)
user.forceMove(loc)
update_icon()
// monkeys and xenos can only pull the flush lever
/obj/machinery/disposal/attack_paw(mob/user)
if(stat & BROKEN)
return
flush = !flush
update_icon()
// 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 = TRUE
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(src)
newHolderDestination(H)
H.init(src)
air_contents = new()
H.start(src)
flushing = FALSE
flush = FALSE
/obj/machinery/disposal/proc/newHolderDestination(obj/structure/disposalholder/H)
for(var/obj/item/smallDelivery/O in src)
H.tomail = TRUE
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
// called when holder is expelled from a disposal
/obj/machinery/disposal/proc/expel(obj/structure/disposalholder/H)
H.active = FALSE
var/turf/T = get_turf(src)
var/turf/target
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
for(var/A in H)
var/atom/movable/AM = A
target = get_offset_target_turf(loc, rand(5)-rand(5), rand(5)-rand(5))
AM.forceMove(T)
AM.pipe_eject(0)
AM.throw_at(target, 5, 1)
H.vent_gas(loc)
qdel(H)
/obj/machinery/disposal/deconstruct(disassembled = TRUE)
var/turf/T = loc
if(!(flags_1 & NODECONSTRUCT_1))
if(stored)
stored.forceMove(T)
src.transfer_fingerprints_to(stored)
stored.anchored = FALSE
stored.density = TRUE
stored.update_icon()
for(var/atom/movable/AM in src) //out, out, darned crowbar!
AM.forceMove(T)
..()
/obj/machinery/disposal/get_dumping_location(obj/item/storage/source,mob/user)
return src
//How disposal handles getting a storage dump from a storage object
/obj/machinery/disposal/storage_contents_dump_act(datum/component/storage/src_object, mob/user)
. = ..()
if(.)
return
for(var/obj/item/I in src_object)
if(user.active_storage != src_object)
if(I.on_found(user))
return
src_object.remove_from_storage(I, src)
return TRUE
// 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/storage/bag/trash)) //Not doing component overrides because this is a specific type.
var/obj/item/storage/bag/trash/T = I
var/datum/component/storage/STR = T.GetComponent(/datum/component/storage)
to_chat(user, "<span class='warning'>You empty the bag.</span>")
for(var/obj/item/O in T.contents)
STR.remove_from_storage(O,src)
T.update_icon()
update_icon()
else
return ..()
// handle machine interaction
/obj/machinery/disposal/bin/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
if(stat & BROKEN)
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "disposal_unit", name, 300, 180, master_ui, state)
ui.open()
/obj/machinery/disposal/bin/ui_data(mob/user)
var/list/data = list()
data["flush"] = flush
data["full_pressure"] = full_pressure
data["pressure_charging"] = pressure_charging
data["panel_open"] = panel_open
data["per"] = CLAMP01(air_contents.return_pressure() / (SEND_PRESSURE))
data["isai"] = isAI(user)
return data
/obj/machinery/disposal/bin/ui_act(action, params)
if(..())
return
switch(action)
if("handle-0")
flush = FALSE
update_icon()
. = TRUE
if("handle-1")
if(!panel_open)
flush = TRUE
update_icon()
. = TRUE
if("pump-0")
if(pressure_charging)
pressure_charging = FALSE
update_icon()
. = TRUE
if("pump-1")
if(!pressure_charging)
pressure_charging = TRUE
update_icon()
. = TRUE
if("eject")
eject()
. = TRUE
/obj/machinery/disposal/bin/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
if(isitem(AM) && AM.CanEnterDisposals())
if(prob(75))
AM.forceMove(src)
visible_message("<span class='notice'>[AM] lands in [src].</span>")
update_icon()
else
visible_message("<span class='notice'>[AM] bounces off of [src]'s rim!</span>")
return ..()
else
return ..()
/obj/machinery/disposal/bin/flush()
..()
full_pressure = FALSE
pressure_charging = TRUE
update_icon()
/obj/machinery/disposal/bin/update_icon()
cut_overlays()
if(stat & BROKEN)
pressure_charging = FALSE
flush = FALSE
return
//flush handle
if(flush)
add_overlay("dispover-handle")
//only handle is shown if no power
if(stat & NOPOWER || panel_open)
return
//check for items in disposal - occupied light
if(contents.len > 0)
add_overlay("dispover-full")
//charging and ready light
if(pressure_charging)
add_overlay("dispover-charge")
else if(full_pressure)
add_overlay("dispover-ready")
/obj/machinery/disposal/bin/proc/do_flush()
set waitfor = FALSE
flush()
//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(full_pressure)
do_flush()
flush_count = 0
updateDialog()
if(flush && air_contents.return_pressure() >= SEND_PRESSURE) // flush can happen even without power
do_flush()
if(stat & NOPOWER) // won't charge if no power
return
use_power(100) // base power usage
if(!pressure_charging) // 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.return_temperature() > 0)
var/transfer_moles = 0.1 * pressure_delta*air_contents.return_volume()/(env.return_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)
full_pressure = TRUE
pressure_charging = FALSE
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 = TRUE
icon_state = "intake"
pressure_charging = FALSE // the chute doesn't need charging and always works
/obj/machinery/disposal/deliveryChute/Initialize(mapload, obj/structure/disposalconstruct/make_from)
. = ..()
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.CanEnterDisposals())
..()
flush()
/obj/machinery/disposal/deliveryChute/Bumped(atom/movable/AM) //Go straight into the chute
if(QDELETED(AM) || !AM.CanEnterDisposals())
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(isobj(AM))
var/obj/O = AM
O.forceMove(src)
else if(ismob(AM))
var/mob/M = AM
if(prob(2)) // to prevent mobs being stuck in infinite loops
to_chat(M, "<span class='warning'>You hit the edge of the chute.</span>")
return
M.forceMove(src)
flush()
/atom/movable/proc/CanEnterDisposals()
return TRUE
/obj/item/projectile/CanEnterDisposals()
return
/obj/effect/CanEnterDisposals()
return
/obj/mecha/CanEnterDisposals()
return
/obj/machinery/disposal/bin/newHolderDestination(obj/structure/disposalholder/H)
H.destinationTag = 1
/obj/machinery/disposal/deliveryChute/newHolderDestination(obj/structure/disposalholder/H)
H.destinationTag = 1