mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-04-22 04:21:57 +01:00
Changes: - Clicking "view structural data" in the station blueprints menu will show you ghost images of where things like disposal pipes, wires, atmospherics pipes, and other power machinery are originally supposed to go. Note, this will show you the ghost images over turfs even if the machinery is destroyed.
321 lines
11 KiB
Plaintext
321 lines
11 KiB
Plaintext
/*
|
|
Quick overview:
|
|
|
|
Pipes combine to form pipelines
|
|
Pipelines and other atmospheric objects combine to form pipe_networks
|
|
Note: A single pipe_network represents a completely open space
|
|
|
|
Pipes -> Pipelines
|
|
Pipelines + Other Objects -> Pipe network
|
|
|
|
*/
|
|
/obj/machinery/atmospherics
|
|
auto_init = 0
|
|
anchored = 1
|
|
layer = 2.4 //under wires with their 2.44
|
|
idle_power_usage = 0
|
|
active_power_usage = 0
|
|
power_channel = ENVIRON
|
|
on_blueprints = TRUE
|
|
var/nodealert = 0
|
|
var/can_unwrench = 0
|
|
|
|
var/connect_types[] = list(1) //1=regular, 2=supply, 3=scrubber
|
|
var/connected_to = 1 //same as above, currently not used for anything
|
|
var/icon_connect_type = "" //"-supply" or "-scrubbers"
|
|
|
|
var/initialize_directions = 0
|
|
|
|
var/pipe_color
|
|
var/obj/item/pipe/stored
|
|
var/image/pipe_image
|
|
var/global/datum/pipe_icon_manager/icon_manager
|
|
|
|
/obj/machinery/atmospherics/New()
|
|
if(!icon_manager)
|
|
icon_manager = new()
|
|
|
|
if(!pipe_color)
|
|
pipe_color = color
|
|
color = null
|
|
|
|
if(!pipe_color_check(pipe_color))
|
|
pipe_color = null
|
|
|
|
..()
|
|
|
|
/obj/machinery/atmospherics/initialize()
|
|
..()
|
|
|
|
if(can_unwrench)
|
|
stored = new(src, make_from = src)
|
|
|
|
/obj/machinery/atmospherics/Destroy()
|
|
if(stored)
|
|
qdel(stored)
|
|
stored = null
|
|
for(var/mob/living/L in src) //ventcrawling is serious business
|
|
L.remove_ventcrawl()
|
|
L.forceMove(get_turf(src))
|
|
if(pipe_image)
|
|
qdel(pipe_image) //we have to del it, or it might keep a ref somewhere else
|
|
pipe_image = null
|
|
return ..()
|
|
|
|
// Icons/overlays/underlays
|
|
/obj/machinery/atmospherics/update_icon()
|
|
return null
|
|
|
|
/obj/machinery/atmospherics/proc/check_icon_cache(var/safety = 0)
|
|
if(!istype(icon_manager))
|
|
if(!safety) //to prevent infinite loops
|
|
icon_manager = new()
|
|
check_icon_cache(1)
|
|
return 0
|
|
|
|
return 1
|
|
|
|
/obj/machinery/atmospherics/proc/color_cache_name(var/obj/machinery/atmospherics/node)
|
|
//Don't use this for standard pipes
|
|
if(!istype(node))
|
|
return null
|
|
|
|
return node.pipe_color
|
|
|
|
/obj/machinery/atmospherics/proc/add_underlay(var/turf/T, var/obj/machinery/atmospherics/node, var/direction, var/icon_connect_type)
|
|
if(node)
|
|
if(T.intact && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
|
|
//underlays += icon_manager.get_atmos_icon("underlay_down", direction, color_cache_name(node))
|
|
underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "down" + icon_connect_type)
|
|
else
|
|
//underlays += icon_manager.get_atmos_icon("underlay_intact", direction, color_cache_name(node))
|
|
underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
|
|
else
|
|
//underlays += icon_manager.get_atmos_icon("underlay_exposed", direction, pipe_color)
|
|
underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "exposed" + icon_connect_type)
|
|
|
|
/obj/machinery/atmospherics/proc/update_underlays()
|
|
if(check_icon_cache())
|
|
return 1
|
|
else
|
|
return 0
|
|
|
|
// Connect types
|
|
/obj/machinery/atmospherics/proc/check_connect_types(obj/machinery/atmospherics/atmos1, obj/machinery/atmospherics/atmos2)
|
|
var/i
|
|
var/list1[] = atmos1.connect_types
|
|
var/list2[] = atmos2.connect_types
|
|
for(i=1,i<=list1.len,i++)
|
|
var/j
|
|
for(j=1,j<=list2.len,j++)
|
|
if(list1[i] == list2[j])
|
|
var/n = list1[i]
|
|
return n
|
|
return 0
|
|
|
|
/obj/machinery/atmospherics/proc/check_connect_types_construction(obj/machinery/atmospherics/atmos1, obj/item/pipe/pipe2)
|
|
var/i
|
|
var/list1[] = atmos1.connect_types
|
|
var/list2[] = pipe2.connect_types
|
|
for(i=1,i<=list1.len,i++)
|
|
var/j
|
|
for(j=1,j<=list2.len,j++)
|
|
if(list1[i] == list2[j])
|
|
var/n = list1[i]
|
|
return n
|
|
return 0
|
|
|
|
// Pipenet related functions
|
|
/obj/machinery/atmospherics/proc/returnPipenet()
|
|
return
|
|
|
|
/obj/machinery/atmospherics/proc/returnPipenetAir()
|
|
return
|
|
|
|
/obj/machinery/atmospherics/proc/setPipenet()
|
|
return
|
|
|
|
/obj/machinery/atmospherics/proc/replacePipenet()
|
|
return
|
|
|
|
/obj/machinery/atmospherics/proc/build_network()
|
|
// Called to build a network from this node
|
|
return
|
|
|
|
/obj/machinery/atmospherics/proc/defer_build_network()
|
|
deferred_pipenet_rebuilds += src
|
|
|
|
/obj/machinery/atmospherics/proc/disconnect(obj/machinery/atmospherics/reference)
|
|
return
|
|
|
|
/obj/machinery/atmospherics/proc/nullifyPipenet(datum/pipeline/P)
|
|
if(P)
|
|
P.other_atmosmch -= src
|
|
|
|
//(De)construction
|
|
/obj/machinery/atmospherics/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
|
if(can_unwrench && istype(W, /obj/item/weapon/wrench))
|
|
var/turf/T = get_turf(src)
|
|
if (level == 1 && isturf(T) && T.intact)
|
|
to_chat(user, "<span class='danger'>You must remove the plating first.</span>")
|
|
return 1
|
|
var/datum/gas_mixture/int_air = return_air()
|
|
var/datum/gas_mixture/env_air = loc.return_air()
|
|
add_fingerprint(user)
|
|
|
|
var/unsafe_wrenching = FALSE
|
|
var/internal_pressure = int_air.return_pressure()-env_air.return_pressure()
|
|
|
|
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
|
to_chat(user, "<span class='notice'>You begin to unfasten \the [src]...</span>")
|
|
if (internal_pressure > 2*ONE_ATMOSPHERE)
|
|
to_chat(user, "<span class='warning'>As you begin unwrenching \the [src] a gush of air blows in your face... maybe you should reconsider?</span>")
|
|
unsafe_wrenching = TRUE //Oh dear oh dear
|
|
|
|
if (do_after(user, 40, target = src) && isnull(gcDestroyed))
|
|
user.visible_message( \
|
|
"[user] unfastens \the [src].", \
|
|
"<span class='notice'>You have unfastened \the [src].</span>", \
|
|
"<span class='italics'>You hear ratchet.</span>")
|
|
investigate_log("was <span class='warning'>REMOVED</span> by [key_name(usr)]", "atmos")
|
|
|
|
//You unwrenched a pipe full of pressure? let's splat you into the wall silly.
|
|
if(unsafe_wrenching)
|
|
unsafe_pressure_release(user,internal_pressure)
|
|
Deconstruct()
|
|
else
|
|
return ..()
|
|
|
|
//Called when an atmospherics object is unwrenched while having a large pressure difference
|
|
//with it's locs air contents.
|
|
/obj/machinery/atmospherics/proc/unsafe_pressure_release(var/mob/user,var/pressures)
|
|
if(!user)
|
|
return
|
|
|
|
if(!pressures)
|
|
var/datum/gas_mixture/int_air = return_air()
|
|
var/datum/gas_mixture/env_air = loc.return_air()
|
|
pressures = int_air.return_pressure()-env_air.return_pressure()
|
|
|
|
var/fuck_you_dir = get_dir(src,user)
|
|
var/turf/general_direction = get_edge_target_turf(user,fuck_you_dir)
|
|
user.visible_message("<span class='danger'>[user] is sent flying by pressure!</span>","<span class='userdanger'>The pressure sends you flying!</span>")
|
|
//Values based on 2*ONE_ATMOS (the unsafe pressure), resulting in 20 range and 4 speed
|
|
user.throw_at(general_direction,pressures/10,pressures/50)
|
|
|
|
/obj/machinery/atmospherics/proc/Deconstruct()
|
|
if(can_unwrench)
|
|
stored.loc = get_turf(src)
|
|
transfer_fingerprints_to(stored)
|
|
stored = null
|
|
|
|
qdel(src)
|
|
|
|
/obj/machinery/atmospherics/construction(D, P, C)
|
|
if(C)
|
|
color = C
|
|
dir = D
|
|
initialize_directions = P
|
|
var/turf/T = loc
|
|
level = T.intact ? 2 : 1
|
|
add_fingerprint(usr)
|
|
initialize()
|
|
var/list/nodes = pipeline_expansion()
|
|
for(var/obj/machinery/atmospherics/A in nodes)
|
|
A.initialize()
|
|
A.addMember(src)
|
|
build_network()
|
|
|
|
// Find a connecting /obj/machinery/atmospherics in specified direction.
|
|
/obj/machinery/atmospherics/proc/findConnecting(var/direction)
|
|
for(var/obj/machinery/atmospherics/target in get_step(src,direction))
|
|
var/can_connect = check_connect_types(target, src)
|
|
if(can_connect && (target.initialize_directions & get_dir(target,src)))
|
|
return target
|
|
|
|
// Ventcrawling
|
|
#define VENT_SOUND_DELAY 30
|
|
/obj/machinery/atmospherics/relaymove(mob/living/user, direction)
|
|
if(!(direction & initialize_directions)) //can't go in a way we aren't connecting to
|
|
return
|
|
|
|
if(buckled_mob == user)
|
|
return
|
|
|
|
var/obj/machinery/atmospherics/target_move = findConnecting(direction)
|
|
if(target_move)
|
|
if(is_type_in_list(target_move, ventcrawl_machinery) && target_move.can_crawl_through())
|
|
user.remove_ventcrawl()
|
|
user.forceMove(target_move.loc) //handles entering and so on
|
|
user.visible_message("You hear something squeezing through the ducts.", "You climb out the ventilation system.")
|
|
else if(target_move.can_crawl_through())
|
|
if(returnPipenet() != target_move.returnPipenet())
|
|
user.update_pipe_vision(target_move)
|
|
user.loc = target_move
|
|
user.client.eye = target_move //if we don't do this, Byond only updates the eye every tick - required for smooth movement
|
|
if(world.time - user.last_played_vent > VENT_SOUND_DELAY)
|
|
user.last_played_vent = world.time
|
|
playsound(src, 'sound/machines/ventcrawl.ogg', 50, 1, -3)
|
|
else
|
|
var/can_connect = check_connect_types(target_move, src)
|
|
if((direction & initialize_directions) || (is_type_in_list(src, ventcrawl_machinery) && target_move.can_crawl_through() && can_connect)) //if we move in a way the pipe can connect, but doesn't - or we're in a vent
|
|
user.remove_ventcrawl()
|
|
user.forceMove(src.loc)
|
|
user.visible_message("You hear something squeezing through the pipes.", "You climb out the ventilation system.")
|
|
user.canmove = 0
|
|
spawn(1)
|
|
user.canmove = 1
|
|
|
|
/obj/machinery/atmospherics/AltClick(var/mob/living/L)
|
|
if(is_type_in_list(src, ventcrawl_machinery))
|
|
L.handle_ventcrawl(src)
|
|
return
|
|
..()
|
|
|
|
/obj/machinery/atmospherics/proc/can_crawl_through()
|
|
return 1
|
|
|
|
/obj/machinery/atmospherics/proc/change_color(var/new_color)
|
|
//only pass valid pipe colors please ~otherwise your pipe will turn invisible
|
|
if(!pipe_color_check(new_color))
|
|
return
|
|
|
|
pipe_color = new_color
|
|
update_icon()
|
|
|
|
// Additional icon procs
|
|
/obj/machinery/atmospherics/proc/universal_underlays(var/obj/machinery/atmospherics/node, var/direction)
|
|
var/turf/T = get_turf(src)
|
|
if(!istype(T)) return
|
|
if(node)
|
|
var/node_dir = get_dir(src,node)
|
|
if(node.icon_connect_type == "-supply")
|
|
add_underlay_adapter(T, , node_dir, "")
|
|
add_underlay_adapter(T, node, node_dir, "-supply")
|
|
add_underlay_adapter(T, , node_dir, "-scrubbers")
|
|
else if (node.icon_connect_type == "-scrubbers")
|
|
add_underlay_adapter(T, , node_dir, "")
|
|
add_underlay_adapter(T, , node_dir, "-supply")
|
|
add_underlay_adapter(T, node, node_dir, "-scrubbers")
|
|
else
|
|
add_underlay_adapter(T, node, node_dir, "")
|
|
add_underlay_adapter(T, , node_dir, "-supply")
|
|
add_underlay_adapter(T, , node_dir, "-scrubbers")
|
|
else
|
|
add_underlay_adapter(T, , direction, "-supply")
|
|
add_underlay_adapter(T, , direction, "-scrubbers")
|
|
add_underlay_adapter(T, , direction, "")
|
|
|
|
/obj/machinery/atmospherics/proc/add_underlay_adapter(var/turf/T, var/obj/machinery/atmospherics/node, var/direction, var/icon_connect_type) //modified from add_underlay, does not make exposed underlays
|
|
if(node)
|
|
if(T.intact && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
|
|
underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "down" + icon_connect_type)
|
|
else
|
|
underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
|
|
else
|
|
underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "retracted" + icon_connect_type)
|
|
|
|
/obj/machinery/atmospherics/singularity_pull(S, current_size)
|
|
if(current_size >= STAGE_FIVE)
|
|
Deconstruct()
|