mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-08-25 06:07:22 +01:00
311 lines
13 KiB
Plaintext
311 lines
13 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
|
|
anchored = TRUE
|
|
idle_power_usage = 0
|
|
active_power_usage = 0
|
|
power_channel = ENVIRON
|
|
var/nodealert = 0
|
|
var/power_rating //the maximum amount of power the machine can use to do work, affects how powerful the machine is, in Watts
|
|
|
|
unacidable = TRUE
|
|
layer = ATMOS_LAYER
|
|
plane = PLATING_PLANE
|
|
|
|
var/pipe_flags = PIPING_DEFAULT_LAYER_ONLY // Allow other layers by exception basis.
|
|
var/connect_types = CONNECT_TYPE_REGULAR
|
|
var/piping_layer = PIPING_LAYER_DEFAULT // This will replace icon_connect_type at some point ~Leshana
|
|
var/icon_connect_type = "" //"-supply" or "-scrubbers"
|
|
var/construction_type = null // Type path of the pipe item when this is deconstructed.
|
|
var/pipe_state // icon_state as a pipe item
|
|
|
|
var/being_loaded = FALSE //If the atmos machinery is currently being loaded via a map_template
|
|
|
|
var/initialize_directions = 0
|
|
var/pipe_color
|
|
|
|
var/obj/machinery/atmospherics/node1
|
|
var/obj/machinery/atmospherics/node2
|
|
|
|
/obj/machinery/atmospherics/Initialize(mapload, newdir)
|
|
. = ..()
|
|
if(!isnull(newdir))
|
|
set_dir(newdir)
|
|
if(!pipe_color)
|
|
pipe_color = color
|
|
color = null
|
|
|
|
if(!pipe_color_check(pipe_color))
|
|
pipe_color = null
|
|
init_dir()
|
|
|
|
/obj/machinery/atmospherics/examine_icon()
|
|
return icon(icon=initial(icon),icon_state=initial(icon_state))
|
|
|
|
// This is used to set up what directions pipes will connect to. Should be called inside New() and whenever a dir changes.
|
|
/obj/machinery/atmospherics/proc/init_dir()
|
|
return
|
|
|
|
// Get ALL initialize_directions - Some types (HE pipes etc) combine two vars together for this.
|
|
/obj/machinery/atmospherics/proc/get_init_dirs()
|
|
return initialize_directions
|
|
|
|
// Get the direction each node is facing to connect.
|
|
// It now returns as a list so it can be fetched nicely, each entry corresponds to node of same number.
|
|
/obj/machinery/atmospherics/proc/get_node_connect_dirs()
|
|
return
|
|
|
|
// Initializes nodes by looking at neighboring atmospherics machinery to connect to.
|
|
// When we're being constructed at runtime, atmos_init() is called by the construction code.
|
|
// When dynamically loading a map atmos_init is called by the maploader (initTemplateBounds proc)
|
|
// But during initial world creation its called by the master_controller.
|
|
// TODO - Consolidate these different ways of being called once SSatoms is created.
|
|
/obj/machinery/atmospherics/proc/atmos_init()
|
|
return
|
|
|
|
/** Check if target is an acceptable target to connect as a node from this machine. */
|
|
/obj/machinery/atmospherics/proc/can_be_node(obj/machinery/atmospherics/target, node_num)
|
|
return (target.initialize_directions & get_dir(target,src)) && check_connectable(target) && target.check_connectable(src)
|
|
|
|
/** Check if this machine is willing to connect with the target machine. */
|
|
/obj/machinery/atmospherics/proc/check_connectable(obj/machinery/atmospherics/target)
|
|
return (src.connect_types & target.connect_types) && !check_if_side_in_use(target)
|
|
|
|
/** Returns true if a pipe is already connected to the same side of the target as ourselves. This is a hack to prevent multi-connection from the same turf. Our atmopipes do not have support for multiple connections, this requires a major refactor or replacement port from TG in the future. */
|
|
/obj/machinery/atmospherics/proc/check_if_side_in_use(obj/machinery/atmospherics/target)
|
|
if(istype(src, /obj/machinery/atmospherics/pipe/simple/hidden/universal) \
|
|
|| istype(src, /obj/machinery/atmospherics/pipe/simple/visible/universal) \
|
|
|| istype(target, /obj/machinery/atmospherics/pipe/simple/visible/universal) \
|
|
|| istype(target, /obj/machinery/atmospherics/pipe/simple/visible/universal))
|
|
return FALSE // Snowflake to allow univerals pipe adaptors to bridge the gap on the same side
|
|
var/list/node_list = target.get_neighbor_nodes_for_init()
|
|
if(!length(node_list)) // Preserving original behavior
|
|
return TRUE
|
|
// By default, do not allow connections from the same side.
|
|
var/turf/our_turf = get_turf(src)
|
|
for(var/obj/machinery/atmospherics/check_node in node_list)
|
|
if(QDELETED(check_node) || check_node == src)
|
|
continue
|
|
if(get_turf(check_node) == our_turf)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/// Prioritize pipes that are already trying to link to us, prevents mismatching when both sides call atmo_init() on their own
|
|
/obj/machinery/atmospherics/proc/get_prioritized_nodes(turf/at_loc)
|
|
RETURN_TYPE(/list)
|
|
|
|
var/priority_target = null
|
|
var/list/viable_nodes = list()
|
|
for(var/obj/machinery/atmospherics/checking in at_loc)
|
|
var/list/node_list = checking.get_neighbor_nodes_for_init()
|
|
if(!priority_target) // Check for pipes already linking to us from their side. We want them to be priority to link back.
|
|
for(var/obj/machinery/atmospherics/node_check in node_list)
|
|
if(!priority_target && node_check == src)
|
|
priority_target = checking
|
|
break
|
|
// Otherwise we just want a list of all the viable targets we COULD link to. check_connectable() will be called after to see if they can be linked to properly.
|
|
if(checking != priority_target)
|
|
viable_nodes += checking
|
|
|
|
// So the goal of this proc is to organize the list so that the one trying to link to us will be FIRST, but the list of targets is always all available nodes
|
|
if(priority_target) // Put the priority target at the head
|
|
viable_nodes = list(priority_target) + viable_nodes
|
|
|
|
return viable_nodes
|
|
|
|
|
|
/obj/machinery/atmospherics/attackby(atom/A, mob/user as mob)
|
|
if(istype(A, /obj/item/pipe_painter))
|
|
return
|
|
..()
|
|
|
|
/obj/machinery/atmospherics/proc/add_underlay(turf/T, obj/machinery/atmospherics/node, direction, icon_connect_type)
|
|
if(node)
|
|
if(!T.is_plating() && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
|
|
//underlays += icon_manager.get_atmos_icon("underlay_down", direction, color_cache_name(node))
|
|
underlays += GLOB.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 += GLOB.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 += GLOB.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "exposed" + icon_connect_type)
|
|
|
|
/obj/machinery/atmospherics/proc/update_underlays()
|
|
return TRUE
|
|
|
|
/obj/machinery/atmospherics/proc/color_cache_name(obj/machinery/atmospherics/node)
|
|
//Don't use this for standard pipes
|
|
if(!istype(node))
|
|
return null
|
|
|
|
return node.pipe_color
|
|
|
|
/obj/machinery/atmospherics/process()
|
|
if(being_loaded) //If we're being maploaded, don't build the network just yet.
|
|
return
|
|
last_flow_rate = 0
|
|
last_power_draw = 0
|
|
|
|
build_network()
|
|
|
|
/obj/machinery/atmospherics/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
|
|
// Check to see if should be added to network. Add self if so and adjust variables appropriately.
|
|
// Note don't forget to have neighbors look as well!
|
|
|
|
return null
|
|
|
|
/obj/machinery/atmospherics/proc/build_network(new_attachment)
|
|
// Called to build a network from this node
|
|
|
|
return null
|
|
|
|
/obj/machinery/atmospherics/proc/return_network(obj/machinery/atmospherics/reference)
|
|
// Returns pipe_network associated with connection to reference
|
|
// Notes: should create network if necessary
|
|
// Should never return null
|
|
|
|
return null
|
|
|
|
/obj/machinery/atmospherics/proc/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
|
|
// Used when two pipe_networks are combining
|
|
|
|
/obj/machinery/atmospherics/proc/return_network_air(datum/pipe_network/reference)
|
|
// Return a list of gas_mixture(s) in the object
|
|
// associated with reference pipe_network for use in rebuilding the networks gases list
|
|
// Is permitted to return null
|
|
|
|
/obj/machinery/atmospherics/proc/disconnect(obj/machinery/atmospherics/reference)
|
|
|
|
/obj/machinery/atmospherics/update_icon()
|
|
return null
|
|
|
|
/obj/machinery/atmospherics/proc/can_unwrench()
|
|
|
|
/* //Old version. We now handle unwrenching in the machinery itself.
|
|
var/datum/gas_mixture/int_air = return_air()
|
|
var/datum/gas_mixture/env_air = loc.return_air()
|
|
if((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
|
return FALSE
|
|
*/
|
|
return TRUE
|
|
|
|
// Deconstruct into a pipe item.
|
|
/obj/machinery/atmospherics/atom_deconstruct()
|
|
if(QDELETED(src))
|
|
return
|
|
if(construction_type)
|
|
var/obj/item/pipe/I = new construction_type(loc, null, null, src)
|
|
I.setPipingLayer(piping_layer)
|
|
if(istype(I, /obj/item/pipe/trinary/flippable))
|
|
var/obj/item/pipe/trinary/flippable/flip = I
|
|
flip.icon_state = "[flip.icon_state][flip.mirrored ? "m" : ""]"
|
|
transfer_fingerprints_to(I)
|
|
qdel(src)
|
|
|
|
// Return a list of nodes which we should call atmos_init() and build_network() during on_construction()
|
|
/obj/machinery/atmospherics/proc/get_neighbor_nodes_for_init()
|
|
return null
|
|
|
|
// Called on construction (i.e from pipe item) but not on initialization
|
|
/obj/machinery/atmospherics/proc/on_construction(obj_color, set_layer)
|
|
pipe_color = obj_color
|
|
setPipingLayer(set_layer)
|
|
// TODO - M.connect_types = src.connect_types - Or otherwise copy from item? Or figure it out from piping layer?
|
|
var/turf/T = get_turf(src)
|
|
level = !T.is_plating() ? 2 : 1
|
|
atmos_init()
|
|
if(QDELETED(src))
|
|
return // TODO - Eventually should get rid of the need for this.
|
|
var/list/nodes = get_neighbor_nodes_for_init()
|
|
for(var/obj/machinery/atmospherics/A in nodes)
|
|
A.atmos_init()
|
|
A.build_network(TRUE)
|
|
build_network()
|
|
|
|
// There was a coder comment her from 7 years ago asking 'tg does it this way, should we?' and the answer was yes.
|
|
// By building the network BEFORE our nodes build their network, two things happened:
|
|
// 1. The network was built and none of the pipes got their temporary air vaiables, resulting in the pipes having no air in them
|
|
// 2. The previous network was nulled but never deleted, resulting in a memory leak.
|
|
// So now, we build our network AFTER the nodes build their network AND we delete the previous network.
|
|
|
|
// This sets our piping layer. Hopefully its cool.
|
|
/obj/machinery/atmospherics/proc/setPipingLayer(new_layer)
|
|
if(pipe_flags & (PIPING_DEFAULT_LAYER_ONLY|PIPING_ALL_LAYER))
|
|
new_layer = PIPING_LAYER_DEFAULT
|
|
piping_layer = new_layer
|
|
// Do it the Polaris way
|
|
switch(piping_layer)
|
|
if(PIPING_LAYER_SCRUBBER)
|
|
icon_state = "[icon_state]-scrubbers"
|
|
connect_types = CONNECT_TYPE_SCRUBBER
|
|
layer = PIPES_SCRUBBER_LAYER
|
|
icon_connect_type = "-scrubbers"
|
|
if(PIPING_LAYER_SUPPLY)
|
|
icon_state = "[icon_state]-supply"
|
|
connect_types = CONNECT_TYPE_SUPPLY
|
|
layer = PIPES_SUPPLY_LAYER
|
|
icon_connect_type = "-supply"
|
|
if(PIPING_LAYER_FUEL)
|
|
icon_state = "[icon_state]-fuel"
|
|
connect_types = CONNECT_TYPE_FUEL
|
|
layer = PIPES_FUEL_LAYER
|
|
icon_connect_type = "-fuel"
|
|
if(PIPING_LAYER_AUX)
|
|
icon_state = "[icon_state]-aux"
|
|
connect_types = CONNECT_TYPE_AUX
|
|
layer = PIPES_AUX_LAYER
|
|
icon_connect_type = "-aux"
|
|
if(pipe_flags & PIPING_ALL_LAYER)
|
|
connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER|CONNECT_TYPE_FUEL|CONNECT_TYPE_AUX
|
|
// Or if we were to do it the TG way...
|
|
// pixel_x = PIPE_PIXEL_OFFSET_X(piping_layer)
|
|
// pixel_y = PIPE_PIXEL_OFFSET_Y(piping_layer)
|
|
// layer = initial(layer) + PIPE_LAYER_OFFSET(piping_layer)
|
|
|
|
/obj/machinery/atmospherics/proc/unsafe_pressure_release(mob/user, pressures = null)
|
|
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()
|
|
|
|
user.visible_message(span_danger("[user] is sent flying by pressure!"),span_userdanger("The pressure sends you flying!"))
|
|
|
|
// if get_dir(src, user) is not 0, target is the edge_target_turf on that dir
|
|
// otherwise, edge_target_turf uses a random cardinal direction
|
|
// range is pressures / 250
|
|
// speed is pressures / 1250
|
|
if(user.buckled)
|
|
user.buckled.unbuckle_mob(user, TRUE)
|
|
user.throw_at(get_edge_target_turf(user, get_dir(src, user) || pick(GLOB.cardinal)), pressures / 250, pressures / 1250)
|
|
|
|
/// Blows out a pipe, deconstructing it, breaking the floor and releasing all mobs crawling inside it
|
|
/obj/machinery/atmospherics/proc/blowout(mob/user)
|
|
// Deconstruct turf
|
|
var/turf/our_turf = loc
|
|
if(!our_turf.is_plating() && istype(our_turf,/turf/simulated/floor)) //intact floor, pop the tile
|
|
var/turf/simulated/floor/our_floor = our_turf
|
|
our_floor.make_plating(TRUE)
|
|
// Deconstruct pipe
|
|
var/datum/gas_mixture/int_air = return_air()
|
|
var/datum/gas_mixture/env_air = our_turf.return_air()
|
|
var/internal_pressure = int_air.return_pressure()-env_air.return_pressure()
|
|
atom_deconstruct()
|
|
// Release pressure
|
|
playsound(our_turf, 'sound/effects/bang.ogg', 70, 0, 0)
|
|
playsound(our_turf, 'sound/effects/clang2.ogg', 70, 0, 0)
|
|
if(internal_pressure > 2*ONE_ATMOSPHERE)
|
|
unsafe_pressure_release(user, internal_pressure)
|
|
playsound(our_turf, 'sound/machines/hiss.ogg', 50, 0, 0)
|