mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
* 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
502 lines
14 KiB
Plaintext
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
|