From 63a1dd01437dba7cc5f91a91ea9c468948a6b87f Mon Sep 17 00:00:00 2001 From: Leshana Date: Sun, 4 Mar 2018 14:40:16 -0500 Subject: [PATCH] - Moved pipe construction defines into __defines/construction.dm - Unified pipe *unwrenching* by creating a standard proc along with the `construction_type` var. - Eliminated the pipe fitting name & icon_state lookup tables by adding `pipe_state` var on atmos machinery and referencing that. - Each pipe which can be made from a fitting object should override `pipe_state` with the icon state to be used on the pipe fitting object. - Eliminated the giant switch statement of doom in pipe construction by delegating that work to `on_construction` proc. - To make this work, every pipe must implement `get_neighbor_nodes_for_init` which returns a list of nodes which should be re-initialized on that pipe's construction. - Combined the SCRUBBERS, SUPPLY and REGULAR pipe fitting classes together by storing the `piping_layer` variable and using the `setPipingLayer` procs - Standardized the code for searching for node neighbors into the `can_be_node` proc. - This proc is also improved in that is a mutual check, `check_connectable` is called on BOTH objects, so they have to mutually agree to connect as nodes. Eliminates lots of special edge case logic. - Updated all the `amos_init` procs to use `can_be_node`. In the most common cases, even that boilerplate code is consolidated into the `STANDARD_ATMOS_CHOOSE_NODE` macro. - Implemented `pipe_flags` which lets pipes declare (or override) certain requirements. - Adds a "pipe_recipe" datum to help out things that construct pipes. By taking it out of the dispenser, we open the road for multiple dispenser types. No, no RPD yet. Soon. - Enhances the pipe dispenser to operate on pipe recipe datums instead of hard coded lists of pipes it can construct. These datums are also (partially) initialized from the pipe machine types themselves, reducing having to define stuff in multiple places. - Switched pipe dispenser UI to use browse(). Not a NanoUI, but makes it a bit prettier with low effort. - Changed pipe dispenser to use a button selector to switch between Regular/Scrubbers/Supply instead of having separate list items. - Added icon states to HE pipes to support the "connected on neither side" state. --- code/ATMOSPHERICS/_atmos_setup.dm | 5 - code/ATMOSPHERICS/atmospherics.dm | 80 +- .../binary_devices/algae_generator_vr.dm | 1 + .../binary_devices/binary_atmos_base.dm | 16 +- .../components/binary_devices/circulator.dm | 1 + .../components/binary_devices/dp_vent_pump.dm | 1 + .../components/binary_devices/passive_gate.dm | 5 +- .../components/binary_devices/pipeturbine.dm | 3 + .../components/binary_devices/pump.dm | 5 +- .../components/binary_devices/volume_pump.dm | 2 + .../components/omni_devices/filter.dm | 1 + .../components/omni_devices/mixer.dm | 1 + .../components/omni_devices/omni_base.dm | 16 +- .../components/portables_connector.dm | 16 +- .../components/trinary_devices/filter.dm | 2 + .../components/trinary_devices/mixer.dm | 4 + .../trinary_devices/trinary_base.dm | 25 +- code/ATMOSPHERICS/components/tvalve.dm | 28 +- .../components/unary/cold_sink.dm | 13 +- .../components/unary/heat_exchanger.dm | 4 +- .../components/unary/heat_source.dm | 13 +- .../components/unary/outlet_injector.dm | 1 + .../components/unary/unary_base.dm | 29 +- .../components/unary/vent_pump.dm | 4 +- .../components/unary/vent_scrubber.dm | 4 +- code/ATMOSPHERICS/components/valve.dm | 21 +- code/ATMOSPHERICS/mainspipe.dm | 3 + code/ATMOSPHERICS/pipes/cap.dm | 10 +- code/ATMOSPHERICS/pipes/he_pipes.dm | 32 +- code/ATMOSPHERICS/pipes/manifold.dm | 30 +- code/ATMOSPHERICS/pipes/manifold4w.dm | 39 +- code/ATMOSPHERICS/pipes/pipe_base.dm | 19 +- code/ATMOSPHERICS/pipes/simple.dm | 29 +- code/ATMOSPHERICS/pipes/tank.dm | 8 +- code/ATMOSPHERICS/pipes/universal.dm | 8 +- code/ATMOSPHERICS/pipes/vent.dm | 10 +- code/__defines/construction.dm | 45 +- code/game/machinery/pipe/construction.dm | 1472 +++-------------- code/game/machinery/pipe/pipe_dispenser.dm | 103 +- code/game/machinery/pipe/pipe_recipes.dm | 102 ++ code/modules/multiz/pipes.dm | 25 +- icons/atmos/heat.dmi | Bin 4827 -> 1605 bytes icons/atmos/junction.dmi | Bin 2799 -> 914 bytes icons/obj/pipe-item.dmi | Bin 28539 -> 29575 bytes vorestation.dme | 1 + 45 files changed, 718 insertions(+), 1519 deletions(-) create mode 100644 code/game/machinery/pipe/pipe_recipes.dm diff --git a/code/ATMOSPHERICS/_atmos_setup.dm b/code/ATMOSPHERICS/_atmos_setup.dm index f1f560a00d..6af102cf38 100644 --- a/code/ATMOSPHERICS/_atmos_setup.dm +++ b/code/ATMOSPHERICS/_atmos_setup.dm @@ -15,11 +15,6 @@ #define PIPE_COLOR_BLACK "#444444" #define PIPE_COLOR_PURPLE "#5c1ec0" -#define CONNECT_TYPE_REGULAR 1 -#define CONNECT_TYPE_SUPPLY 2 -#define CONNECT_TYPE_SCRUBBER 4 -#define CONNECT_TYPE_HE 8 - var/global/list/pipe_colors = list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "black" = PIPE_COLOR_BLACK, "purple" = PIPE_COLOR_PURPLE) /proc/pipe_color_lookup(var/color) diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm index 59163e1b82..940c5edf1c 100644 --- a/code/ATMOSPHERICS/atmospherics.dm +++ b/code/ATMOSPHERICS/atmospherics.dm @@ -19,8 +19,12 @@ Pipelines + Other Objects -> Pipe network layer = 2.4 //under wires with their 2.44 + 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/initialize_directions = 0 var/pipe_color @@ -46,6 +50,10 @@ Pipelines + Other Objects -> Pipe network /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() @@ -59,6 +67,14 @@ Pipelines + Other Objects -> Pipe network /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) + /obj/machinery/atmospherics/attackby(atom/A, mob/user as mob) if(istype(A, /obj/item/device/pipe_painter)) return @@ -82,12 +98,6 @@ Pipelines + Other Objects -> Pipe network else return 0 -obj/machinery/atmospherics/proc/check_connect_types(obj/machinery/atmospherics/atmos1, obj/machinery/atmospherics/atmos2) - return (atmos1.connect_types & atmos2.connect_types) - -/obj/machinery/atmospherics/proc/check_connect_types_construction(obj/machinery/atmospherics/atmos1, obj/item/pipe/pipe2) - return (atmos1.connect_types & pipe2.connect_types) - /obj/machinery/atmospherics/proc/check_icon_cache(var/safety = 0) if(!istype(icon_manager)) if(!safety) //to prevent infinite loops @@ -146,4 +156,60 @@ obj/machinery/atmospherics/proc/check_connect_types(obj/machinery/atmospherics/a var/datum/gas_mixture/env_air = loc.return_air() if((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE) return 0 - return 1 \ No newline at end of file + return 1 + +// Deconstruct into a pipe item. +/obj/machinery/atmospherics/proc/deconstruct() + if(QDELETED(src)) + return + if(construction_type) + var/obj/item/pipe/I = new construction_type(loc, null, null, src) + I.setPipingLayer(piping_layer) + 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. + build_network() + var/list/nodes = get_neighbor_nodes_for_init() + for(var/obj/machinery/atmospherics/A in nodes) + A.atmos_init() + A.build_network() + // TODO - Should we do src.build_network() before or after the nodes? + // We've historically done before, but /tg does after. TODO research if there is a difference. + +// 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 = 2.38 + icon_connect_type = "-scrubbers" + if(PIPING_LAYER_SUPPLY) + icon_state = "[icon_state]-supply" + connect_types = CONNECT_TYPE_SUPPLY + layer = 2.39 + icon_connect_type = "-supply" + if(pipe_flags & PIPING_ALL_LAYER) + connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER + // 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) diff --git a/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm b/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm index 1429b9b30a..adafb2ed17 100644 --- a/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm +++ b/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm @@ -14,6 +14,7 @@ idle_power_usage = 100 // Minimal lights to keep algae alive active_power_usage = 5000 // Powerful grow lights to stimulate oxygen production //power_rating = 7500 //7500 W ~ 10 HP + pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF var/list/stored_material = list(MATERIAL_ALGAE = 0, MATERIAL_CARBON = 0) // Capacity increases with matter bin quality diff --git a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm index 6e6662f39c..4698c613a9 100644 --- a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm +++ b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm @@ -30,6 +30,9 @@ initialize_directions = EAST|WEST // Housekeeping and pipe network stuff below +/obj/machinery/atmospherics/binary/get_neighbor_nodes_for_init() + return list(node1, node2) + /obj/machinery/atmospherics/binary/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) if(reference == node1) network1 = new_network @@ -64,17 +67,8 @@ var/node2_connect = dir var/node1_connect = turn(dir, 180) - for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node1 = target - break - - for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node2 = target - break + STANDARD_ATMOS_CHOOSE_NODE(1, node1_connect) + STANDARD_ATMOS_CHOOSE_NODE(2, node2_connect) update_icon() update_underlays() diff --git a/code/ATMOSPHERICS/components/binary_devices/circulator.dm b/code/ATMOSPHERICS/components/binary_devices/circulator.dm index 68ce37d088..ff1089e6f8 100644 --- a/code/ATMOSPHERICS/components/binary_devices/circulator.dm +++ b/code/ATMOSPHERICS/components/binary_devices/circulator.dm @@ -9,6 +9,7 @@ icon = 'icons/obj/pipes.dmi' icon_state = "circ-off" anchored = 0 + pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF var/kinetic_efficiency = 0.04 //combined kinetic and kinetic-to-electric efficiency var/volume_ratio = 0.2 diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm index 840d2bdf8b..d696aad039 100644 --- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm @@ -24,6 +24,7 @@ idle_power_usage = 150 //internal circuitry, friction losses and stuff power_rating = 7500 //7500 W ~ 10 HP + pipe_flags = PIPING_ALL_LAYER connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER //connects to regular, supply and scrubbers pipes var/pump_direction = 1 //0 = siphoning, 1 = releasing diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm index b4f25459c1..c08c82f6b9 100644 --- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm +++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm @@ -5,6 +5,8 @@ /obj/machinery/atmospherics/binary/passive_gate icon = 'icons/atmos/passive_gate.dmi' icon_state = "map" + construction_type = /obj/item/pipe/directional + pipe_state = "passivegate" level = 1 name = "pressure regulator" @@ -257,8 +259,7 @@ "\The [user] unfastens \the [src].", \ "You have unfastened \the [src].", \ "You hear ratchet.") - new /obj/item/pipe(loc, make_from=src) - qdel(src) + deconstruct() #undef REGULATE_NONE #undef REGULATE_INPUT diff --git a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm index b8c7883796..a7127a4dc6 100644 --- a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm +++ b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm @@ -139,6 +139,9 @@ src.set_dir(turn(src.dir, 90)) //Goddamn copypaste from binary base class because atmospherics machinery API is not damn flexible + get_neighbor_nodes_for_init() + return list(node1, node2) + network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) if(reference == node1) network1 = new_network diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm index 6320ddf8a3..a89b1c5659 100644 --- a/code/ATMOSPHERICS/components/binary_devices/pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm @@ -15,6 +15,8 @@ Thus, the two variables affect pump operation are set in New(): /obj/machinery/atmospherics/binary/pump icon = 'icons/atmos/pump.dmi' icon_state = "map_off" + construction_type = /obj/item/pipe/directional + pipe_state = "pump" level = 1 name = "gas pump" @@ -236,5 +238,4 @@ Thus, the two variables affect pump operation are set in New(): "\The [user] unfastens \the [src].", \ "You have unfastened \the [src].", \ "You hear ratchet.") - new /obj/item/pipe(loc, make_from=src) - qdel(src) + deconstruct() diff --git a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm index 42b02282cc..b4493a1566 100644 --- a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm @@ -1,6 +1,8 @@ /obj/machinery/atmospherics/binary/pump/high_power icon = 'icons/atmos/volume_pump.dmi' icon_state = "map_off" + construction_type = /obj/item/pipe/directional + pipe_state = "volumepump" level = 1 name = "high power gas pump" diff --git a/code/ATMOSPHERICS/components/omni_devices/filter.dm b/code/ATMOSPHERICS/components/omni_devices/filter.dm index 8710623dfd..57889c463e 100644 --- a/code/ATMOSPHERICS/components/omni_devices/filter.dm +++ b/code/ATMOSPHERICS/components/omni_devices/filter.dm @@ -4,6 +4,7 @@ /obj/machinery/atmospherics/omni/atmos_filter name = "omni gas filter" icon_state = "map_filter" + pipe_state = "omni_filter" var/list/atmos_filters = new() var/datum/omni_port/input diff --git a/code/ATMOSPHERICS/components/omni_devices/mixer.dm b/code/ATMOSPHERICS/components/omni_devices/mixer.dm index 6340397870..c833b5bb2a 100644 --- a/code/ATMOSPHERICS/components/omni_devices/mixer.dm +++ b/code/ATMOSPHERICS/components/omni_devices/mixer.dm @@ -4,6 +4,7 @@ /obj/machinery/atmospherics/omni/mixer name = "omni gas mixer" icon_state = "map_mixer" + pipe_state = "omni_mixer" use_power = 1 idle_power_usage = 150 //internal circuitry, friction losses and stuff diff --git a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm index a469b4e9ee..0981ff6b44 100644 --- a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm +++ b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm @@ -7,6 +7,7 @@ icon_state = "base" use_power = 1 initialize_directions = 0 + construction_type = /obj/item/pipe/quaternary level = 1 var/configuring = 0 @@ -93,8 +94,7 @@ "\The [user] unfastens \the [src].", \ "You have unfastened \the [src].", \ "You hear a ratchet.") - new /obj/item/pipe(loc, make_from=src) - qdel(src) + deconstruct() /obj/machinery/atmospherics/omni/can_unwrench() var/int_pressure = 0 @@ -222,6 +222,11 @@ // Housekeeping and pipe network stuff below +/obj/machinery/atmospherics/omni/get_neighbor_nodes_for_init() + var/list/neighbor_nodes = list() + for(var/datum/omni_port/P in ports) + neighbor_nodes += P.node + return neighbor_nodes /obj/machinery/atmospherics/omni/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) for(var/datum/omni_port/P in ports) @@ -252,10 +257,9 @@ if(P.node || P.mode == 0) continue for(var/obj/machinery/atmospherics/target in get_step(src, P.dir)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - P.node = target - break + if(can_be_node(target, 1)) + P.node = target + break for(var/datum/omni_port/P in ports) P.update = 1 diff --git a/code/ATMOSPHERICS/components/portables_connector.dm b/code/ATMOSPHERICS/components/portables_connector.dm index 6911288c93..7dca3f52d4 100644 --- a/code/ATMOSPHERICS/components/portables_connector.dm +++ b/code/ATMOSPHERICS/components/portables_connector.dm @@ -7,6 +7,9 @@ dir = SOUTH initialize_directions = SOUTH + construction_type = /obj/item/pipe/directional + pipe_state = "connector" + pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF var/obj/machinery/portable_atmospherics/connected_device @@ -47,6 +50,9 @@ return 1 // Housekeeping and pipe network stuff below +/obj/machinery/atmospherics/portables_connector/get_neighbor_nodes_for_init() + return list(node) + /obj/machinery/atmospherics/portables_connector/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) if(reference == node) network = new_network @@ -77,10 +83,9 @@ var/node_connect = dir for(var/obj/machinery/atmospherics/target in get_step(src,node_connect)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node = target - break + if(can_be_node(target, 1)) + node = target + break update_icon() update_underlays() @@ -146,5 +151,4 @@ "\The [user] unfastens \the [src].", \ "You have unfastened \the [src].", \ "You hear a ratchet.") - new /obj/item/pipe(loc, make_from=src) - qdel(src) + deconstruct() diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm index 94924baedc..49cb05e9af 100755 --- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm @@ -1,6 +1,8 @@ /obj/machinery/atmospherics/trinary/atmos_filter icon = 'icons/atmos/filter.dmi' icon_state = "map" + construction_type = /obj/item/pipe/trinary/flippable + pipe_state = "filter" density = 0 level = 1 diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm index 2a70fe1591..84c5d49daa 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm @@ -1,6 +1,8 @@ /obj/machinery/atmospherics/trinary/mixer icon = 'icons/atmos/mixer.dmi' icon_state = "map" + construction_type = /obj/item/pipe/trinary/flippable + pipe_state = "mixer" density = 0 level = 1 @@ -133,6 +135,8 @@ // obj/machinery/atmospherics/trinary/mixer/t_mixer icon_state = "tmap" + construction_type = /obj/item/pipe/trinary // Can't flip a "T", its symmetrical + pipe_state = "t_mixer" dir = SOUTH initialize_directions = SOUTH|EAST|WEST tee = TRUE diff --git a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm index 79aa77dc6f..0a68f74c71 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm @@ -2,6 +2,7 @@ dir = SOUTH initialize_directions = SOUTH|NORTH|WEST use_power = 0 + pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF var/mirrored = FALSE var/tee = FALSE @@ -64,10 +65,12 @@ "\The [user] unfastens \the [src].", \ "You have unfastened \the [src].", \ "You hear a ratchet.") - new /obj/item/pipe(loc, make_from=src) - qdel(src) + deconstruct() // Housekeeping and pipe network stuff below +/obj/machinery/atmospherics/trinary/get_neighbor_nodes_for_init() + return list(node1, node2, node3) + /obj/machinery/atmospherics/trinary/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) if(reference == node1) network1 = new_network @@ -113,21 +116,9 @@ var/list/node_connects = get_node_connect_dirs() - for(var/obj/machinery/atmospherics/target in get_step(src,node_connects[1])) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node1 = target - break - for(var/obj/machinery/atmospherics/target in get_step(src,node_connects[2])) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node2 = target - break - for(var/obj/machinery/atmospherics/target in get_step(src,node_connects[3])) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node3 = target - break + STANDARD_ATMOS_CHOOSE_NODE(1, node_connects[1]) + STANDARD_ATMOS_CHOOSE_NODE(2, node_connects[2]) + STANDARD_ATMOS_CHOOSE_NODE(3, node_connects[3]) update_icon() update_underlays() diff --git a/code/ATMOSPHERICS/components/tvalve.dm b/code/ATMOSPHERICS/components/tvalve.dm index 2b64d6f5bb..b65c615174 100644 --- a/code/ATMOSPHERICS/components/tvalve.dm +++ b/code/ATMOSPHERICS/components/tvalve.dm @@ -1,6 +1,8 @@ /obj/machinery/atmospherics/tvalve icon = 'icons/atmos/tvalve.dmi' icon_state = "map_tvalve0" + construction_type = /obj/item/pipe/trinary/flippable + pipe_state = "mtvalve" name = "manual switching valve" desc = "A pipe valve" @@ -12,6 +14,7 @@ var/state = 0 // 0 = go straight, 1 = go to side var/mirrored = FALSE + var/tee = FALSE // Note: Tee not actually supported for T-valves: no sprites // like a trinary component, node1 is input, node2 is side output, node3 is straight output var/obj/machinery/atmospherics/node3 @@ -47,6 +50,9 @@ /obj/machinery/atmospherics/tvalve/init_dir() initialize_directions = get_initialize_directions_trinary(dir, mirrored) +/obj/machinery/atmospherics/tvalve/get_neighbor_nodes_for_init() + return list(node1, node2, node3) + /obj/machinery/atmospherics/tvalve/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) if(reference == node1) network_node1 = new_network @@ -178,21 +184,9 @@ var/list/node_connects = get_node_connect_dirs() - for(var/obj/machinery/atmospherics/target in get_step(src,node_connects[1])) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node1 = target - break - for(var/obj/machinery/atmospherics/target in get_step(src,node_connects[2])) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node2 = target - break - for(var/obj/machinery/atmospherics/target in get_step(src,node_connects[3])) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node3 = target - break + STANDARD_ATMOS_CHOOSE_NODE(1, node_connects[1]) + STANDARD_ATMOS_CHOOSE_NODE(2, node_connects[2]) + STANDARD_ATMOS_CHOOSE_NODE(3, node_connects[3]) update_icon() update_underlays() @@ -262,6 +256,7 @@ name = "digital switching valve" desc = "A digitally controlled valve." icon = 'icons/atmos/digital_tvalve.dmi' + pipe_state = "dtvalve" var/frequency = 0 var/id = null @@ -348,8 +343,7 @@ "\The [user] unfastens \the [src].", \ "You have unfastened \the [src].", \ "You hear a ratchet.") - new /obj/item/pipe(loc, make_from=src) - qdel(src) + deconstruct() /obj/machinery/atmospherics/tvalve/mirrored icon_state = "map_tvalvem0" diff --git a/code/ATMOSPHERICS/components/unary/cold_sink.dm b/code/ATMOSPHERICS/components/unary/cold_sink.dm index 5759c39dcf..07b0052910 100644 --- a/code/ATMOSPHERICS/components/unary/cold_sink.dm +++ b/code/ATMOSPHERICS/components/unary/cold_sink.dm @@ -38,18 +38,15 @@ var/node_connect = dir for(var/obj/machinery/atmospherics/target in get_step(src, node_connect)) - if(target.initialize_directions & get_dir(target, src)) + if(can_be_node(target, 1)) node = target break - //copied from pipe construction code since heaters/freezers don't use fittings and weren't doing this check - this all really really needs to be refactored someday. - //check that there are no incompatible pipes/machinery in our own location - for(var/obj/machinery/atmospherics/M in src.loc) - if(M != src && (M.initialize_directions & node_connect) && M.check_connect_types(M,src)) // matches at least one direction on either type of pipe & same connection type - node = null - break + if(check_for_obstacles()) + node = null - update_icon() + if(node) + update_icon() /obj/machinery/atmospherics/unary/freezer/update_icon() if(node) diff --git a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm index 8a7fba153a..ed4010f81e 100644 --- a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm +++ b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm @@ -2,6 +2,7 @@ icon = 'icons/obj/atmospherics/heat_exchanger.dmi' icon_state = "intact" + pipe_state = "heunary" density = 1 name = "Heat Exchanger" @@ -83,5 +84,4 @@ "\The [user] unfastens \the [src].", \ "You have unfastened \the [src].", \ "You hear a ratchet.") - new /obj/item/pipe(loc, make_from=src) - qdel(src) + deconstruct() diff --git a/code/ATMOSPHERICS/components/unary/heat_source.dm b/code/ATMOSPHERICS/components/unary/heat_source.dm index a1e933b96a..bc1aaae118 100644 --- a/code/ATMOSPHERICS/components/unary/heat_source.dm +++ b/code/ATMOSPHERICS/components/unary/heat_source.dm @@ -39,18 +39,15 @@ //check that there is something to connect to for(var/obj/machinery/atmospherics/target in get_step(src, node_connect)) - if(target.initialize_directions & get_dir(target, src)) + if(can_be_node(target, 1)) node = target break - //copied from pipe construction code since heaters/freezers don't use fittings and weren't doing this check - this all really really needs to be refactored someday. - //check that there are no incompatible pipes/machinery in our own location - for(var/obj/machinery/atmospherics/M in src.loc) - if(M != src && (M.initialize_directions & node_connect) && M.check_connect_types(M,src)) // matches at least one direction on either type of pipe & same connection type - node = null - break + if(check_for_obstacles()) + node = null - update_icon() + if(node) + update_icon() /obj/machinery/atmospherics/unary/heater/update_icon() diff --git a/code/ATMOSPHERICS/components/unary/outlet_injector.dm b/code/ATMOSPHERICS/components/unary/outlet_injector.dm index 7c52cea895..9d980647a8 100644 --- a/code/ATMOSPHERICS/components/unary/outlet_injector.dm +++ b/code/ATMOSPHERICS/components/unary/outlet_injector.dm @@ -5,6 +5,7 @@ /obj/machinery/atmospherics/unary/outlet_injector icon = 'icons/atmos/injector.dmi' icon_state = "map_injector" + pipe_state = "injector" layer = 3 name = "air injector" diff --git a/code/ATMOSPHERICS/components/unary/unary_base.dm b/code/ATMOSPHERICS/components/unary/unary_base.dm index 77b135cdc5..db395ad6fc 100644 --- a/code/ATMOSPHERICS/components/unary/unary_base.dm +++ b/code/ATMOSPHERICS/components/unary/unary_base.dm @@ -1,6 +1,8 @@ /obj/machinery/atmospherics/unary dir = SOUTH initialize_directions = SOUTH + construction_type = /obj/item/pipe/directional + pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF //layer = TURF_LAYER+0.1 var/datum/gas_mixture/air_contents @@ -21,6 +23,9 @@ initialize_directions = dir // Housekeeping and pipe network stuff below +/obj/machinery/atmospherics/unary/get_neighbor_nodes_for_init() + return list(node) + /obj/machinery/atmospherics/unary/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) if(reference == node) network = new_network @@ -48,10 +53,9 @@ var/node_connect = dir for(var/obj/machinery/atmospherics/target in get_step(src,node_connect)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node = target - break + if(can_be_node(target, 1)) + node = target + break update_icon() update_underlays() @@ -93,4 +97,19 @@ update_icon() update_underlays() - return null \ No newline at end of file + return null + +// Check if there are any other atmos machines in the same turf that will block this machine from initializing. +// Intended for use when a frame-constructable machine (i.e. not made from pipe fittings) wants to wrench down and connect. +// Returns TRUE if something is blocking, FALSE if its okay to continue. +/obj/machinery/atmospherics/unary/proc/check_for_obstacles() + for(var/obj/machinery/atmospherics/M in loc) + if((M.pipe_flags & pipe_flags & PIPING_ONE_PER_TURF)) //Only one dense/requires density object per tile, eg connectors/cryo/heater/coolers. + visible_message("\The [src]'s cannot be connected, something is hogging the tile!") + return TRUE + if((M.piping_layer != piping_layer) && !((M.pipe_flags | flags) & PIPING_ALL_LAYER)) // Pipes on different layers can't block each other unless they are ALL_LAYER + continue + if(M.get_init_dirs() & get_init_dirs()) // matches at least one direction on either type of pipe + visible_message("\The [src]'s connector can't be connected, there is already a pipe at that location!") + return TRUE + return FALSE diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm index 17da4afcf7..9338516343 100644 --- a/code/ATMOSPHERICS/components/unary/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm @@ -10,6 +10,7 @@ /obj/machinery/atmospherics/unary/vent_pump icon = 'icons/atmos/vent_pump.dmi' icon_state = "map_vent" + pipe_state = "uvent" name = "Air Vent" desc = "Has a valve and pump attached to it" @@ -426,8 +427,7 @@ "\The [user] unfastens \the [src].", \ "You have unfastened \the [src].", \ "You hear a ratchet.") - new /obj/item/pipe(loc, make_from=src) - qdel(src) + deconstruct() #undef DEFAULT_PRESSURE_DELTA diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm index ad78f5a1f4..09b5fde7c1 100644 --- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm @@ -1,6 +1,7 @@ /obj/machinery/atmospherics/unary/vent_scrubber icon = 'icons/atmos/vent_scrubber.dmi' icon_state = "map_scrubber_off" + pipe_state = "scrubber" name = "Air Scrubber" desc = "Has a valve and pump attached to it" @@ -283,8 +284,7 @@ "\The [user] unfastens \the [src].", \ "You have unfastened \the [src].", \ "You hear a ratchet.") - new /obj/item/pipe(loc, make_from=src) - qdel(src) + deconstruct() /obj/machinery/atmospherics/unary/vent_scrubber/examine(mob/user) if(..(user, 1)) diff --git a/code/ATMOSPHERICS/components/valve.dm b/code/ATMOSPHERICS/components/valve.dm index 77aedf94e0..93e5da7c32 100644 --- a/code/ATMOSPHERICS/components/valve.dm +++ b/code/ATMOSPHERICS/components/valve.dm @@ -1,6 +1,8 @@ /obj/machinery/atmospherics/valve icon = 'icons/atmos/valve.dmi' icon_state = "map_valve0" + construction_type = /obj/item/pipe/binary + pipe_state = "mvalve" name = "manual valve" desc = "A pipe valve" @@ -45,6 +47,9 @@ if(EAST || WEST) initialize_directions = EAST|WEST +/obj/machinery/atmospherics/valve/get_neighbor_nodes_for_init() + return list(node1, node2) + /obj/machinery/atmospherics/valve/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) if(reference == node1) network_node1 = new_network @@ -153,16 +158,8 @@ else if (!node2_dir) node2_dir = direction - for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node1 = target - break - for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node2 = target - break + STANDARD_ATMOS_CHOOSE_NODE(1, node1_dir) + STANDARD_ATMOS_CHOOSE_NODE(2, node2_dir) build_network() @@ -224,6 +221,7 @@ name = "digital valve" desc = "A digitally controlled valve." icon = 'icons/atmos/digital_valve.dmi' + pipe_state = "dvalve" var/frequency = 0 var/id = null @@ -306,8 +304,7 @@ "\The [user] unfastens \the [src].", \ "You have unfastened \the [src].", \ "You hear a ratchet.") - new /obj/item/pipe(loc, make_from=src) - qdel(src) + deconstruct() /obj/machinery/atmospherics/valve/examine(mob/user) ..() diff --git a/code/ATMOSPHERICS/mainspipe.dm b/code/ATMOSPHERICS/mainspipe.dm index 1b0c617564..a38587baf5 100644 --- a/code/ATMOSPHERICS/mainspipe.dm +++ b/code/ATMOSPHERICS/mainspipe.dm @@ -92,6 +92,9 @@ obj/machinery/atmospherics/mains_pipe else return 1 + get_neighbor_nodes_for_init() + return nodes + disconnect() ..() for(var/obj/machinery/atmospherics/pipe/mains_component/node in nodes) diff --git a/code/ATMOSPHERICS/pipes/cap.dm b/code/ATMOSPHERICS/pipes/cap.dm index de81c60200..8e56319d69 100644 --- a/code/ATMOSPHERICS/pipes/cap.dm +++ b/code/ATMOSPHERICS/pipes/cap.dm @@ -14,6 +14,9 @@ dir = SOUTH initialize_directions = SOUTH + construction_type = /obj/item/pipe/directional + pipe_state = "cap" + var/obj/machinery/atmospherics/node /obj/machinery/atmospherics/pipe/cap/init_dir() @@ -56,10 +59,9 @@ /obj/machinery/atmospherics/pipe/cap/atmos_init() for(var/obj/machinery/atmospherics/target in get_step(src, dir)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node = target - break + if (can_be_node(target, 1)) + node = target + break var/turf/T = src.loc // hide if turf is not intact if(level == 1 && !T.is_plating()) hide(1) diff --git a/code/ATMOSPHERICS/pipes/he_pipes.dm b/code/ATMOSPHERICS/pipes/he_pipes.dm index 8953739a9c..fe6580b1ce 100644 --- a/code/ATMOSPHERICS/pipes/he_pipes.dm +++ b/code/ATMOSPHERICS/pipes/he_pipes.dm @@ -8,6 +8,10 @@ color = "#404040" level = 2 connect_types = CONNECT_TYPE_HE + pipe_flags = PIPING_DEFAULT_LAYER_ONLY + construction_type = /obj/item/pipe/binary/bendable + pipe_state = "he" + layer = 2.41 var/initialize_directions_he var/surface = 2 //surface area in m^2 @@ -27,6 +31,16 @@ /obj/machinery/atmospherics/pipe/simple/heat_exchanging/init_dir() ..() initialize_directions_he = initialize_directions // The auto-detection from /pipe is good enough for a simple HE pipe + initialize_directions = 0 + +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/get_init_dirs() + return ..() | initialize_directions_he + +// Use initialize_directions_he to connect to neighbors instead. +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/can_be_node(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target) + if(!istype(target)) + return FALSE + return (target.initialize_directions_he & get_dir(target,src)) && check_connectable(target) && target.check_connectable(src) /obj/machinery/atmospherics/pipe/simple/heat_exchanging/atmos_init() normalize_dir() @@ -41,11 +55,11 @@ node2_dir = direction for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,node1_dir)) - if(target.initialize_directions_he & get_dir(target,src)) + if(can_be_node(target, 1)) node1 = target break for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,node2_dir)) - if(target.initialize_directions_he & get_dir(target,src)) + if(can_be_node(target, 2)) node2 = target break if(!node1 && !node2) @@ -117,6 +131,8 @@ pipe_icon = "hejunction" level = 2 connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_HE + construction_type = /obj/item/pipe/directional + pipe_state = "junction" minimum_temperature_difference = 300 thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT @@ -136,6 +152,18 @@ initialize_directions = EAST initialize_directions_he = WEST + // Allow ourselves to make connections to either HE or normal pipes depending on which node we are doing. +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/can_be_node(obj/machinery/atmospherics/target, node_num) + var/target_initialize_directions + switch(node_num) + if(1) + target_initialize_directions = target.initialize_directions // Node1 is towards normal pipes + if(2) + var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/H = target + if(!istype(H)) + return FALSE + target_initialize_directions = H.initialize_directions_he // Node2 is towards HE pies. + return (target_initialize_directions & get_dir(target,src)) && check_connectable(target) && target.check_connectable(src) /obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/atmos_init() for(var/obj/machinery/atmospherics/target in get_step(src,initialize_directions)) diff --git a/code/ATMOSPHERICS/pipes/manifold.dm b/code/ATMOSPHERICS/pipes/manifold.dm index 1b9afd9c63..8df3b4326a 100644 --- a/code/ATMOSPHERICS/pipes/manifold.dm +++ b/code/ATMOSPHERICS/pipes/manifold.dm @@ -12,6 +12,9 @@ dir = SOUTH initialize_directions = EAST|NORTH|WEST + construction_type = /obj/item/pipe/trinary + pipe_state = "manifold" + var/obj/machinery/atmospherics/node3 level = 1 @@ -116,11 +119,10 @@ for(var/direction in cardinal) if(direction&connect_directions) for(var/obj/machinery/atmospherics/target in get_step(src,direction)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node1 = target - connect_directions &= ~direction - break + if (can_be_node(target, 1)) + node1 = target + connect_directions &= ~direction + break if (node1) break @@ -128,11 +130,10 @@ for(var/direction in cardinal) if(direction&connect_directions) for(var/obj/machinery/atmospherics/target in get_step(src,direction)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node2 = target - connect_directions &= ~direction - break + if (can_be_node(target, 2)) + node2 = target + connect_directions &= ~direction + break if (node2) break @@ -140,11 +141,10 @@ for(var/direction in cardinal) if(direction&connect_directions) for(var/obj/machinery/atmospherics/target in get_step(src,direction)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node3 = target - connect_directions &= ~direction - break + if (can_be_node(target, 3)) + node3 = target + connect_directions &= ~direction + break if (node3) break diff --git a/code/ATMOSPHERICS/pipes/manifold4w.dm b/code/ATMOSPHERICS/pipes/manifold4w.dm index ba360eefd8..1bd556b3fb 100644 --- a/code/ATMOSPHERICS/pipes/manifold4w.dm +++ b/code/ATMOSPHERICS/pipes/manifold4w.dm @@ -12,6 +12,9 @@ dir = SOUTH initialize_directions = NORTH|SOUTH|EAST|WEST + construction_type = /obj/item/pipe/quaternary + pipe_state = "manifold4w" + var/obj/machinery/atmospherics/node3 var/obj/machinery/atmospherics/node4 @@ -127,29 +130,25 @@ /obj/machinery/atmospherics/pipe/manifold4w/atmos_init() - for(var/obj/machinery/atmospherics/target in get_step(src,1)) - if(target.initialize_directions & 2) - if (check_connect_types(target,src)) - node1 = target - break + for(var/obj/machinery/atmospherics/target in get_step(src, NORTH)) + if (can_be_node(target, 1)) + node1 = target + break - for(var/obj/machinery/atmospherics/target in get_step(src,2)) - if(target.initialize_directions & 1) - if (check_connect_types(target,src)) - node2 = target - break + for(var/obj/machinery/atmospherics/target in get_step(src, SOUTH)) + if (can_be_node(target, 2)) + node2 = target + break - for(var/obj/machinery/atmospherics/target in get_step(src,4)) - if(target.initialize_directions & 8) - if (check_connect_types(target,src)) - node3 = target - break + for(var/obj/machinery/atmospherics/target in get_step(src, EAST)) + if (can_be_node(target, 3)) + node3 = target + break - for(var/obj/machinery/atmospherics/target in get_step(src,8)) - if(target.initialize_directions & 4) - if (check_connect_types(target,src)) - node4 = target - break + for(var/obj/machinery/atmospherics/target in get_step(src, WEST)) + if (can_be_node(target, 4)) + node4 = target + break if(!node1 && !node2 && !node3 && !node4) qdel(src) diff --git a/code/ATMOSPHERICS/pipes/pipe_base.dm b/code/ATMOSPHERICS/pipes/pipe_base.dm index 94167e01f6..4e852ed0c8 100644 --- a/code/ATMOSPHERICS/pipes/pipe_base.dm +++ b/code/ATMOSPHERICS/pipes/pipe_base.dm @@ -10,6 +10,8 @@ layer = 2.4 //under wires with their 2.44 use_power = 0 + pipe_flags = 0 // Does not have PIPING_DEFAULT_LAYER_ONLY flag. + var/alert_pressure = 80*ONE_ATMOSPHERE //minimum pressure before check_pressure(...) should be called @@ -31,6 +33,10 @@ /obj/machinery/atmospherics/pipe/proc/pipeline_expansion() return null +// For pipes this is the same as pipeline_expansion() +/obj/machinery/atmospherics/pipe/get_neighbor_nodes_for_init() + return pipeline_expansion() + /obj/machinery/atmospherics/pipe/proc/check_pressure(pressure) //Return 1 if parent should continue checking other pipes //Return null if parent should stop checking other pipes. Recall: qdel(src) will by default return null @@ -69,7 +75,11 @@ qdel_null(parent) if(air_temporary) loc.assume_air(air_temporary) - + for(var/obj/machinery/meter/meter in loc) + if(meter.target == src) + var/obj/item/pipe_meter/PM = new /obj/item/pipe_meter(loc) + meter.transfer_fingerprints_to(PM) + qdel(meter) . = ..() /obj/machinery/atmospherics/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) @@ -96,12 +106,7 @@ "\The [user] unfastens \the [src].", \ "You have unfastened \the [src].", \ "You hear a ratchet.") - new /obj/item/pipe(loc, make_from=src) - for (var/obj/machinery/meter/meter in T) - if (meter.target == src) - new /obj/item/pipe_meter(T) - qdel(meter) - qdel(src) + deconstruct() /obj/machinery/atmospherics/pipe/proc/change_color(var/new_color) //only pass valid pipe colors please ~otherwise your pipe will turn invisible diff --git a/code/ATMOSPHERICS/pipes/simple.dm b/code/ATMOSPHERICS/pipes/simple.dm index f676c1ac38..289e8b4274 100644 --- a/code/ATMOSPHERICS/pipes/simple.dm +++ b/code/ATMOSPHERICS/pipes/simple.dm @@ -13,6 +13,10 @@ dir = SOUTH initialize_directions = SOUTH|NORTH + pipe_flags = PIPING_CARDINAL_AUTONORMALIZE + construction_type = /obj/item/pipe/binary/bendable + pipe_state = "simple" + var/minimum_temperature_difference = 300 var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No @@ -47,9 +51,13 @@ /obj/machinery/atmospherics/pipe/simple/init_dir() switch(dir) - if(SOUTH || NORTH) + if(SOUTH) initialize_directions = SOUTH|NORTH - if(EAST || WEST) + if(NORTH) + initialize_directions = SOUTH|NORTH + if(EAST) + initialize_directions = EAST|WEST + if(WEST) initialize_directions = EAST|WEST if(NORTHEAST) initialize_directions = NORTH|EAST @@ -124,15 +132,13 @@ node2_dir = direction for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node1 = target - break + if(can_be_node(target, 1)) + node1 = target + break for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node2 = target - break + if(can_be_node(target, 2)) + node2 = target + break if(!node1 && !node2) qdel(src) @@ -248,6 +254,9 @@ icon = 'icons/obj/atmospherics/red_pipe.dmi' icon_state = "intact" + construction_type = /obj/item/pipe/binary/bendable + pipe_state = "insulated" + minimum_temperature_difference = 10000 thermal_conductivity = 0 maximum_pressure = 1000*ONE_ATMOSPHERE diff --git a/code/ATMOSPHERICS/pipes/tank.dm b/code/ATMOSPHERICS/pipes/tank.dm index 07ce8d5b71..c96f4ddf1d 100644 --- a/code/ATMOSPHERICS/pipes/tank.dm +++ b/code/ATMOSPHERICS/pipes/tank.dm @@ -14,6 +14,7 @@ level = 1 dir = SOUTH initialize_directions = SOUTH + pipe_flags = PIPING_DEFAULT_LAYER_ONLY density = 1 /obj/machinery/atmospherics/pipe/tank/New() @@ -48,10 +49,9 @@ var/connect_direction = dir for(var/obj/machinery/atmospherics/target in get_step(src,connect_direction)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node1 = target - break + if (can_be_node(target, 1)) + node1 = target + break update_underlays() diff --git a/code/ATMOSPHERICS/pipes/universal.dm b/code/ATMOSPHERICS/pipes/universal.dm index 1017751aa1..2d8bd09dff 100644 --- a/code/ATMOSPHERICS/pipes/universal.dm +++ b/code/ATMOSPHERICS/pipes/universal.dm @@ -6,6 +6,9 @@ desc = "An adapter for regular, supply and scrubbers pipes" connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER icon_state = "map_universal" + pipe_flags = PIPING_ALL_LAYER|PIPING_CARDINAL_AUTONORMALIZE + construction_type = /obj/item/pipe/binary + pipe_state = "universal" /obj/machinery/atmospherics/pipe/simple/visible/universal/update_icon(var/safety = 0) if(!check_icon_cache()) @@ -28,7 +31,7 @@ universal_underlays(node2) else universal_underlays(,dir) - universal_underlays(dir, -180) + universal_underlays(,turn(dir, -180)) /obj/machinery/atmospherics/pipe/simple/visible/universal/update_underlays() ..() @@ -41,6 +44,9 @@ desc = "An adapter for regular, supply and scrubbers pipes" connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER icon_state = "map_universal" + pipe_flags = PIPING_ALL_LAYER|PIPING_CARDINAL_AUTONORMALIZE + construction_type = /obj/item/pipe/binary + pipe_state = "universal" /obj/machinery/atmospherics/pipe/simple/hidden/universal/update_icon(var/safety = 0) if(!check_icon_cache()) diff --git a/code/ATMOSPHERICS/pipes/vent.dm b/code/ATMOSPHERICS/pipes/vent.dm index 74eebb29a1..4a1dc5696d 100644 --- a/code/ATMOSPHERICS/pipes/vent.dm +++ b/code/ATMOSPHERICS/pipes/vent.dm @@ -14,6 +14,9 @@ dir = SOUTH initialize_directions = SOUTH + pipe_flags = PIPING_DEFAULT_LAYER_ONLY + construction_type = /obj/item/pipe/directional + pipe_state = "passive vent" var/build_killswitch = 1 @@ -58,10 +61,9 @@ var/connect_direction = dir for(var/obj/machinery/atmospherics/target in get_step(src,connect_direction)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node1 = target - break + if (can_be_node(target, 1)) + node1 = target + break update_icon() diff --git a/code/__defines/construction.dm b/code/__defines/construction.dm index 7aceb1ffc4..837ad7ed38 100644 --- a/code/__defines/construction.dm +++ b/code/__defines/construction.dm @@ -1,4 +1,6 @@ - +// +// Frame construction +// // Frame construction states #define FRAME_PLACED 0 // Has been placed (can be anchored or not). @@ -16,3 +18,44 @@ // Does the frame get built on the floor or a wall? #define FRAME_STYLE_FLOOR "floor" #define FRAME_STYLE_WALL "wall" + +// +// Pipe Construction +// + +//Construction Orientation Types - Each of these categories has a different selection of how pipes can rotate and flip. Used for RPD. +#define PIPE_STRAIGHT 0 //2 directions: N/S, E/W +#define PIPE_BENDABLE 1 //6 directions: N/S, E/W, N/E, N/W, S/E, S/W +#define PIPE_TRINARY 2 //4 directions: N/E/S, E/S/W, S/W/N, W/N/E +#define PIPE_TRIN_M 3 //8 directions: N->S+E, S->N+E, N->S+W, S->N+W, E->W+S, W->E+S, E->W+N, W->E+N +#define PIPE_DIRECTIONAL 4 //4 directions: N, S, E, W +#define PIPE_ONEDIR 5 //1 direction: N/S/E/W +#define PIPE_UNARY_FLIPPABLE 6 //8 directions: N, S, E, W, N-flipped, S-flipped, E-flipped, W-flipped +#define PIPE_TRIN_T 7 //8 directions: N->S+E, S->N+E, N->S+W, S->N+W, E->W+S, W->E+S, E->W+N, W->E+N + +// Pipe connectivity bit flags +#define CONNECT_TYPE_REGULAR 1 +#define CONNECT_TYPE_SUPPLY 2 +#define CONNECT_TYPE_SCRUBBER 4 +#define CONNECT_TYPE_HE 8 + +// We are based on the three named layers of supply, regular, and scrubber. +#define PIPING_LAYER_SUPPLY 1 +#define PIPING_LAYER_REGULAR 2 +#define PIPING_LAYER_SCRUBBER 3 +#define PIPING_LAYER_DEFAULT PIPING_LAYER_REGULAR + +// Pipe flags +#define PIPING_ALL_LAYER 1 //intended to connect with all layers, check for all instead of just one. +#define PIPING_ONE_PER_TURF 2 //can only be built if nothing else with this flag is on the tile already. +#define PIPING_DEFAULT_LAYER_ONLY 4 //can only exist at PIPING_LAYER_DEFAULT +#define PIPING_CARDINAL_AUTONORMALIZE 8 //north/south east/west doesn't matter, auto normalize on build. + +// Macro for easy use of boilerplate code for searching for a valid node connection. +#define STANDARD_ATMOS_CHOOSE_NODE(node_num, direction) \ + for(var/obj/machinery/atmospherics/target in get_step(src, direction)) { \ + if(can_be_node(target, node_num)) { \ + node##node_num = target; \ + break; \ + } \ + } diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index f03e56e642..9c67a9bc5d 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -2,1317 +2,273 @@ Buildable pipes Buildable meters */ -#define PIPE_SIMPLE_STRAIGHT 0 -#define PIPE_SIMPLE_BENT 1 -#define PIPE_HE_STRAIGHT 2 -#define PIPE_HE_BENT 3 -#define PIPE_CONNECTOR 4 -#define PIPE_MANIFOLD 5 -#define PIPE_JUNCTION 6 -#define PIPE_UVENT 7 -#define PIPE_MVALVE 8 -#define PIPE_PUMP 9 -#define PIPE_SCRUBBER 10 -#define PIPE_INSULATED_STRAIGHT 11 -#define PIPE_INSULATED_BENT 12 -#define PIPE_GAS_FILTER 13 -#define PIPE_GAS_MIXER 14 -#define PIPE_PASSIVE_GATE 15 -#define PIPE_VOLUME_PUMP 16 -#define PIPE_HEAT_EXCHANGE 17 -#define PIPE_MTVALVE 18 -#define PIPE_MANIFOLD4W 19 -#define PIPE_CAP 20 -///// Z-Level stuff -#define PIPE_UP 21 -#define PIPE_DOWN 22 -///// Z-Level stuff -#define PIPE_GAS_FILTER_M 23 -#define PIPE_GAS_MIXER_T 24 -#define PIPE_GAS_MIXER_M 25 -#define PIPE_OMNI_MIXER 26 -#define PIPE_OMNI_FILTER 27 -///// Supply, scrubbers and universal pipes -#define PIPE_UNIVERSAL 28 -#define PIPE_SUPPLY_STRAIGHT 29 -#define PIPE_SUPPLY_BENT 30 -#define PIPE_SCRUBBERS_STRAIGHT 31 -#define PIPE_SCRUBBERS_BENT 32 -#define PIPE_SUPPLY_MANIFOLD 33 -#define PIPE_SCRUBBERS_MANIFOLD 34 -#define PIPE_SUPPLY_MANIFOLD4W 35 -#define PIPE_SCRUBBERS_MANIFOLD4W 36 -#define PIPE_SUPPLY_UP 37 -#define PIPE_SCRUBBERS_UP 38 -#define PIPE_SUPPLY_DOWN 39 -#define PIPE_SCRUBBERS_DOWN 40 -#define PIPE_SUPPLY_CAP 41 -#define PIPE_SCRUBBERS_CAP 42 -///// Mirrored T-valve ~ because I couldn't be bothered re-sorting all of the defines -#define PIPE_MTVALVEM 43 -///// Digital Valves sit here because otherwise we're resorting every define. -#define PIPE_DVALVE 44 -#define PIPE_DTVALVE 45 -#define PIPE_DTVALVEM 46 - -#define PIPE_PASSIVE_VENT 47 /obj/item/pipe name = "pipe" - desc = "A pipe" - var/pipe_type = 0 - //var/pipe_dir = 0 + desc = "A pipe." + var/pipe_type var/pipename - var/connect_types = CONNECT_TYPE_REGULAR force = 7 + throwforce = 7 icon = 'icons/obj/pipe-item.dmi' icon_state = "simple" item_state = "buildpipe" w_class = ITEMSIZE_NORMAL level = 2 + var/piping_layer = PIPING_LAYER_DEFAULT + var/dispenser_class // Tells the dispenser what orientations we support, so RPD can show previews. -/obj/item/pipe/New(var/loc, var/pipe_type as num, var/dir as num, var/obj/machinery/atmospherics/make_from = null) - ..() - if (make_from) - src.set_dir(make_from.dir) - src.pipename = make_from.name - if(make_from.req_access) - src.req_access = make_from.req_access - if(make_from.req_one_access) - src.req_one_access = make_from.req_one_access - color = make_from.pipe_color - var/is_bent - if (make_from.initialize_directions in list(NORTH|SOUTH, WEST|EAST)) - is_bent = 0 - else - is_bent = 1 - if (istype(make_from, /obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction)) - src.pipe_type = PIPE_JUNCTION - connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_HE - else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple/heat_exchanging)) - src.pipe_type = PIPE_HE_STRAIGHT + is_bent - connect_types = CONNECT_TYPE_HE - else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple/insulated)) - src.pipe_type = PIPE_INSULATED_STRAIGHT + is_bent - else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple/visible/supply) || istype(make_from, /obj/machinery/atmospherics/pipe/simple/hidden/supply)) - src.pipe_type = PIPE_SUPPLY_STRAIGHT + is_bent - connect_types = CONNECT_TYPE_SUPPLY - src.color = PIPE_COLOR_BLUE - else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple/visible/scrubbers) || istype(make_from, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers)) - src.pipe_type = PIPE_SCRUBBERS_STRAIGHT + is_bent - connect_types = CONNECT_TYPE_SCRUBBER - src.color = PIPE_COLOR_RED - else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple/visible/universal) || istype(make_from, /obj/machinery/atmospherics/pipe/simple/hidden/universal)) - src.pipe_type = PIPE_UNIVERSAL - connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER - else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple)) - src.pipe_type = PIPE_SIMPLE_STRAIGHT + is_bent - else if(istype(make_from, /obj/machinery/atmospherics/portables_connector)) - src.pipe_type = PIPE_CONNECTOR - else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold/visible/supply) || istype(make_from, /obj/machinery/atmospherics/pipe/manifold/hidden/supply)) - src.pipe_type = PIPE_SUPPLY_MANIFOLD - connect_types = CONNECT_TYPE_SUPPLY - src.color = PIPE_COLOR_BLUE - else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold/visible/scrubbers) || istype(make_from, /obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers)) - src.pipe_type = PIPE_SCRUBBERS_MANIFOLD - connect_types = CONNECT_TYPE_SCRUBBER - src.color = PIPE_COLOR_RED - else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold)) - src.pipe_type = PIPE_MANIFOLD - else if(istype(make_from, /obj/machinery/atmospherics/unary/vent_pump)) - src.pipe_type = PIPE_UVENT - else if(istype(make_from, /obj/machinery/atmospherics/valve/digital)) - src.pipe_type = PIPE_DVALVE - else if(istype(make_from, /obj/machinery/atmospherics/valve)) - src.pipe_type = PIPE_MVALVE - else if(istype(make_from, /obj/machinery/atmospherics/binary/pump/high_power)) - src.pipe_type = PIPE_VOLUME_PUMP - else if(istype(make_from, /obj/machinery/atmospherics/binary/pump)) - src.pipe_type = PIPE_PUMP - else if(istype(make_from, /obj/machinery/atmospherics/trinary/atmos_filter/m_filter)) - src.pipe_type = PIPE_GAS_FILTER_M - else if(istype(make_from, /obj/machinery/atmospherics/trinary/mixer/t_mixer)) - src.pipe_type = PIPE_GAS_MIXER_T - else if(istype(make_from, /obj/machinery/atmospherics/trinary/mixer/m_mixer)) - src.pipe_type = PIPE_GAS_MIXER_M - else if(istype(make_from, /obj/machinery/atmospherics/trinary/atmos_filter)) - src.pipe_type = PIPE_GAS_FILTER - else if(istype(make_from, /obj/machinery/atmospherics/trinary/mixer)) - src.pipe_type = PIPE_GAS_MIXER - else if(istype(make_from, /obj/machinery/atmospherics/unary/vent_scrubber)) - src.pipe_type = PIPE_SCRUBBER - else if(istype(make_from, /obj/machinery/atmospherics/binary/passive_gate)) - src.pipe_type = PIPE_PASSIVE_GATE - else if(istype(make_from, /obj/machinery/atmospherics/unary/heat_exchanger)) - src.pipe_type = PIPE_HEAT_EXCHANGE - else if(istype(make_from, /obj/machinery/atmospherics/tvalve/digital/mirrored)) - src.pipe_type = PIPE_DTVALVEM - else if(istype(make_from, /obj/machinery/atmospherics/tvalve/mirrored)) - src.pipe_type = PIPE_MTVALVEM - else if(istype(make_from, /obj/machinery/atmospherics/tvalve/digital)) - src.pipe_type = PIPE_DTVALVE - else if(istype(make_from, /obj/machinery/atmospherics/tvalve)) - src.pipe_type = PIPE_MTVALVE - else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold4w/visible/supply) || istype(make_from, /obj/machinery/atmospherics/pipe/manifold4w/hidden/supply)) - src.pipe_type = PIPE_SUPPLY_MANIFOLD4W - connect_types = CONNECT_TYPE_SUPPLY - src.color = PIPE_COLOR_BLUE - else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold4w/visible/scrubbers) || istype(make_from, /obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers)) - src.pipe_type = PIPE_SCRUBBERS_MANIFOLD4W - connect_types = CONNECT_TYPE_SCRUBBER - src.color = PIPE_COLOR_RED - else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold4w)) - src.pipe_type = PIPE_MANIFOLD4W - else if(istype(make_from, /obj/machinery/atmospherics/pipe/cap/visible/supply) || istype(make_from, /obj/machinery/atmospherics/pipe/cap/hidden/supply)) - src.pipe_type = PIPE_SUPPLY_CAP - connect_types = CONNECT_TYPE_SUPPLY - src.color = PIPE_COLOR_BLUE - else if(istype(make_from, /obj/machinery/atmospherics/pipe/cap/visible/scrubbers) || istype(make_from, /obj/machinery/atmospherics/pipe/cap/hidden/scrubbers)) - src.pipe_type = PIPE_SCRUBBERS_CAP - connect_types = CONNECT_TYPE_SCRUBBER - src.color = PIPE_COLOR_RED - else if(istype(make_from, /obj/machinery/atmospherics/pipe/cap)) - src.pipe_type = PIPE_CAP - else if(istype(make_from, /obj/machinery/atmospherics/omni/mixer)) - src.pipe_type = PIPE_OMNI_MIXER - else if(istype(make_from, /obj/machinery/atmospherics/omni/atmos_filter)) - src.pipe_type = PIPE_OMNI_FILTER -///// Z-Level stuff - else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/up/supply)) - src.pipe_type = PIPE_SUPPLY_UP - connect_types = CONNECT_TYPE_SUPPLY - src.color = PIPE_COLOR_BLUE - else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/up/scrubbers)) - src.pipe_type = PIPE_SCRUBBERS_UP - connect_types = CONNECT_TYPE_SCRUBBER - src.color = PIPE_COLOR_RED - else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/up)) - src.pipe_type = PIPE_UP - else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/down/supply)) - src.pipe_type = PIPE_SUPPLY_DOWN - connect_types = CONNECT_TYPE_SUPPLY - src.color = PIPE_COLOR_BLUE - else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/down/scrubbers)) - src.pipe_type = PIPE_SCRUBBERS_DOWN - connect_types = CONNECT_TYPE_SCRUBBER - src.color = PIPE_COLOR_RED - else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/down)) - src.pipe_type = PIPE_DOWN -///// Z-Level stuff - else if(istype(make_from, /obj/machinery/atmospherics/pipe/vent)) - src.pipe_type = PIPE_PASSIVE_VENT +// One subtype for each way components connect to neighbors +/obj/item/pipe/directional + dispenser_class = PIPE_DIRECTIONAL +/obj/item/pipe/binary + dispenser_class = PIPE_STRAIGHT +/obj/item/pipe/binary/bendable + dispenser_class = PIPE_BENDABLE +/obj/item/pipe/trinary + dispenser_class = PIPE_TRINARY +/obj/item/pipe/trinary/flippable + dispenser_class = PIPE_TRIN_M + var/mirrored = FALSE +/obj/item/pipe/quaternary + dispenser_class = PIPE_ONEDIR + +/** + * Call constructor with: + * @param loc Location + * @pipe_type + */ +/obj/item/pipe/initialize(var/mapload, var/_pipe_type, var/_dir, var/obj/machinery/atmospherics/make_from) + if(make_from) + make_from_existing(make_from) else - src.pipe_type = pipe_type - src.set_dir(dir) - if (pipe_type == 29 || pipe_type == 30 || pipe_type == 33 || pipe_type == 35 || pipe_type == 37 || pipe_type == 39 || pipe_type == 41) - connect_types = CONNECT_TYPE_SUPPLY - src.color = PIPE_COLOR_BLUE - else if (pipe_type == 31 || pipe_type == 32 || pipe_type == 34 || pipe_type == 36 || pipe_type == 38 || pipe_type == 40 || pipe_type == 42) - connect_types = CONNECT_TYPE_SCRUBBER - src.color = PIPE_COLOR_RED - else if (pipe_type == 2 || pipe_type == 3) - connect_types = CONNECT_TYPE_HE - else if (pipe_type == 6) - connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_HE - else if (pipe_type == 28) - connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER - //src.pipe_dir = get_pipe_dir() - update() - src.pixel_x = rand(-5, 5) - src.pixel_y = rand(-5, 5) + pipe_type = _pipe_type + set_dir(_dir) -//update the name and icon of the pipe item depending on the type + update() + pixel_x += rand(-5, 5) + pixel_y += rand(-5, 5) + return ..() + +/obj/item/pipe/proc/make_from_existing(obj/machinery/atmospherics/make_from) + set_dir(make_from.dir) + pipename = make_from.name + if(make_from.req_access) + src.req_access = make_from.req_access + if(make_from.req_one_access) + src.req_one_access = make_from.req_one_access + color = make_from.pipe_color + pipe_type = make_from.type + +/obj/item/pipe/trinary/flippable/make_from_existing(obj/machinery/atmospherics/trinary/make_from) + ..() + if(make_from.mirrored) + do_a_flip() + +/obj/item/pipe/dropped() + if(loc) + setPipingLayer(piping_layer) + return ..() + +/obj/item/pipe/proc/setPipingLayer(new_layer = PIPING_LAYER_DEFAULT) + var/obj/machinery/atmospherics/fakeA = pipe_type + if(initial(fakeA.pipe_flags) & (PIPING_ALL_LAYER|PIPING_DEFAULT_LAYER_ONLY)) + new_layer = PIPING_LAYER_DEFAULT + piping_layer = new_layer + // Do it the Polaris way + switch(piping_layer) + if(PIPING_LAYER_SCRUBBER) + color = PIPE_COLOR_RED + name = "[initial(fakeA.name)] scrubber fitting" + if(PIPING_LAYER_SUPPLY) + color = PIPE_COLOR_BLUE + name = "[initial(fakeA.name)] supply fitting" + // 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/item/pipe/proc/update() - var/list/nlist = list( \ - "pipe", \ - "bent pipe", \ - "h/e pipe", \ - "bent h/e pipe", \ - "connector", \ - "manifold", \ - "junction", \ - "uvent", \ - "mvalve", \ - "pump", \ - "scrubber", \ - "insulated pipe", \ - "bent insulated pipe", \ - "gas filter", \ - "gas mixer", \ - "pressure regulator", \ - "high power pump", \ - "heat exchanger", \ - "t-valve", \ - "4-way manifold", \ - "pipe cap", \ -///// Z-Level stuff - "pipe up", \ - "pipe down", \ -///// Z-Level stuff - "gas filter m", \ - "gas mixer t", \ - "gas mixer m", \ - "omni mixer", \ - "omni filter", \ -///// Supply and scrubbers pipes - "universal pipe adapter", \ - "supply pipe", \ - "bent supply pipe", \ - "scrubbers pipe", \ - "bent scrubbers pipe", \ - "supply manifold", \ - "scrubbers manifold", \ - "supply 4-way manifold", \ - "scrubbers 4-way manifold", \ - "supply pipe up", \ - "scrubbers pipe up", \ - "supply pipe down", \ - "scrubbers pipe down", \ - "supply pipe cap", \ - "scrubbers pipe cap", \ - "t-valve m", \ - "dvalve", \ - "dt-valve", \ - "dt-valve m", \ - "passive vent", \ - ) - name = nlist[pipe_type+1] + " fitting" - var/list/islist = list( \ - "simple", \ - "simple", \ - "he", \ - "he", \ - "connector", \ - "manifold", \ - "junction", \ - "uvent", \ - "mvalve", \ - "pump", \ - "scrubber", \ - "insulated", \ - "insulated", \ - "filter", \ - "mixer", \ - "passivegate", \ - "volumepump", \ - "heunary", \ - "mtvalve", \ - "manifold4w", \ - "cap", \ -///// Z-Level stuff - "cap", \ - "cap", \ -///// Z-Level stuff - "m_filter", \ - "t_mixer", \ - "m_mixer", \ - "omni_mixer", \ - "omni_filter", \ -///// Supply and scrubbers pipes - "universal", \ - "simple", \ - "simple", \ - "simple", \ - "simple", \ - "manifold", \ - "manifold", \ - "manifold4w", \ - "manifold4w", \ - "cap", \ - "cap", \ - "cap", \ - "cap", \ - "cap", \ - "cap", \ - "mtvalvem", \ - "dvalve", \ - "dtvalve", \ - "dtvalvem", \ - "passive vent", \ - ) - icon_state = islist[pipe_type + 1] + var/obj/machinery/atmospherics/fakeA = pipe_type + name = "[initial(fakeA.name)] fitting" + icon_state = initial(fakeA.pipe_state) -//called when a turf is attacked with a pipe item -/obj/item/pipe/afterattack(turf/simulated/floor/target, mob/user, proximity) - if(!proximity) return - if(istype(target)) - user.drop_from_inventory(src, target) - else - return ..() +/obj/item/pipe/verb/flip() + set category = "Object" + set name = "Flip Pipe" + set src in view(1) -// rotate the pipe item clockwise + if ( usr.stat || usr.restrained() || !usr.canmove ) + return + + do_a_flip() + +/obj/item/pipe/proc/do_a_flip() + set_dir(turn(dir, -180)) + fixdir() + +/obj/item/pipe/trinary/flippable/do_a_flip() + // set_dir(turn(dir, flipped ? 45 : -45)) + // TG has a magic icon set with the flipped versions in the diagonals. + // We may switch to this later, but for now gotta do some magic. + mirrored = !mirrored + var/obj/machinery/atmospherics/fakeA = pipe_type + icon_state = "[initial(fakeA.pipe_state)][mirrored ? "m" : ""]" /obj/item/pipe/verb/rotate() set category = "Object" set name = "Rotate Pipe" set src in view(1) - if ( usr.stat || usr.restrained() ) + if ( usr.stat || usr.restrained() || !usr.canmove ) return - src.set_dir(turn(src.dir, -90)) - - if (pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_SUPPLY_STRAIGHT, PIPE_SCRUBBERS_STRAIGHT, PIPE_UNIVERSAL, PIPE_HE_STRAIGHT, PIPE_INSULATED_STRAIGHT, PIPE_MVALVE)) - if(dir==2) - set_dir(1) - else if(dir==8) - set_dir(4) - else if (pipe_type in list (PIPE_MANIFOLD4W, PIPE_SUPPLY_MANIFOLD4W, PIPE_SCRUBBERS_MANIFOLD4W)) - set_dir(2) - //src.pipe_set_dir(get_pipe_dir()) - return + set_dir(turn(src.dir, -90)) // Rotate clockwise + fixdir() /obj/item/pipe/Move() - ..() - if ((pipe_type in list (PIPE_SIMPLE_BENT, PIPE_SUPPLY_BENT, PIPE_SCRUBBERS_BENT, PIPE_HE_BENT, PIPE_INSULATED_BENT)) \ - && (src.dir in cardinal)) - src.set_dir(src.dir|turn(src.dir, 90)) - else if (pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_SUPPLY_STRAIGHT, PIPE_SCRUBBERS_STRAIGHT, PIPE_UNIVERSAL, PIPE_HE_STRAIGHT, PIPE_INSULATED_STRAIGHT, PIPE_MVALVE)) - if(dir==2) - set_dir(1) - else if(dir==8) - set_dir(4) + var/old_dir = dir + . = ..() + set_dir(old_dir) //pipes changing direction when moved is just annoying and buggy + +//Helper to clean up dir +/obj/item/pipe/proc/fixdir() return -// returns all pipe's endpoints +/obj/item/pipe/binary/fixdir() + if(dir == SOUTH) + set_dir(NORTH) + else if(dir == WEST) + set_dir(EAST) -/obj/item/pipe/proc/get_pipe_dir() - if (!dir) - return 0 - var/flip = turn(dir, 180) - var/cw = turn(dir, -90) - var/acw = turn(dir, 90) +/obj/item/pipe/trinary/flippable/fixdir() + if(dir in cornerdirs) + set_dir(turn(dir, 45)) - switch(pipe_type) - if( PIPE_SIMPLE_STRAIGHT, \ - PIPE_INSULATED_STRAIGHT, \ - PIPE_HE_STRAIGHT, \ - PIPE_JUNCTION ,\ - PIPE_PUMP ,\ - PIPE_VOLUME_PUMP ,\ - PIPE_PASSIVE_GATE ,\ - PIPE_MVALVE, \ - PIPE_SUPPLY_STRAIGHT, \ - PIPE_SCRUBBERS_STRAIGHT, \ - PIPE_UNIVERSAL, \ - PIPE_DVALVE, \ - ) - return dir|flip - if(PIPE_SIMPLE_BENT, PIPE_INSULATED_BENT, PIPE_HE_BENT, PIPE_SUPPLY_BENT, PIPE_SCRUBBERS_BENT) - return dir //dir|acw - if(PIPE_CONNECTOR,PIPE_UVENT,PIPE_SCRUBBER,PIPE_HEAT_EXCHANGE) - return dir - if(PIPE_MANIFOLD4W, PIPE_SUPPLY_MANIFOLD4W, PIPE_SCRUBBERS_MANIFOLD4W, PIPE_OMNI_MIXER, PIPE_OMNI_FILTER) - return dir|flip|cw|acw - if(PIPE_MANIFOLD, PIPE_SUPPLY_MANIFOLD, PIPE_SCRUBBERS_MANIFOLD) - return flip|cw|acw - if(PIPE_GAS_FILTER, PIPE_GAS_MIXER, PIPE_MTVALVE, PIPE_DTVALVE) - return dir|flip|cw - if(PIPE_GAS_FILTER_M, PIPE_GAS_MIXER_M, PIPE_MTVALVEM, PIPE_DTVALVEM) - return dir|flip|acw - if(PIPE_GAS_MIXER_T) - return dir|cw|acw - if(PIPE_CAP, PIPE_SUPPLY_CAP, PIPE_SCRUBBERS_CAP) - return dir -///// Z-Level stuff - if(PIPE_UP,PIPE_DOWN,PIPE_SUPPLY_UP,PIPE_SUPPLY_DOWN,PIPE_SCRUBBERS_UP,PIPE_SCRUBBERS_DOWN) - return dir -///// Z-Level stuff - if(PIPE_PASSIVE_VENT) - return dir - return 0 +/obj/item/pipe/attack_self(mob/user) + set_dir(turn(dir,-90)) + fixdir() -/obj/item/pipe/proc/get_pdir() //endpoints for regular pipes - - var/flip = turn(dir, 180) -// var/cw = turn(dir, -90) -// var/acw = turn(dir, 90) - - if (!(pipe_type in list(PIPE_HE_STRAIGHT, PIPE_HE_BENT, PIPE_JUNCTION))) - return get_pipe_dir() - switch(pipe_type) - if(PIPE_HE_STRAIGHT,PIPE_HE_BENT) - return 0 - if(PIPE_JUNCTION) - return flip - return 0 - -// return the h_dir (heat-exchange pipes) from the type and the dir - -/obj/item/pipe/proc/get_hdir() //endpoints for h/e pipes - -// var/flip = turn(dir, 180) -// var/cw = turn(dir, -90) - - switch(pipe_type) - if(PIPE_HE_STRAIGHT) - return get_pipe_dir() - if(PIPE_HE_BENT) - return get_pipe_dir() - if(PIPE_JUNCTION) - return dir - else - return 0 - -/obj/item/pipe/attack_self(mob/user as mob) - return rotate() +//called when a turf is attacked with a pipe item +/obj/item/pipe/afterattack(turf/simulated/floor/target, mob/user, proximity) + if(!proximity) return + if(istype(target) && user.canUnEquip(src)) + user.drop_from_inventory(src, target) + else + return ..() /obj/item/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - ..() - //* - if (!istype(W, /obj/item/weapon/wrench)) - return ..() - if (!isturf(src.loc)) - return 1 - if (pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_SUPPLY_STRAIGHT, PIPE_SCRUBBERS_STRAIGHT, PIPE_HE_STRAIGHT, PIPE_INSULATED_STRAIGHT, PIPE_MVALVE)) - if(dir==2) - set_dir(1) - else if(dir==8) - set_dir(4) - else if (pipe_type in list(PIPE_MANIFOLD4W, PIPE_SUPPLY_MANIFOLD4W, PIPE_SCRUBBERS_MANIFOLD4W, PIPE_OMNI_MIXER, PIPE_OMNI_FILTER)) - set_dir(2) - var/pipe_dir = get_pipe_dir() + if(iswrench(W)) + return wrench_act(user, W) + return ..() - for(var/obj/machinery/atmospherics/M in src.loc) - if((M.initialize_directions & pipe_dir) && M.check_connect_types_construction(M,src)) // matches at least one direction on either type of pipe & same connection type - user << "There is already a pipe of the same type at this location." - return 1 +/obj/item/pipe/proc/wrench_act(var/mob/living/user, var/obj/item/weapon/wrench/W) + if(!isturf(loc)) + return TRUE + + add_fingerprint(user) + fixdir() + + var/obj/machinery/atmospherics/fakeA = pipe_type + var/flags = initial(fakeA.pipe_flags) + for(var/obj/machinery/atmospherics/M in loc) + if((M.pipe_flags & flags & PIPING_ONE_PER_TURF)) //Only one dense/requires density object per tile, eg connectors/cryo/heater/coolers. + to_chat(user, "Something is hogging the tile!") + return TRUE + if((M.piping_layer != piping_layer) && !((M.pipe_flags | flags) & PIPING_ALL_LAYER)) // Pipes on different layers can't block each other unless they are ALL_LAYER + continue + if(M.get_init_dirs() & SSmachines.get_init_dirs(pipe_type, dir)) // matches at least one direction on either type of pipe + to_chat(user, "There is already a pipe at that location!") + return TRUE // no conflicts found - var/pipefailtext = "There's nothing to connect this pipe section to!" //(with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)" - - //TODO: Move all of this stuff into the various pipe constructors. - switch(pipe_type) - if(PIPE_SIMPLE_STRAIGHT, PIPE_SIMPLE_BENT) - var/obj/machinery/atmospherics/pipe/simple/P = new( src.loc ) - P.pipe_color = color - P.set_dir(src.dir) - P.initialize_directions = pipe_dir - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - if (QDELETED(P)) - usr << pipefailtext - return 1 - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - - if(PIPE_SUPPLY_STRAIGHT, PIPE_SUPPLY_BENT) - var/obj/machinery/atmospherics/pipe/simple/hidden/supply/P = new( src.loc ) - P.pipe_color = color - P.set_dir(src.dir) - P.initialize_directions = pipe_dir - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - if (QDELETED(P)) - usr << pipefailtext - return 1 - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - - if(PIPE_SCRUBBERS_STRAIGHT, PIPE_SCRUBBERS_BENT) - var/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers/P = new( src.loc ) - P.pipe_color = color - P.set_dir(src.dir) - P.initialize_directions = pipe_dir - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - if (QDELETED(P)) - usr << pipefailtext - return 1 - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - - if(PIPE_UNIVERSAL) - var/obj/machinery/atmospherics/pipe/simple/hidden/universal/P = new( src.loc ) - P.pipe_color = color - P.set_dir(src.dir) - P.initialize_directions = pipe_dir - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - if (QDELETED(P)) - usr << pipefailtext - return 1 - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - - if(PIPE_HE_STRAIGHT, PIPE_HE_BENT) - var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/P = new ( src.loc ) - P.set_dir(src.dir) - P.initialize_directions = pipe_dir //this var it's used to know if the pipe is bent or not - P.initialize_directions_he = pipe_dir - P.atmos_init() - if (QDELETED(P)) - usr << pipefailtext - return 1 - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - - if(PIPE_CONNECTOR) // connector - var/obj/machinery/atmospherics/portables_connector/C = new( src.loc ) - C.set_dir(dir) - C.initialize_directions = pipe_dir - if (pipename) - C.name = pipename - var/turf/T = C.loc - C.level = !T.is_plating() ? 2 : 1 - C.atmos_init() - C.build_network() - if (C.node) - C.node.atmos_init() - C.node.build_network() - - - if(PIPE_MANIFOLD) //manifold - var/obj/machinery/atmospherics/pipe/manifold/M = new( src.loc ) - M.pipe_color = color - M.set_dir(dir) - M.initialize_directions = pipe_dir - //M.New() - var/turf/T = M.loc - M.level = !T.is_plating() ? 2 : 1 - M.atmos_init() - if (QDELETED(M)) - usr << pipefailtext - return 1 - M.build_network() - if (M.node1) - M.node1.atmos_init() - M.node1.build_network() - if (M.node2) - M.node2.atmos_init() - M.node2.build_network() - if (M.node3) - M.node3.atmos_init() - M.node3.build_network() - - if(PIPE_SUPPLY_MANIFOLD) //manifold - var/obj/machinery/atmospherics/pipe/manifold/hidden/supply/M = new( src.loc ) - M.pipe_color = color - M.set_dir(dir) - M.initialize_directions = pipe_dir - //M.New() - var/turf/T = M.loc - M.level = !T.is_plating() ? 2 : 1 - M.atmos_init() - if (!M) - usr << "There's nothing to connect this manifold to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)" - return 1 - M.build_network() - if (M.node1) - M.node1.atmos_init() - M.node1.build_network() - if (M.node2) - M.node2.atmos_init() - M.node2.build_network() - if (M.node3) - M.node3.atmos_init() - M.node3.build_network() - - if(PIPE_SCRUBBERS_MANIFOLD) //manifold - var/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers/M = new( src.loc ) - M.pipe_color = color - M.set_dir(dir) - M.initialize_directions = pipe_dir - //M.New() - var/turf/T = M.loc - M.level = !T.is_plating() ? 2 : 1 - M.atmos_init() - if (!M) - usr << "There's nothing to connect this manifold to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)" - return 1 - M.build_network() - if (M.node1) - M.node1.atmos_init() - M.node1.build_network() - if (M.node2) - M.node2.atmos_init() - M.node2.build_network() - if (M.node3) - M.node3.atmos_init() - M.node3.build_network() - M.node3.build_network() - - if(PIPE_MANIFOLD4W) //4-way manifold - var/obj/machinery/atmospherics/pipe/manifold4w/M = new( src.loc ) - M.pipe_color = color - M.set_dir(dir) - M.initialize_directions = pipe_dir - //M.New() - var/turf/T = M.loc - M.level = !T.is_plating() ? 2 : 1 - M.atmos_init() - if (QDELETED(M)) - usr << pipefailtext - return 1 - M.build_network() - if (M.node1) - M.node1.atmos_init() - M.node1.build_network() - if (M.node2) - M.node2.atmos_init() - M.node2.build_network() - if (M.node3) - M.node3.atmos_init() - M.node3.build_network() - if (M.node4) - M.node4.atmos_init() - M.node4.build_network() - - if(PIPE_SUPPLY_MANIFOLD4W) //4-way manifold - var/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply/M = new( src.loc ) - M.pipe_color = color - M.set_dir(dir) - M.initialize_directions = pipe_dir - M.connect_types = src.connect_types - //M.New() - var/turf/T = M.loc - M.level = !T.is_plating() ? 2 : 1 - M.atmos_init() - if (!M) - usr << "There's nothing to connect this manifold to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)" - return 1 - M.build_network() - if (M.node1) - M.node1.atmos_init() - M.node1.build_network() - if (M.node2) - M.node2.atmos_init() - M.node2.build_network() - if (M.node3) - M.node3.atmos_init() - M.node3.build_network() - if (M.node4) - M.node4.atmos_init() - M.node4.build_network() - - if(PIPE_SCRUBBERS_MANIFOLD4W) //4-way manifold - var/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers/M = new( src.loc ) - M.pipe_color = color - M.set_dir(dir) - M.initialize_directions = pipe_dir - M.connect_types = src.connect_types - //M.New() - var/turf/T = M.loc - M.level = !T.is_plating() ? 2 : 1 - M.atmos_init() - if (!M) - usr << "There's nothing to connect this manifold to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)" - return 1 - M.build_network() - if (M.node1) - M.node1.atmos_init() - M.node1.build_network() - if (M.node2) - M.node2.atmos_init() - M.node2.build_network() - if (M.node3) - M.node3.atmos_init() - M.node3.build_network() - if (M.node4) - M.node4.atmos_init() - M.node4.build_network() - - if(PIPE_JUNCTION) - var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/P = new ( src.loc ) - P.set_dir(src.dir) - P.initialize_directions = src.get_pdir() - P.initialize_directions_he = src.get_hdir() - P.atmos_init() - if (QDELETED(P)) - usr << pipefailtext //"There's nothing to connect this pipe to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)" - return 1 - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - - if(PIPE_UVENT) //unary vent - var/obj/machinery/atmospherics/unary/vent_pump/V = new( src.loc ) - V.set_dir(dir) - V.initialize_directions = pipe_dir - if (pipename) - V.name = pipename - var/turf/T = V.loc - V.level = !T.is_plating() ? 2 : 1 - V.atmos_init() - V.build_network() - if (V.node) - V.node.atmos_init() - V.node.build_network() - - if(PIPE_MVALVE) //manual valve - var/obj/machinery/atmospherics/valve/V = new( src.loc) - V.set_dir(dir) - V.initialize_directions = pipe_dir - if (pipename) - V.name = pipename - var/turf/T = V.loc - V.level = !T.is_plating() ? 2 : 1 - V.atmos_init() - V.build_network() - if (V.node1) -// world << "[V.node1.name] is connected to valve, forcing it to update its nodes." - V.node1.atmos_init() - V.node1.build_network() - if (V.node2) -// world << "[V.node2.name] is connected to valve, forcing it to update its nodes." - V.node2.atmos_init() - V.node2.build_network() - - if(PIPE_PUMP) //gas pump - var/obj/machinery/atmospherics/binary/pump/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - - if(PIPE_GAS_FILTER) //gas filter - var/obj/machinery/atmospherics/trinary/atmos_filter/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - if (P.node3) - P.node3.atmos_init() - P.node3.build_network() - - if(PIPE_GAS_MIXER) //gas mixer - var/obj/machinery/atmospherics/trinary/mixer/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - if (P.node3) - P.node3.atmos_init() - P.node3.build_network() - - if(PIPE_GAS_FILTER_M) //gas filter mirrored - var/obj/machinery/atmospherics/trinary/atmos_filter/m_filter/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - if (P.node3) - P.node3.atmos_init() - P.node3.build_network() - - if(PIPE_GAS_MIXER_T) //gas mixer-t - var/obj/machinery/atmospherics/trinary/mixer/t_mixer/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - if (P.node3) - P.node3.atmos_init() - P.node3.build_network() - - if(PIPE_GAS_MIXER_M) //gas mixer mirrored - var/obj/machinery/atmospherics/trinary/mixer/m_mixer/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - if (P.node3) - P.node3.atmos_init() - P.node3.build_network() - - if(PIPE_SCRUBBER) //scrubber - var/obj/machinery/atmospherics/unary/vent_scrubber/S = new(src.loc) - S.set_dir(dir) - S.initialize_directions = pipe_dir - if (pipename) - S.name = pipename - var/turf/T = S.loc - S.level = !T.is_plating() ? 2 : 1 - S.atmos_init() - S.build_network() - if (S.node) - S.node.atmos_init() - S.node.build_network() - - if(PIPE_INSULATED_STRAIGHT, PIPE_INSULATED_BENT) - var/obj/machinery/atmospherics/pipe/simple/insulated/P = new( src.loc ) - P.set_dir(src.dir) - P.initialize_directions = pipe_dir - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - if (QDELETED(P)) - usr << pipefailtext - return 1 - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - - if(PIPE_MTVALVE) //manual t-valve - var/obj/machinery/atmospherics/tvalve/V = new(src.loc) - V.set_dir(dir) - V.initialize_directions = pipe_dir - if (pipename) - V.name = pipename - var/turf/T = V.loc - V.level = !T.is_plating() ? 2 : 1 - V.atmos_init() - V.build_network() - if (V.node1) - V.node1.atmos_init() - V.node1.build_network() - if (V.node2) - V.node2.atmos_init() - V.node2.build_network() - if (V.node3) - V.node3.atmos_init() - V.node3.build_network() - - if(PIPE_MTVALVEM) //manual t-valve - var/obj/machinery/atmospherics/tvalve/mirrored/V = new(src.loc) - V.set_dir(dir) - V.initialize_directions = pipe_dir - if (pipename) - V.name = pipename - var/turf/T = V.loc - V.level = !T.is_plating() ? 2 : 1 - V.atmos_init() - V.build_network() - if (V.node1) - V.node1.atmos_init() - V.node1.build_network() - if (V.node2) - V.node2.atmos_init() - V.node2.build_network() - if (V.node3) - V.node3.atmos_init() - V.node3.build_network() - - if(PIPE_CAP) - var/obj/machinery/atmospherics/pipe/cap/C = new(src.loc) - C.set_dir(dir) - C.initialize_directions = pipe_dir - C.atmos_init() - C.build_network() - if(C.node) - C.node.atmos_init() - C.node.build_network() - - if(PIPE_SUPPLY_CAP) - var/obj/machinery/atmospherics/pipe/cap/hidden/supply/C = new(src.loc) - C.set_dir(dir) - C.initialize_directions = pipe_dir - C.atmos_init() - C.build_network() - if(C.node) - C.node.atmos_init() - C.node.build_network() - - if(PIPE_SCRUBBERS_CAP) - var/obj/machinery/atmospherics/pipe/cap/hidden/scrubbers/C = new(src.loc) - C.set_dir(dir) - C.initialize_directions = pipe_dir - C.atmos_init() - C.build_network() - if(C.node) - C.node.atmos_init() - C.node.build_network() - - if(PIPE_PASSIVE_GATE) //passive gate - var/obj/machinery/atmospherics/binary/passive_gate/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - - if(PIPE_VOLUME_PUMP) //volume pump - var/obj/machinery/atmospherics/binary/pump/high_power/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - - if(PIPE_HEAT_EXCHANGE) // heat exchanger - var/obj/machinery/atmospherics/unary/heat_exchanger/C = new( src.loc ) - C.set_dir(dir) - C.initialize_directions = pipe_dir - if (pipename) - C.name = pipename - var/turf/T = C.loc - C.level = !T.is_plating() ? 2 : 1 - C.atmos_init() - C.build_network() - if (C.node) - C.node.atmos_init() - C.node.build_network() - - if(PIPE_DVALVE) //digital valve - var/obj/machinery/atmospherics/valve/digital/V = new( src.loc) - if(src.req_access) - V.req_access = src.req_access - if(src.req_one_access) - V.req_one_access = src.req_one_access - V.set_dir(dir) - V.initialize_directions = pipe_dir - if (pipename) - V.name = pipename - var/turf/T = V.loc - V.level = !T.is_plating() ? 2 : 1 - V.atmos_init() - V.build_network() - if (V.node1) - V.node1.atmos_init() - V.node1.build_network() - if (V.node2) - V.node2.atmos_init() - V.node2.build_network() - - if(PIPE_DTVALVE) //digital t-valve - var/obj/machinery/atmospherics/tvalve/digital/V = new(src.loc) - if(src.req_access) - V.req_access = src.req_access - if(src.req_one_access) - V.req_one_access = src.req_one_access - V.set_dir(dir) - V.initialize_directions = pipe_dir - if (pipename) - V.name = pipename - var/turf/T = V.loc - V.level = !T.is_plating() ? 2 : 1 - V.atmos_init() - V.build_network() - if (V.node1) - V.node1.atmos_init() - V.node1.build_network() - if (V.node2) - V.node2.atmos_init() - V.node2.build_network() - if (V.node3) - V.node3.atmos_init() - V.node3.build_network() - - if(PIPE_DTVALVEM) //mirrored digital t-valve - var/obj/machinery/atmospherics/tvalve/digital/mirrored/V = new(src.loc) - if(src.req_access) - V.req_access = src.req_access - if(src.req_one_access) - V.req_one_access = src.req_one_access - V.set_dir(dir) - V.initialize_directions = pipe_dir - if (pipename) - V.name = pipename - var/turf/T = V.loc - V.level = !T.is_plating() ? 2 : 1 - V.atmos_init() - V.build_network() - if (V.node1) - V.node1.atmos_init() - V.node1.build_network() - if (V.node2) - V.node2.atmos_init() - V.node2.build_network() - if (V.node3) - V.node3.atmos_init() - V.node3.build_network() - -///// Z-Level stuff - if(PIPE_UP) - var/obj/machinery/atmospherics/pipe/zpipe/up/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - if(PIPE_DOWN) - var/obj/machinery/atmospherics/pipe/zpipe/down/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - if(PIPE_SUPPLY_UP) - var/obj/machinery/atmospherics/pipe/zpipe/up/supply/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - if(PIPE_SUPPLY_DOWN) - var/obj/machinery/atmospherics/pipe/zpipe/down/supply/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - if(PIPE_SCRUBBERS_UP) - var/obj/machinery/atmospherics/pipe/zpipe/up/scrubbers/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() - if(PIPE_SCRUBBERS_DOWN) - var/obj/machinery/atmospherics/pipe/zpipe/down/scrubbers/P = new(src.loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - if (pipename) - P.name = pipename - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() - if (P.node2) - P.node2.atmos_init() - P.node2.build_network() -///// Z-Level stuff - if(PIPE_OMNI_MIXER) - var/obj/machinery/atmospherics/omni/mixer/P = new(loc) - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if(PIPE_OMNI_FILTER) - var/obj/machinery/atmospherics/omni/atmos_filter/P = new(loc) - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if(PIPE_PASSIVE_VENT) - var/obj/machinery/atmospherics/pipe/vent/P = new(loc) - P.set_dir(dir) - P.initialize_directions = pipe_dir - var/turf/T = P.loc - P.level = !T.is_plating() ? 2 : 1 - P.atmos_init() - P.build_network() - if (P.node1) - P.node1.atmos_init() - P.node1.build_network() + var/obj/machinery/atmospherics/A = new pipe_type(loc) + build_pipe(A) + // TODO - Evaluate and remove the "need at least one thing to connect to" thing ~Leshana + // With how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment. + if (QDELETED(A)) + to_chat(user, "There's nothing to connect this pipe section to!") + return TRUE + transfer_fingerprints_to(A) playsound(src, W.usesound, 50, 1) user.visible_message( \ - "[user] fastens the [src].", \ - "You have fastened the [src].", \ - "You hear ratchet.") - qdel(src) // remove the pipe item + "[user] fastens \the [src].", \ + "You fasten \the [src].", \ + "You hear ratcheting.") - return - //TODO: DEFERRED + qdel(src) -// ensure that setterm() is called for a newly connected pipeline +/obj/item/pipe/proc/build_pipe(obj/machinery/atmospherics/A) + A.set_dir(dir) + A.init_dir() + if(pipename) + A.name = pipename + if(req_access) + A.req_access = req_access + if(req_one_access) + A.req_one_access = req_one_access + A.on_construction(color, piping_layer) + +/obj/item/pipe/trinary/flippable/build_pipe(obj/machinery/atmospherics/trinary/T) + T.mirrored = mirrored + . = ..() + +// Lookup the initialize_directions for a given atmos machinery instance facing dir. +// TODO - Right now this determines the answer by instantiating an instance and checking! +// There has to be a better way... ~Leshana +/datum/controller/subsystem/machines/proc/get_init_dirs(type, dir) + var/static/list/pipe_init_dirs_cache = list() + if(!pipe_init_dirs_cache[type]) + pipe_init_dirs_cache[type] = list() + + if(!pipe_init_dirs_cache[type]["[dir]"]) + var/obj/machinery/atmospherics/temp = new type(null, FALSE, dir) + pipe_init_dirs_cache[type]["[dir]"] = temp.get_init_dirs() + qdel(temp) + + return pipe_init_dirs_cache[type]["[dir]"] + + +// +// Meters are special - not like any other pipes or components +// + /obj/item/pipe_meter name = "meter" - desc = "A meter that can be laid on pipes" + desc = "A meter that can be laid on pipes." icon = 'icons/obj/pipe-item.dmi' icon_state = "meter" item_state = "buildpipe" w_class = ITEMSIZE_LARGE + var/piping_layer = PIPING_LAYER_DEFAULT /obj/item/pipe_meter/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - ..() + if(iswrench(W)) + return wrench_act(user, W) + return ..() - if (!istype(W, /obj/item/weapon/wrench)) - return ..() - if(!locate(/obj/machinery/atmospherics/pipe, src.loc)) - user << "You need to fasten it to a pipe" - return 1 - new/obj/machinery/meter( src.loc ) +/obj/item/pipe_meter/proc/wrench_act(var/mob/living/user, var/obj/item/weapon/wrench/W) + var/obj/machinery/atmospherics/pipe/pipe + for(var/obj/machinery/atmospherics/pipe/P in loc) + if(P.piping_layer == piping_layer) + pipe = P + break + if(!pipe) + to_chat(user, "You need to fasten it to a pipe!") + return TRUE + new /obj/machinery/meter(loc, piping_layer) playsound(src, W.usesound, 50, 1) - user << "You have fastened the meter to the pipe" + to_chat(user, "You fasten the meter to the pipe.") qdel(src) -//not sure why these are necessary -#undef PIPE_SIMPLE_STRAIGHT -#undef PIPE_SIMPLE_BENT -#undef PIPE_HE_STRAIGHT -#undef PIPE_HE_BENT -#undef PIPE_CONNECTOR -#undef PIPE_MANIFOLD -#undef PIPE_JUNCTION -#undef PIPE_UVENT -#undef PIPE_MVALVE -#undef PIPE_PUMP -#undef PIPE_SCRUBBER -#undef PIPE_INSULATED_STRAIGHT -#undef PIPE_INSULATED_BENT -#undef PIPE_GAS_FILTER -#undef PIPE_GAS_MIXER -#undef PIPE_PASSIVE_GATE -#undef PIPE_VOLUME_PUMP -#undef PIPE_OUTLET_INJECT -#undef PIPE_MTVALVE -#undef PIPE_MTVALVEM -#undef PIPE_GAS_FILTER_M -#undef PIPE_GAS_MIXER_T -#undef PIPE_GAS_MIXER_M -#undef PIPE_SUPPLY_STRAIGHT -#undef PIPE_SUPPLY_BENT -#undef PIPE_SCRUBBERS_STRAIGHT -#undef PIPE_SCRUBBERS_BENT -#undef PIPE_SUPPLY_MANIFOLD -#undef PIPE_SCRUBBERS_MANIFOLD -#undef PIPE_UNIVERSAL -//#undef PIPE_MANIFOLD4W + +/obj/item/pipe_meter/dropped() + . = ..() + if(loc) + setAttachLayer(piping_layer) + +/obj/item/pipe_meter/proc/setAttachLayer(new_layer = PIPING_LAYER_DEFAULT) + piping_layer = new_layer diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm index 8bc779adf3..6675a5ca15 100644 --- a/code/game/machinery/pipe/pipe_dispenser.dm +++ b/code/game/machinery/pipe/pipe_dispenser.dm @@ -6,74 +6,32 @@ anchored = 1 var/unwrenched = 0 var/wait = 0 + var/p_layer = PIPING_LAYER_REGULAR -/obj/machinery/pipedispenser/attack_hand(user as mob) - if(..()) +// TODO - Its about time to make this NanoUI don't we think? +/obj/machinery/pipedispenser/attack_hand(var/mob/user as mob) + if((. = ..())) return -///// Z-Level stuff - var/dat = {" -Regular pipes:
-Pipe
-Bent Pipe
-Manifold
-Digital Valve
-Manual Valve
-Pipe Cap
-4-Way Manifold
-Digital T-Valve
-Digital T-Valve - Mirrored
-Manual T-Valve
-Manual T-Valve - Mirrored
-Upward Pipe
-Downward Pipe
-Supply pipes:
-Pipe
-Bent Pipe
-Manifold
-Pipe Cap
-4-Way Manifold
-Upward Pipe
-Downward Pipe
-Scrubbers pipes:
-Pipe
-Bent Pipe
-Manifold
-Pipe Cap
-4-Way Manifold
-Upward Pipe
-Downward Pipe
-Devices:
-Universal pipe adapter
-Connector
-Unary Vent
-Passive Vent
-Gas Pump
-Pressure Regulator
-High Power Gas Pump
-Scrubber
-Meter
-Gas Filter
-Gas Filter - Mirrored
-Gas Mixer
-Gas Mixer - Mirrored
-Gas Mixer - T
-Omni Gas Mixer
-Omni Gas Filter
-Heat exchange:
-Pipe
-Bent Pipe
-Junction
-Heat Exchanger
-Insulated pipes:
-Pipe
-Bent Pipe
+ src.interact(user) -"} -///// Z-Level stuff -//What number the make points to is in the define # at the top of construction.dm in same folder +/obj/machinery/pipedispenser/interact(mob/user) + user.set_machine(src) - user << browse("[src][dat]", "window=pipedispenser") - onclose(user, "pipedispenser") + var/list/lines = list() + for(var/category in atmos_pipe_recipes) + lines += "[category]:
" + if(category == "Pipes") + // Stupid hack. Fix someday. So tired right now. + lines += "Regular " + lines += "Supply " + lines += "Scrubber " + lines += "
" + for(var/datum/pipe_recipe/PI in atmos_pipe_recipes[category]) + lines += PI.Render(src) + var/dat = lines.Join() + var/datum/browser/popup = new(user, "pipedispenser", name, 300, 800, src) + popup.set_content("[dat]") + popup.open() return /obj/machinery/pipedispenser/Topic(href, href_list) @@ -81,20 +39,27 @@ return if(unwrenched || !usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) usr << browse(null, "window=pipedispenser") + usr.unset_machine(src) return usr.set_machine(src) src.add_fingerprint(usr) - if(href_list["make"]) + if(href_list["setlayer"]) + var/new_pipe_layer = text2num(href_list["setlayer"]) + if(isnum(new_pipe_layer)) + p_layer = new_pipe_layer + updateDialog() + else if(href_list["makepipe"]) if(!wait) - var/p_type = text2num(href_list["make"]) + var/obj/machinery/atmospherics/p_type = text2path(href_list["makepipe"]) var/p_dir = text2num(href_list["dir"]) - var/obj/item/pipe/P = new (/*usr.loc*/ src.loc, pipe_type=p_type, dir=p_dir) - P.update() + var/pi_type = initial(p_type.construction_type) + var/obj/item/pipe/P = new pi_type(src.loc, p_type, p_dir) + P.setPipingLayer(p_layer) P.add_fingerprint(usr) wait = 1 spawn(10) wait = 0 - if(href_list["makemeter"]) + else if(href_list["makemeter"]) if(!wait) new /obj/item/pipe_meter(/*usr.loc*/ src.loc) wait = 1 diff --git a/code/game/machinery/pipe/pipe_recipes.dm b/code/game/machinery/pipe/pipe_recipes.dm new file mode 100644 index 0000000000..f0ae483055 --- /dev/null +++ b/code/game/machinery/pipe/pipe_recipes.dm @@ -0,0 +1,102 @@ +// +// Recipies for Pipe Dispenser and (someday) the RPD +// + +var/global/list/atmos_pipe_recipes = null + +/hook/startup/proc/init_pipe_recipes() + global.atmos_pipe_recipes = list( + "Pipes" = list( + new /datum/pipe_recipe/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple), + new /datum/pipe_recipe/pipe("Manifold", /obj/machinery/atmospherics/pipe/manifold), + new /datum/pipe_recipe/pipe("Manual Valve", /obj/machinery/atmospherics/valve), + new /datum/pipe_recipe/pipe("Digital Valve", /obj/machinery/atmospherics/valve/digital), + new /datum/pipe_recipe/pipe("Pipe cap", /obj/machinery/atmospherics/pipe/cap), + new /datum/pipe_recipe/pipe("4-Way Manifold", /obj/machinery/atmospherics/pipe/manifold4w), + new /datum/pipe_recipe/pipe("Manual T-Valve", /obj/machinery/atmospherics/tvalve), + new /datum/pipe_recipe/pipe("Digital T-Valve", /obj/machinery/atmospherics/tvalve/digital), + new /datum/pipe_recipe/pipe("Upward Pipe", /obj/machinery/atmospherics/pipe/zpipe/up), + new /datum/pipe_recipe/pipe("Downward Pipe", /obj/machinery/atmospherics/pipe/zpipe/down), + new /datum/pipe_recipe/pipe("Universal Pipe Adaptor", /obj/machinery/atmospherics/pipe/simple/visible/universal), + ), + "Devices" = list( + new /datum/pipe_recipe/pipe("Connector", /obj/machinery/atmospherics/portables_connector), + new /datum/pipe_recipe/pipe("Unary Vent", /obj/machinery/atmospherics/unary/vent_pump), + new /datum/pipe_recipe/pipe("Passive Vent", /obj/machinery/atmospherics/pipe/vent), + new /datum/pipe_recipe/pipe("Injector", /obj/machinery/atmospherics/unary/outlet_injector), + new /datum/pipe_recipe/pipe("Gas Pump", /obj/machinery/atmospherics/binary/pump), + new /datum/pipe_recipe/pipe("Pressure Regulator", /obj/machinery/atmospherics/binary/passive_gate), + new /datum/pipe_recipe/pipe("High Power Gas Pump",/obj/machinery/atmospherics/binary/pump/high_power), + new /datum/pipe_recipe/pipe("Scrubber", /obj/machinery/atmospherics/unary/vent_scrubber), + new /datum/pipe_recipe/meter("Meter"), + new /datum/pipe_recipe/pipe("Gas Filter", /obj/machinery/atmospherics/trinary/atmos_filter), + new /datum/pipe_recipe/pipe("Gas Mixer", /obj/machinery/atmospherics/trinary/mixer), + new /datum/pipe_recipe/pipe("Gas Mixer 'T'", /obj/machinery/atmospherics/trinary/mixer/t_mixer), + new /datum/pipe_recipe/pipe("Omni Gas Mixer", /obj/machinery/atmospherics/omni/mixer), + new /datum/pipe_recipe/pipe("Omni Gas Filter", /obj/machinery/atmospherics/omni/atmos_filter), + ), + "Heat Exchange" = list( + new /datum/pipe_recipe/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple/heat_exchanging), + new /datum/pipe_recipe/pipe("Junction", /obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction), + new /datum/pipe_recipe/pipe("Heat Exchanger", /obj/machinery/atmospherics/unary/heat_exchanger), + ), + "Insulated pipes" = list( + new /datum/pipe_recipe/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple/insulated), + ) + ) + return TRUE + +// +// New method of handling pipe construction. Instead of numeric constants and a giant switch statement of doom +// every pipe type has a datum instance which describes its name, placement rules and construction method, dispensing etc. +// The advantages are obvious, mostly in simplifying the code of the dispenser, and the ability to add new pipes without hassle. +// +/datum/pipe_recipe + var/name = "Abstract Pipe (fixme)" // Recipe name + var/dirtype // If using an RPD, this tells more about what previews to show. + +// Render an HTML link to select this pipe type. Returns text. +/datum/pipe_recipe/proc/Render(dispenser) + return "[name]
" + +// Parameters for the Topic link returned by Render(). Returns text. +/datum/pipe_recipe/proc/Params() + return "" + +// +// Subtype for actual pipes +// +/datum/pipe_recipe/pipe + var/obj/item/pipe/construction_type // The type PATH to the type of pipe fitting object the recipe makes. + var/obj/machinery/atmospherics/pipe_type // The type PATH of what actual pipe the fitting becomes. + +/datum/pipe_recipe/pipe/New(var/label, var/obj/machinery/atmospherics/path) + name = label + pipe_type = path + construction_type = initial(path.construction_type) + dirtype = initial(construction_type.dispenser_class) + +// Render an HTML link to select this pipe type +/datum/pipe_recipe/pipe/Render(dispenser) + var/dat = ..(dispenser) + // Stationary pipe dispensers don't allow you to pre-select pipe directions. + // This makes it impossble to spawn bent versions of bendable pipes. + // We add a "Bent" pipe type with a preset diagonal direction to work around it. + if(istype(dispenser, /obj/machinery/pipedispenser) && (dirtype == PIPE_BENDABLE)) + dat += "Bent [name]
" + return dat + +/datum/pipe_recipe/pipe/Params() + return "makepipe=[pipe_type]" + +// +// Subtype for meters +// +/datum/pipe_recipe/meter + dirtype = PIPE_ONEDIR + +/datum/pipe_recipe/meter/New(label) + name = label + +/datum/pipe_recipe/meter/Params() + return "makemeter=1" diff --git a/code/modules/multiz/pipes.dm b/code/modules/multiz/pipes.dm index 62b62e3fca..2f6e1e8dde 100644 --- a/code/modules/multiz/pipes.dm +++ b/code/modules/multiz/pipes.dm @@ -13,6 +13,9 @@ obj/machinery/atmospherics/pipe/zpipe dir = SOUTH initialize_directions = SOUTH + construction_type = /obj/item/pipe/directional + pipe_state = "cap" + // node1 is the connection on the same Z // node2 is the connection on the other Z @@ -135,16 +138,15 @@ obj/machinery/atmospherics/pipe/zpipe/up/atmos_init() node1_dir = direction for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node1 = target - break + if(can_be_node(target, 1)) + node1 = target + break var/turf/above = GetAbove(src) if(above) for(var/obj/machinery/atmospherics/target in above) - if(target.initialize_directions && istype(target, /obj/machinery/atmospherics/pipe/zpipe/down)) - if (check_connect_types(target,src)) + if(istype(target, /obj/machinery/atmospherics/pipe/zpipe/down)) + if (check_connectable(target) && target.check_connectable(src)) node2 = target break @@ -173,16 +175,15 @@ obj/machinery/atmospherics/pipe/zpipe/down/atmos_init() node1_dir = direction for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir)) - if(target.initialize_directions & get_dir(target,src)) - if (check_connect_types(target,src)) - node1 = target - break + if(can_be_node(target, 1)) + node1 = target + break var/turf/below = GetBelow(src) if(below) for(var/obj/machinery/atmospherics/target in below) - if(target.initialize_directions && istype(target, /obj/machinery/atmospherics/pipe/zpipe/up)) - if (check_connect_types(target,src)) + if(istype(target, /obj/machinery/atmospherics/pipe/zpipe/up)) + if (check_connectable(target) && target.check_connectable(src)) node2 = target break diff --git a/icons/atmos/heat.dmi b/icons/atmos/heat.dmi index 1014c2015b0530e63190c50fd363fdf51ae96873..8ac9682df1fc22724689d99290d1f2c2c81225eb 100644 GIT binary patch delta 1503 zcmV<51t9v{CB+O)iBL{Q4GJ0x0000DNk~Le0002s0002M1Oos70PnAINpnuNy>HH%&j&%lxf=rs-w=SpblESma@E{7ES6#ufpT za@e;CiKYYoaR%x2^P1G;{;9#C9$OugXa=-*V>-QffF&I2`SI=VdhOQ?s9pixkj{Yg zkd}DZ55`A$XX`GxA!PxUaM;i8KoW=ff_vWN$8vdT>Tqc8e;pzc$JxJwfF&HxQ%KJw zx@*7PpwR72IuA|f9_FQ7Db(WwUHs)7&OdskP!YRL1r8S<1BDL(V2Ppar^If+YXV|n zW)@Hwmwv&JUJ9_}25AS_J^BNH#56eH!`gcB3po5=0FfOU1N0kxy79vZ0NmGs2kgfn z7@&`2(#R&#e;RZ2A8QXh%A!3?#1bg`HahZ5w%W9SL%NnBZEO3r?3#pkf5bfj`Rbs`v_|A0DEmS5L+HnJ z|GNr+$d-%dVXMMCcTAvPj+$g1HXFUzCjPBu*TF|K*qc|xF(one2U$y>Dqc)M*|%us zyPI`hqF?_=4%H5U;H_+wy{Jk|z8^04mftT0Y?l_zd4TK@`8+^wSXo;yvKw4~NG}IS z0mv7EfA0gl_2TDq_)fsx9sbce;h*o@cu=JuHW83p^gaN?% zu*G?nUL-yAai{`uXn4iFUep4;nD@}!8%Nq2_SQ&|V!c?%VX7rGs9T6A){9LUhlyGm zK$RVUV!c?#VWJ216VxsBYNHor93~z>-(CGie=o}BVWR05gJe8a!m)H7CSNU52j^~< z>ct`sv-v$lFN!%_R+3~$gI=^tYNX%9^Kj;`jR7?zuwm%MA`a)3QY9S1PHKi;q&dty zfHLt0{0)HHuT5_SZ0(1T^8mLWeu%rJap~n>n$FxihdO)Z>VR*z3NJ}rz^?6*A?|oX zf6N7}J_5I1Jm15Q0Q3=z4v|a(X!DCp{ek=#qf3qgDqF%!e+P|wdV25SS}5PKL$ zX={FQspsbxQxA!}Mb-SGy(461oQIptjL$FHdS-rc>tP>qPmaTlUi7&mThGfcZaDnnN4=Ijlj+q=%Z(+e(%=C~t4@%8bHiyJY zLas#Ic}T65s%Wj{aft2)pr`x03GXeHZJ_M-H(-6hcOLJo(m>kbFW~TOz{?w@2j~Ak zkTTn-A*?>cw_ZHo!;b*W?$q!B2hXGK;w7=jo?f(-486FEhn)iJ1?N%o_D;Q+e>M6f z-{JG9JAl+##pCBuvqqlA6r4xR1HMx)=8W>7i2p)|i3TLFhsy~y@ZnqN$YE3#)6P?%rjdnn8=##X?gR4*R!P?TSc z0So3~!CHx~wMRS@?k&PDHLk FV1j%;-4y@; delta 4750 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 NT)Aw4BpYHQ{|BhE0IC20 diff --git a/icons/atmos/junction.dmi b/icons/atmos/junction.dmi index 892f5823f2e512291e3bb0a5c4a49afb33370d74..36704e0e4780669b0e37d20e0e8aef23d604795a 100644 GIT binary patch delta 808 zcmV+@1K0fT6_N*8iBL{Q4GJ0x0000DNk~Le0001>0001h1Oos70Det>C;$Ke8&FJC zMF0Q*s;a8n+uQ#B{{R2~{{R3~R8%oBF#rGn@x!$v00001bW%=J06^y0W&i*Hg^?wA ze?+UqX{NG*tDg(l+Wg0a0$;jg&JGs} z+)mOyX_OzXK*lG%YQVS0_h$mQuO5dAf85oh!GfzF36#L%z?zp;tyXm-p0e&s9o@4O zgW8bx>T3PE3NAaWp+&`@{x{o-p=N+oT+x0w-&;Io+WiQUl$zjFo;rw7x zH3(*9x~S1pDa~Oy`4yu!jcO18r{CQi0-!$46VPoAZ;ietSObvUhk0)(VYV7J@O&CmqEQpK1823pg#7!4C+^4 z0$^l51og=s!f+G`gi5|BkqQ7RyAMoRZ1hNQ$u?kQ9(1@5V;wFOX#NjAe+)?U809rC1KztAC1#=h8B;NJu7c`~^}&S{6iR=%Ci0lsrMu^UX0iyeZKB9YD{yau^-~64r m50med^m{q^(`MDGf241VZWdl7Swj2(0000zi-<}7RSGGoD1S22qIvcWQ&8K z9B!-d3AXc67qklp@HWO>d1_L|g?(KbU3o={HINjF3O50q0BM5&#+_2Ru%Le+ z01tr+dvi%NSJ=ahM*J}|oZ)cD`2d1Vf05!F&OAQ8d3<~X6c`K!WIP^|>2ylQ<1rZw z21I2)qOzvbX)Hr_*^|wJ?FM-4;uWCbcm-%UPALE(gvcy=@^MN5TCG+~X4#XEQwreG zk5_<(vuL{kb;D%*VPj)M`z6jRfJO#`0SUv<=>Bypfinsa1OWzv0SSUYXt`|If5D$j zCK!!I+V&j;0Xm%y!Z6gX1kNZxr_-7F3tV(e*7~ww6^{;n(jXB+NY+dxZ9ToLbUK|_ z(RC?-(oX0BcRHQS1J*^FX`M_ai32_y4vn^lZyW6kwp}JH0Kb17$LNFw*x1-;C3Q59 zO2-s++LGGT>2!=*BD!xK4yO|ee*k<}0wCGktDY4_eFlD@CzA;PXtw~oEL{rbi~<13 zN&plyiMl$H4m1kD^(K#3 zNQ0_254Y`uq_xR(BoHV!#sT1ak|lq}kH_QqleFG+qG**Y0EO)<6CV@DDeMEVT1~Za zG#Y^qfwJqH20KkPwSV3F6jlIgW(R`->2x}|%T2}hrAQW^5YlkG0yG@201d}0K*Nzz z0H2p%Kcp1E=jGQAe+g(fe_jDR?oriHu!}gA5o7~ax%g18$Z~ltRl{Eb1mN$4$}U$K zuK*3lD}V%bjDvUukf4rn5U&6Y$16a?$(;rgfB-;C@)-iv-+7856BF6k*k}pI0SG`u z2a^uIr(9&}6AXt#00I`E1+?gZiYNg)_;ot_>sp^c$O4EeL0tzQf2ePL0;TKvvZGm6U??vwLXEA4*<+tg7q-OWHP~j7-4lg^MQKSClK}lcvvNPdASpIo$UTxp|14_ zl`AhfJKH z2);hSJSz1GRDFP%f5BhB^o*%5U|I=$eS&$)s82v4g!zPFNP-|BVHlDy3}@D9mkeK@ zKu3F$ZdZ$1fW$K&+;^rdfoO=6PJdjq1VvyU%FQYvm*fM8?0@der)NL?u;1yn1in6j zI5PDKXq!du2FA1i1WfcRsXoA8f*=kI>9hpCK0!W4>Ju<$e>2@N3BxdVS(g>4;%noo zY5`QpO$ccr`I;~CyCwvOT*qewH5`#yKx;S~^Os%rR2Xjo8je#6P{+J{+c>2FbsTq0!UEDe>j9!fQI80py4b6;*Tf!=~nfToe{-x0Fk82rX^dthD?0`N~{1`@pF^! zuXlx7*9V{jYUBO&u2Adx0D0GqO1!y}!Pf_vZJTO+06@|Qpy+&my$hDaWPJdNYG10> z2cQW10CdN!kS1ZOJ^+A1zJr$f03tqssrT2rgo*k9f0UwqsahXE*at{zq>lI3ce`EX zGsf1tgLTWN{jXvLv{eX^oj;m-1UZko)dv8+TNc&+RH+X@k%|LQY|R4dSRa6*+HS4& z0c^a#UKC#+pm=+d##cHHQ2P7pQN4M%Z6749O)8PV_{X;1UoX=(UmqYFnfd_qBjf{6 zY-+i$e-Dt4N_~KtI6#%5W|o#h$y;tJvSaBJLK==&fQI80py7B0XgE$OKppe)ZR3;z z)G;sLHqJgAY7_qEjSJK0G`s>R;_{%gSU-p`3<(p(6KPKzhyTOUDSo*1)6B|#zmHz8 zH}|8o??3+c82>xF0f{zb%1@G&CR;>)uh*OLe{1^vKJw(tU|j(=w^j+;0enaG`+X^; z7~Yx>X>b0%is!$*!J}U<{;scwG6OC`zWn_NkG9%)z8_&d{G(C%%iPL8{l1D9`>(ON z^$T9?zeX6Y$MUT!Ko-5%e_!bT^3Q43Htlws^m;uU930^0&6{}q_%V)-j&k?Cva*7w ze@~y{)2B~ZTU$fF-$xWh(*2=R{=BA!-Me>2_FriWpvc@c`o@hLI6Xa8 zx!%X@?CjJs#$a6msFTAF&d$zG>Th;;e|HNxLcCL^s2HivV3yODhOOhT>@;w9cQa4Sv7hkGEm}=Q%z;PTfZshH?G| zd;FsNX1}v;0fHbPWqQLbs+R*%`8=BylrNP*Vj}o)cz8&tH+=8jJscbyD0|~;e`{;_ z@Zp29H%{eWyLJs%u3W*lZ{I+p%L@w&I6FJT($W&9(+l5}5E5_q`SWM!l3(WWFUmX* z;Bwk^QO?fJ5JgcdiXz;;eY^4!EP&yx;JNE<7JOu^X(R;3 z3OS>*uYk{aHqb;GG&`WWy>S)ze>UVfbS7n^gyWaC0D#^ngZMMrc5IxNpZB~T-KH!B z)E63$@aWezTGQ!N$)py2HZXo78Ox;1*!aIO+X2sii?F`#hJ4Y`c)Q)k{rmUP?RK%U zvXbcx3R?g`@6*B5g6!?>5dd*R$Kx^HzkiP?iU2^$Bc|bGnGT>N$yfEpe_fKl$eQso z>jT($vbYTBOyT6@gnlLDjX!zv1khl8WaV480GnH@PI~n(_TLD5<0|mJz~b5WT z-zfVbQgHwlT|PisW6SCQK-;|mWqBebDBKKLq46wvm74`n5(Xg`Q6&%=fIJ1v8<0zK zok14Uq2VO?*5d%|CBS%WfBatn{>I2w8~~X_mGOA2>0X^7i&N?Eu1dz{$zU(%rjv&qVjjcfj__Hje&r1pJu&yEOUiHg!r=k%|MD zD7-+YffQY5KmtY*MQqEzd~>@p*6#)uJ%HhGs5Lgu!w*iD(>xpwf2-h(N*({A?Ynz- z?%aw0H|>olgjJ;#B0=G1Q1!->5J^^X3uBLK6vmTS3WMXm4p;yG#W|W8%WFGP5WQ>@zeh+VF5(8Gw~3o z40-Z-3m`KHI^-uHbo|y8ATJJJ${QA??((fGz~SLxt_3jV4U1A|`TqwK-#>Lnuo(*g O00005|Nk9BKtV(WX+{aCv>;Lglu%-zw4`(i(kQZvfpm$$n;3{lNp}ewHM+YT z64KqHzSqyczsK)9_Sj=PyXSS!>visV#@WelSl}WoiXQZ*AOis4M{7A20ATmu>KJ$^ zTDx1i*}wL%cX0*)pXBhbz0QroRQTR?ZG+dpNsX@6?uowVq29Wp`^3cItDNpE>A`_C zuKAOBkH~;#DrU1(Hn4Yp)P_8FJ+p^_^9{LxSYc?5)U#f$vaNGHeXfC*^POBJ7N2g} zM6X%B)&uor11JRE4Gq(LZJ`k0cNyd3nvf1m^s9>Qwj8*t@=>CWf-PoH{dcf=$CAMh z9y%`TPn=^m)}kQ>V4$pst*Y0J^6%94Se0>kHxb5`u~1Ke9kaRxO9%EQ2B~#ca+fQv z;|fyrTBBOjA=ag(673ez@mxGvjg?c}@eA)3@?_L#0zUZV%xqSO@rp3yTUnMRnvzA= zDDq3RnizJ(_1t#*Ew!@Iy4r4A=jmZ~b~%y7n(A4?hi<8J-=@Dszw^z@r-$Th^J5ky z436AO4PXc(u=Mh))ro^6vyvZp$KK||G4C33`f}E4KK_TMB>f-2vwdo1T(1`*@amZ?MHshwbxEAn>Om&UX z>FRA?kR150LVmhg(=Ur~K~&|aR-r-2$0nt=Td7LbPoI}CeTxxNkR-;kXj+5!$a&Gc zlfBEUy$|0lMWwgivjz>-aCiLZ#-zUyr>sR86*;dDYCWwm**8`j_P)VO052xK2;Pir zRatklDr%S3(9qzcz0xOk6>4pZyQlYoyh5;0Uqd2(>`!SjEtPz z^O{^zmsOYbmnYo9;^GTWXv0_+ds9cJhP=O@>djr9^)5N<=#Ol%_%Ahe^y)!-Sa()a z)6t2(*`Eva1;$0%V~hPuywF_jW_`>`XsLm2r<{~jh=){oY%HC9we{%7OT7I2{Oq^D z(3cJlsy_?AD0Vw_HLayEIJV46DyBa}BgRe;;mX&;m5ZyZ@Aw^bIgHy7CnqOQON}^o zeo~KZ98bnj&ol;5rrY);H%M>(N>3`jyw+m^<<+*}W?*8XWNFFO_(#|ubFS+JudJv5 z){L_$=>>I^yyM46X%T?lt`(u(#s@U}<#Qdk@jR~Dm>TH&{kx~IGu{k+XPC~6#3m{^ z`}lBg?`z(*B{N{II-!ms?-aLjMxNJ+bs->4;%^R;&Er$od5!p$b+P5;bi2E|rw?;< zLJ*TabxL!7OEU^o;6Z}*vEjVdodpCdtCDC!GYB5vMw^+$vQ7HPD!wo>0tNQh`8>Nm zdQyg5cUxom{Q2|IgW^+MkCQdmf=6-C;;LQ^g)TWir|-q#4>;i8(}VhTb}%XP@;Ne9 zMVLX6oyI@Y9?IG7yveSjtZa*}UQFY0n$`@qeR22bcrkVRXxlPXtt_BV0BzQ>Gtr-1qj86d9S%Uv(s z3_sER?!q!jlkU>|3WtEl=ofO*P%NRnXPYmp?7`my=c_K@>C32?=3kxkT&d+L?qFkLHbKhtf%+i#VaTgCm$-nDMfQc!?r|SKfan7Be z12#hh*tu+k-fN>~Hl}M;iByJa^U%J_h)<10jMZKEdme92Rcm|j8?JXQeM4cStlysL z?rZ1J%0++%dWOfKi76gDUl2Mv?Vt;bh~T^x%8}H)!gE#kryOw<>*hBnE{u%)No_Q!Mch|N(?e3Yr+)VNCn;1F&|5mf=&F)`2P=*ch%E^he$Z}|0OnFQm0Ish-RaDR+ zwye1eGc@Pw7XrZHCZSU1HzGJrc^bL-Ji46Js(d~p<2Hcn>Y@^oE}GP5yb^H45L6{+ zetrY!DI;Z*Lp$a6KKiXFVA)MrS&)cBjJ0QHKS%4Kwrdji&l1a@s}4(8h!Y;o9}a`M zKL+i&W1gn);)8dm*S$BxCdAKMbXyw;QX1#*)9OzEb!B)Jc2 z>+HVhH|-bN8k7z0?1&;ktlK4WYL+dX3*3A7zvqu%NXYW2v{wh?pU%}NDy>C54>(XI zUS5;4;0_W|9HO+MZtGoj8ICt2V{!_!-r2GK@%)ZmBL1;X9e0Adg@*@iVkSqdD#x4S zk}M*s#I_YU5VdiK{c2oKz?B2;BDin7_?1m&$UO z`P;WI;=?p#5R@#{TKHogdFxntH$dEfoYF4#$^@k!aI{-&X(#?Pa5bQwe#``XFt(I| zq}0S^(IZoLLZi0 z_TdrrH`U^|unrSiU!f&mrSdq!tF!j@cK;}m(&RRfE~iP$gl77ikWvLVCwuRLc86rP zU3_lg3-ooNy8z5^K)BItjjizs_xGe=#&G2~HjnSCz5$+M>-Tdp=jZ7BtSs`gv$Ow_ zlA88cM@5jx4Z~xIA|0O{c}NNPk!4@f3NWb4+x9W0Bqdo|U2Up%Ulf**2xOLUrajxp zulx-<5EtUjOxMNzgkFC?EzdJsFWM$AjLC1`!=Q+n16LTCnPc>T4*T~}@N5wtUS2rV zn2KUF0~W-$R~8P92rj3B7xVL0?9or`jEsz=nzV&Ru@kQ?g{L~N02-vZ3LhHSD=I2{ zY8)6BM(Q0E2rfDunpJ^>Q9|}+i!lWrgvNeLOM{_wfi~C>d!cDvBatYTA_qno3))Uz z)Q;|*;Wu|q@;4;dQbFtyUhBQdnbiGuf>ahf|1~l= z*tCz3L+6#1u_(}x7ONRr0{wQh>+9=w_Vx-8Ehi=>CL@K^IHQA5Sa9g}9K{FryBrvl zNZx+ch8F=X+OMLA9D^-l8F{l{rE5S#Be-5~wL7_9in(aEV9DkVhN zre$Mq1)jMLOR_~eLU%cSm%@zJ7^I1870;@9uft=>KwqeL9Nux9!;;0qr}~lofGpq< z?9c1}^glQ<=D@W;kq;JK_S`p$&oDn>9*&%((iJ8_u|_%8YOYaeP0}4BGv%Ce{w!Xy z<9tn>Yl)fLo}P!va4iws!h9oNd4TzYt2Mc~YEpEyxw)O9-s*R9E+zLUXopll1$Obf z_pdhZ-@}Y+JT7n69kP*;k!{UI%FW`#nNOt;u*^sKnxGE7)2rzh_%h124xqQU*Ak7c zx2qj@>F8dyIDqCNPUj#=Hl1TEwjgyATZknPIW5*}wfMH^3!%4>tnG`228HgN7gYqJ zqGy_YqKjoJ%2JZd+}2+=yX?WMxKI=0sD=>Lk_Fww!1@7ozq{0Z&LUB&1^)t#7ML_` zfm_0C$aj2a=YN_4Po*mgW1u<-gOO{wGA@k@qYb)fh23GV(bmC+E9}@Gam^ zMZNZkNQWCRT*UX#oy2shete35xOigY0a{RXBmR75hJCHk1G0FPL6$h`8X57kpaTdC+SmYW#RaOmq-kT0O3#Qh`|)Dj2rUdZoBe%#||DEDRwK zy{hP5=?D-ZXjZz;^L;luU@BxX43%A4TAI0+U&N&ERy$d&w+A9*-~M>_tM7Psv0RJq z)1x%pU?|=~q^q}g64{3uI-T3D8W|db`u!z-`@kV?iGE`4;1IG}I+3Z`mQ^KpzmbxX z@(K4124?2R>@+wW&i@t_+4jmX3O{Qn7GfuMMc(Yd@8n=xkQ!gu*;&JcJn5<^Jv00| z0AamFF@p_gV*@NDjX63x4m2=X98C-OS*Y3h(aLKpK>lmj~?cd#(|%2nfvpFTtM%2me&^%-OWM%4w?K zgM-lfsN{$5M@IDW^7Atf9wnLlGYP7q!2zG`S*895mYs@gXqf6I$&MN!!b7T? zV0nOzN8udL;yZ;zre(To>vZ;oOn*_xBaI{>9BsD}r6JCIyw*1`@Zs}kGEx#424?fs z0#H>N5~95#b*6JSz<^(m*1nM{$pDn5uPoiPv9*ovw()$s*n@ctxe8=z>+WJN3=j|y z7*Jx}fTZ)h;@BHli;0GX+QLwdw$ILda6zUAWF(Nme5t+Z<2HHzl4AX7430$ng%Yyb z<1#NQxoAkMpFWaT*&K$;(3D$PwEhbO4@7x3Fud$hSuiNiEbJ(??R^c-w_P8NFk2-; zetKS3y1_h(F!&A`nWdRZ0zA5gKq~tB)()vFaw6&~U|i$px#ct8ew@U2Eza7Qp(X`ql46Q=NTUR#UtOV`m}P0 z`#sm>PH{#dHfjIi1Cp)8-5ziy44>+_j~?Z_sE8))c~apV{ajN%h9G?jY%)H$N|D+o z7J#z#Dx>~DNb6i8!=;kq;y(^msShbSI9*G|^8~N7sOx+Bs;H1ds$1eHLlKt1L4EYX zBp!^2ptcfaOp(>TeWlF+J!f7!J>z>fb~YcOcksMukiL?c+#l0d`RD<~ zCri%Rv9Q+zchpfRvf1q_n;~zK2lBR{jlWvI4IZJDL}8sJFlm-?`ZJ|~LDd;LO{;8(=nF7>X5E3r?7bXQ&`!rwFxizDgnZu*Tk>v$0aaIM% zmhmwOLoR-dT@*k6&bl)7Q!u+<*O1VpU*L4pCOBiCXA_O(QMO+_UQD*1zq*e~k;$Rd zwuU$1oU2yxc(U{Ka=OG!NigO6h>PF#O82v){9dv}=-fq|mscz2@65Ilfnqh0t};O> zF1Xw+tHiZq?>*+d;r&-ad%EbXlGHD7;gJt5Oq;2ZtaBHk&m>SYdk_7!Cm=Kiyey{1 zo5uS4|9mYY^C!sM=jE0%55zK_LDzN6z;9Pf#KG=O>A79IDad|80)!$EwVwj{6Odbmp=R90bu5);L@w!$+6wPvm2{RzZRDG=&GlqFltS4*Ik z^mh;ghRJf@7p>)><_^nuj0jW}8_vQEL-`H&&|qc!elRO!U@IysuTzlzxZ_0O`9lD> z2gfBphK_5t=UPQXL>jbN^>hEQJ0P%*L+I6;wN)mtTwYb@$0A&WzCK)%`Fr_q1z{j$ z*GEQf?HvEg<%lFzpnbfV>i%^)7%zAZ_3pP^hlFc_I!{r3eME5Z<#{(r2aK+~;Z3k% zWMm|&bD?i)Dh#5Q`VzgmqPn_p=%WmH&Qfh0!TXkrqLKMaJ2#^rIR(RD&D-#m#v7yx zG@nYf2v-$o6fuve{n;tLqd3UrX-J=CMZwuAK4fdR!DvVohVIM*khWf-bpxOQo*@H@ z!V>yFIH0c6h7nlvoU1^BI!K~rlopy19nm_+BnkV#9<-t)N%v{RVK<{dRTGMF^zjSa zTzR_cLDBFz6hzT8eI8(wecSA~ujfdbD+R@(XauX^MK5*)|ECO8ZD(4Bv11IdBJGpZ zloYR1#mmqowwGbJN&-3;I(STjn%(0@Fdq}HKP6>0^tz6Vq)5iG8URR1FCQ^0U5D|elzYXV+B41<)*`ueL3 zM9elXl)cF#T+fOW=q;YSFd$&OYoaI z4;QA4F0!@U=|QL>XWFD7lV3FCnOJ${;SEsEy5Y|m?DX~NFVxdgps&90+vI&CBbhSQ zp*AEpp(>Mg&RG@79e^=y+B=7(l jBo)8{{C`*S9Ff9vRsZ6h4-Wd@0eGr}QY?66{^9=sS($8+ delta 5244 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