diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index 8dfe81c7b27..fe6806c9b58 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -398,6 +398,9 @@ var/datum/gas_mixture/gas_mix = all_gas_mixes[gas_mix_number] if(!gas_mix.total_moles()) empty_mixes++ + if(!nodes[gas_mix_number] || (istype(nodes[gas_mix_number], /obj/machinery/atmospherics/components/unary/portables_connector) && !portable_device_connected(gas_mix_number))) + var/pressure_delta = all_gas_mixes[gas_mix_number].return_pressure() - env_air.return_pressure() + internal_pressure = internal_pressure > pressure_delta ? internal_pressure : pressure_delta if(empty_mixes == device_type) empty_pipe = TRUE if(!int_air.total_moles()) @@ -629,6 +632,13 @@ src.pipe_color = uppertext(pipe_colour) update_name() +/// Return TRUE if there is device connected to portables_connector +/obj/machinery/atmospherics/proc/portable_device_connected(node) + var/obj/machinery/atmospherics/components/unary/portables_connector/portable_devices_connector = nodes[node] + if(portable_devices_connector.connected_device) + return TRUE + return FALSE + #undef PIPE_VISIBLE_LEVEL #undef PIPE_HIDDEN_LEVEL #undef VENT_SOUND_DELAY diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index 9e1f4f0de21..1aae85d2a14 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -105,6 +105,10 @@ . = ..() update_parents() +/obj/machinery/atmospherics/components/on_deconstruction() + relocate_airs() + return ..() + /obj/machinery/atmospherics/components/rebuild_pipes() . = ..() if(update_parents_after_rebuild) @@ -172,31 +176,6 @@ /obj/machinery/atmospherics/components/replace_pipenet(datum/pipeline/Old, datum/pipeline/New) parents[parents.Find(Old)] = New -/obj/machinery/atmospherics/components/unsafe_pressure_release(mob/user, pressures) - . = ..() - - var/turf/current_turf = get_turf(src) - if(!current_turf) - return - //Remove the gas from airs and assume it - var/datum/gas_mixture/environment = current_turf.return_air() - var/lost = null - var/times_lost = 0 - for(var/i in 1 to device_type) - var/datum/gas_mixture/air = airs[i] - lost += pressures*environment.volume/(air.temperature * R_IDEAL_GAS_EQUATION) - times_lost++ - var/shared_loss = lost/times_lost - - var/datum/gas_mixture/to_release - for(var/i in 1 to device_type) - var/datum/gas_mixture/air = airs[i] - if(!to_release) - to_release = air.remove(shared_loss) - continue - to_release.merge(air.remove(shared_loss)) - current_turf.assume_air(to_release) - // Helpers /** @@ -245,6 +224,69 @@ /obj/machinery/atmospherics/components/return_analyzable_air() return airs +/** + * Handles machinery deconstruction and unsafe pressure release + */ +/obj/machinery/atmospherics/components/proc/crowbar_deconstruction_act(mob/living/user, obj/item/tool, internal_pressure = 0) + if(!panel_open) + balloon_alert(user, "open panel!") + return ITEM_INTERACT_SUCCESS + + var/unsafe_wrenching = FALSE + var/filled_pipe = FALSE + var/datum/gas_mixture/environment_air = loc.return_air() + + for(var/i in 1 to device_type) + var/datum/gas_mixture/inside_air = airs[i] + if(inside_air.total_moles() > 0 || internal_pressure) + filled_pipe = TRUE + if(!nodes[i] || (istype(nodes[i], /obj/machinery/atmospherics/components/unary/portables_connector) && !portable_device_connected(i))) + internal_pressure = internal_pressure > airs[i].return_pressure() ? internal_pressure : airs[i].return_pressure() + + if(!filled_pipe) + default_deconstruction_crowbar(tool) + return ITEM_INTERACT_SUCCESS + + to_chat(user, span_notice("You begin to unfasten \the [src]...")) + + internal_pressure -= environment_air.return_pressure() + + if(internal_pressure > 2 * ONE_ATMOSPHERE) + to_chat(user, span_warning("As you begin deconstructing \the [src] a gush of air blows in your face... maybe you should reconsider?")) + unsafe_wrenching = TRUE + + if(!do_after(user, 2 SECONDS, src)) + return + if(unsafe_wrenching) + unsafe_pressure_release(user, internal_pressure) + tool.play_tool_sound(src, 50) + deconstruct(TRUE) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/atmospherics/components/default_change_direction_wrench(mob/user, obj/item/I) + . = ..() + if(!.) + return FALSE + set_init_directions() + for(var/i in 1 to device_type) + var/obj/machinery/atmospherics/node = nodes[i] + if(node) + if(src in node.nodes) + node.disconnect(src) + nodes[i] = null + if(parents[i]) + nullify_pipenet(parents[i]) + for(var/i in 1 to device_type) + var/obj/machinery/atmospherics/node = nodes[i] + atmos_init() + node = nodes[i] + if(node) + node.atmos_init() + node.add_member(src) + update_parents() + SSair.add_to_rebuild_queue(src) + return TRUE + /** * Disconnects all nodes from ourselves, remove us from the node's nodes. * Nullify our parent pipenet @@ -286,3 +328,21 @@ /obj/machinery/atmospherics/components/update_layer() layer = initial(layer) + (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE + (GLOB.pipe_colors_ordered[pipe_color] * 0.001) + +/** + * Handles air relocation to the pipenet/environment + */ +/obj/machinery/atmospherics/components/proc/relocate_airs(datum/gas_mixture/to_release) + var/turf/local_turf = get_turf(src) + for(var/i in 1 to device_type) + var/datum/gas_mixture/air = airs[i] + if(!nodes[i] || (istype(nodes[i], /obj/machinery/atmospherics/components/unary/portables_connector) && !portable_device_connected(i))) + if(!to_release) + to_release = air + continue + to_release.merge(air) + continue + var/datum/gas_mixture/parents_air = parents[i].air + parents_air.merge(air) + if(to_release) + local_turf.assume_air(to_release) diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_core.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_core.dm index 2d7db14ef07..6d3d5d31a16 100644 --- a/code/modules/atmospherics/machinery/components/fusion/hfr_core.dm +++ b/code/modules/atmospherics/machinery/components/fusion/hfr_core.dm @@ -199,3 +199,18 @@ QDEL_NULL(soundloop) machine_parts = null return..() + +/obj/machinery/atmospherics/components/unary/hypertorus/core/on_deconstruction() + var/turf/local_turf = get_turf(loc) + var/datum/gas_mixture/to_release = moderator_internal || internal_fusion + if(to_release == moderator_internal) + to_release.merge(internal_fusion) + if(to_release) + local_turf.assume_air(to_release) + return ..() + +/obj/machinery/atmospherics/components/unary/hypertorus/core/crowbar_deconstruction_act(mob/living/user, obj/item/tool, internal_pressure = 0) + internal_pressure = max(internal_fusion.return_pressure(), moderator_internal.return_pressure()) + if(internal_pressure) + say("WARNING - Core can contain hazardous gases, deconstruct with caution!") + return ..(user, tool, internal_pressure) diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm index 96423f9f770..86f2e3dddf5 100644 --- a/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm +++ b/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm @@ -40,8 +40,6 @@ return if(default_change_direction_wrench(user, I)) return - if(default_deconstruction_crowbar(I)) - return return ..() /obj/machinery/atmospherics/components/unary/hypertorus/welder_act(mob/living/user, obj/item/tool) @@ -55,22 +53,8 @@ cracked = FALSE update_appearance() -/obj/machinery/atmospherics/components/unary/hypertorus/default_change_direction_wrench(mob/user, obj/item/I) - . = ..() - if(.) - set_init_directions() - var/obj/machinery/atmospherics/node = nodes[1] - if(node) - node.disconnect(src) - nodes[1] = null - if(parents[1]) - nullify_pipenet(parents[1]) - atmos_init() - node = nodes[1] - if(node) - node.atmos_init() - node.add_member(src) - SSair.add_to_rebuild_queue(src) +/obj/machinery/atmospherics/components/unary/hypertorus/crowbar_act(mob/living/user, obj/item/tool) + return crowbar_deconstruction_act(user, tool) /obj/machinery/atmospherics/components/unary/hypertorus/update_icon_state() if(panel_open) @@ -207,6 +191,7 @@ ui.open() else to_chat(user, span_notice("Activate the machine first by using a multitool on the interface.")) + ui.close() /obj/machinery/hypertorus/interface/proc/gas_list_to_gasid_list(list/gas_list) var/list/gasid_list = list() diff --git a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm index b71dc05d776..0ca6bafea26 100644 --- a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm +++ b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm @@ -41,6 +41,12 @@ internal = new register_context() +/obj/machinery/atmospherics/components/binary/crystallizer/on_deconstruction() + var/turf/local_turf = get_turf(loc) + if(internal.total_moles()) + local_turf.assume_air(internal) + return ..() + /obj/machinery/atmospherics/components/binary/crystallizer/add_context(atom/source, list/context, obj/item/held_item, mob/user) . = ..() context[SCREENTIP_CONTEXT_CTRL_LMB] = "Turn [on ? "off" : "on"]" @@ -59,42 +65,10 @@ return if(default_change_direction_wrench(user, I)) return - if(default_deconstruction_crowbar(I)) - return return ..() -/obj/machinery/atmospherics/components/binary/crystallizer/default_change_direction_wrench(mob/user, obj/item/I) - . = ..() - if(!.) - return FALSE - set_init_directions() - var/obj/machinery/atmospherics/node1 = nodes[1] - var/obj/machinery/atmospherics/node2 = nodes[2] - if(node1) - if(src in node1.nodes) //Only if it's actually connected. On-pipe version would is one-sided. - node1.disconnect(src) - nodes[1] = null - if(node2) - if(src in node2.nodes) //Only if it's actually connected. On-pipe version would is one-sided. - node2.disconnect(src) - nodes[2] = null - - if(parents[1]) - nullify_pipenet(parents[1]) - if(parents[2]) - nullify_pipenet(parents[2]) - - atmos_init() - node1 = nodes[1] - if(node1) - node1.atmos_init() - node1.add_member(src) - node2 = nodes[2] - if(node2) - node2.atmos_init() - node2.add_member(src) - SSair.add_to_rebuild_queue(src) - return TRUE +/obj/machinery/atmospherics/components/binary/crystallizer/crowbar_act(mob/living/user, obj/item/tool) + return crowbar_deconstruction_act(user, tool, internal.return_pressure()) /obj/machinery/atmospherics/components/binary/crystallizer/update_overlays() . = ..() diff --git a/code/modules/atmospherics/machinery/components/unary_devices/bluespace_sender.dm b/code/modules/atmospherics/machinery/components/unary_devices/bluespace_sender.dm index 3d3c4d9c05a..269e0943004 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/bluespace_sender.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/bluespace_sender.dm @@ -49,10 +49,6 @@ GLOBAL_LIST_EMPTY_TYPED(bluespace_senders, /obj/machinery/atmospherics/component register_context() /obj/machinery/atmospherics/components/unary/bluespace_sender/Destroy() - if(bluespace_network.total_moles()) - var/turf/local_turf = get_turf(src) - local_turf.assume_air(bluespace_network) - GLOB.bluespace_senders -= src return ..() @@ -75,6 +71,11 @@ GLOBAL_LIST_EMPTY_TYPED(bluespace_senders, /obj/machinery/atmospherics/component context[SCREENTIP_CONTEXT_RMB] = "[anchored ? "Unan" : "An"]chor" return CONTEXTUAL_SCREENTIP_SET +/obj/machinery/atmospherics/components/unary/bluespace_sender/is_connectable() + if(!anchored) + return FALSE + . = ..() + /obj/machinery/atmospherics/components/unary/bluespace_sender/update_icon_state() if(panel_open) icon_state = "[base_icon_state]_open" @@ -101,6 +102,12 @@ GLOBAL_LIST_EMPTY_TYPED(bluespace_senders, /obj/machinery/atmospherics/component bluespace_network.temperature = T20C update_parents() +/obj/machinery/atmospherics/components/unary/bluespace_sender/relocate_airs() + if(bluespace_network.total_moles() > 0) + airs[1].merge(bluespace_network) + airs[1].garbage_collect() + return ..() + /obj/machinery/atmospherics/components/unary/bluespace_sender/screwdriver_act(mob/living/user, obj/item/tool) if(on) balloon_alert(user, "turn off!") @@ -108,17 +115,13 @@ GLOBAL_LIST_EMPTY_TYPED(bluespace_senders, /obj/machinery/atmospherics/component if(!anchored) balloon_alert(user, "anchor!") return ITEM_INTERACT_SUCCESS - if(default_deconstruction_screwdriver(user, "[base_icon_state]_open", "[base_icon_state]", tool)) - change_pipe_connection(panel_open) + if(default_deconstruction_screwdriver(user, "[base_icon_state]_open", "[base_icon_state]_off", tool)) return ITEM_INTERACT_SUCCESS /obj/machinery/atmospherics/components/unary/bluespace_sender/crowbar_act(mob/living/user, obj/item/tool) - default_deconstruction_crowbar(tool, custom_deconstruct = bluespace_network.total_moles() > 0 ? TRUE : FALSE) - say("WARNING - Bluespace network can contain hazardous gases, deconstruct with caution!") - if(!do_after(user, 3 SECONDS, src)) - return - tool.play_tool_sound(src, 50) - deconstruct(TRUE) + if(panel_open && bluespace_network.total_moles() > 0 && !nodes[1]) + say("WARNING - Bluespace network can contain hazardous gases, deconstruct with caution!") + return crowbar_deconstruction_act(user, tool) /obj/machinery/atmospherics/components/unary/bluespace_sender/multitool_act(mob/living/user, obj/item/item) var/obj/item/multitool/multitool = item @@ -134,6 +137,7 @@ GLOBAL_LIST_EMPTY_TYPED(bluespace_senders, /obj/machinery/atmospherics/component balloon_alert(user, "open panel!") return if(default_unfasten_wrench(user, tool)) + change_pipe_connection(!anchored) return ITEM_INTERACT_SUCCESS return diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 021d5848cb0..25965222ab2 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -457,9 +457,45 @@ /obj/machinery/cryo_cell/crowbar_act(mob/living/user, obj/item/tool) if(on || state_open) return FALSE - if(default_pry_open(tool) || default_deconstruction_crowbar(tool)) + if(!panel_open) + balloon_alert(user, "open panel!") return ITEM_INTERACT_SUCCESS + var/unsafe_wrenching = FALSE + var/filled_pipe = FALSE + var/datum/gas_mixture/environment_air = loc.return_air() + var/datum/gas_mixture/inside_air = internal_connector.gas_connector.airs[1] + var/obj/machinery/atmospherics/node = internal_connector.gas_connector.nodes[1] + var/internal_pressure = 0 + + if(istype(node, /obj/machinery/atmospherics/components/unary/portables_connector)) + var/obj/machinery/atmospherics/components/unary/portables_connector/portable_devices_connector = node + internal_pressure = !portable_devices_connector.connected_device ? 1 : 0 + + if(inside_air.total_moles() > 0) + filled_pipe = TRUE + if(!node || internal_pressure > 0) + internal_pressure = inside_air.return_pressure() - environment_air.return_pressure() + + if(!filled_pipe) + default_deconstruction_crowbar(tool) + return ITEM_INTERACT_SUCCESS + + to_chat(user, span_notice("You begin to unfasten \the [src]...")) + + if(internal_pressure > 2 * ONE_ATMOSPHERE) + to_chat(user, span_warning("As you begin deconstructing \the [src] a gush of air blows in your face... maybe you should reconsider?")) + unsafe_wrenching = TRUE + + if(!do_after(user, 2 SECONDS, src)) + return + if(unsafe_wrenching) + internal_connector.gas_connector.unsafe_pressure_release(user, internal_pressure) + + tool.play_tool_sound(src, 50) + deconstruct(TRUE) + return ITEM_INTERACT_SUCCESS + /obj/machinery/cryo_cell/wrench_act(mob/living/user, obj/item/tool) if(on || occupant || state_open) return FALSE diff --git a/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm b/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm index 49103c7729e..b1e2567f82f 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm @@ -75,6 +75,7 @@ */ /datum/gas_machine_connector/proc/deconstruct_connected_machine() SIGNAL_HANDLER + relocate_airs() disconnect_connector() SSair.stop_processing_machine(connected_machine) unregister_from_machine() @@ -106,4 +107,23 @@ if(node) node.atmos_init() node.add_member(gas_connector) + gas_connector.update_parents() SSair.add_to_rebuild_queue(gas_connector) + +/** + * Handles air relocation to the pipe network/environment + */ +/datum/gas_machine_connector/proc/relocate_airs(mob/user) + var/turf/local_turf = get_turf(connected_machine) + var/datum/gas_mixture/inside_air = gas_connector.airs[1] + if(inside_air.total_moles() > 0) + if(!gas_connector.nodes[1]) + local_turf.assume_air(inside_air) + return + var/datum/gas_mixture/parents_air = gas_connector.parents[1].air + if(istype(gas_connector.nodes[1], /obj/machinery/atmospherics/components/unary/portables_connector)) + var/obj/machinery/atmospherics/components/unary/portables_connector/portable_devices_connector = gas_connector.nodes[1] + if(!portable_devices_connector.connected_device) + local_turf.assume_air(inside_air) + return + parents_air.merge(inside_air) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm index 2a3ac2bb082..5067dcddae2 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm @@ -63,7 +63,7 @@ return CONTEXTUAL_SCREENTIP_SET /obj/machinery/atmospherics/components/unary/thermomachine/is_connectable() - if(!anchored || panel_open) + if(!anchored) return FALSE . = ..() @@ -78,7 +78,6 @@ if(check_pipe_on_turf()) set_anchored(FALSE) set_panel_open(TRUE) - change_pipe_connection(TRUE) icon_state = "thermo-open" balloon_alert(user, "the port is already in use!") @@ -208,14 +207,14 @@ balloon_alert(user, "anchor!") return ITEM_INTERACT_SUCCESS if(default_deconstruction_screwdriver(user, "thermo-open", "thermo-0", tool)) - change_pipe_connection(panel_open) + update_appearance() return ITEM_INTERACT_SUCCESS /obj/machinery/atmospherics/components/unary/thermomachine/wrench_act(mob/living/user, obj/item/tool) return default_change_direction_wrench(user, tool) /obj/machinery/atmospherics/components/unary/thermomachine/crowbar_act(mob/living/user, obj/item/tool) - return default_deconstruction_crowbar(tool) + return crowbar_deconstruction_act(user, tool) /obj/machinery/atmospherics/components/unary/thermomachine/multitool_act(mob/living/user, obj/item/multitool/multitool) if(!panel_open) @@ -226,13 +225,6 @@ update_appearance() return ITEM_INTERACT_SUCCESS -/obj/machinery/atmospherics/components/unary/thermomachine/default_change_direction_wrench(mob/user, obj/item/I) - if(!..()) - return FALSE - set_init_directions() - update_appearance() - return TRUE - /obj/machinery/atmospherics/components/unary/thermomachine/multitool_act_secondary(mob/living/user, obj/item/tool) if(!panel_open) balloon_alert(user, "open panel!") @@ -257,6 +249,7 @@ visible_message(span_warning("A pipe is hogging the port, remove the obstruction or change the machine piping layer.")) return ITEM_INTERACT_SUCCESS if(default_unfasten_wrench(user, tool)) + change_pipe_connection(!anchored) return ITEM_INTERACT_SUCCESS return