Skip to content

Commit

Permalink
Fixed atmospherics components air relocation and unsafe pressure rele…
Browse files Browse the repository at this point in the history
…ase (#173)

* Fixed atmospherics components air relocation and unsafe pressure release (#80244)

## About The Pull Request

At present

- If user deconstructs/unwrenches something from
[/obj/machinery/atmospherics/components](https://github.com/tgstation/tgstation/blob/master/code/modules/atmospherics/machinery/components/components_base.dm)
- all air inside it disappear. (only unary, binary, trinary devices).

-
[/obj/machinery/atmospherics/components/unsafe_pressure_release()](https://github.com/tgstation/tgstation/blob/f9a5502f78263690378ca01f660b1cfb2886efd1/code/modules/atmospherics/machinery/components/components_base.dm#L175)
doesn't work at all.

- HFR UI has the problem of [activation request
message](https://github.com/tgstation/tgstation/blob/f9a5502f78263690378ca01f660b1cfb2886efd1/code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm#L209C3-L209C3)
constantly repeating if the user forcefully switches off the machine
(e.g. unscrewed one of the components).

- Thermomachine and Bluespace sender do not connect to pipes when panel
is open.

- Crystallizer does not move air from node after rotation.

Now

- Each
[/obj/machinery/atmospherics/components](https://github.com/tgstation/tgstation/blob/master/code/modules/atmospherics/machinery/components/components_base.dm)
deconstruction will move air into connected pipeline if any, otherwise
it will be released from open nodes, HFR internals or if there is
portable connector that has no device connected will also release air
outside. The user will also be notified of deconstruction and if
pressure inside is safe for action.

- The
[/obj/machinery/atmospherics/components/unsafe_pressure_release()](https://github.com/tgstation/tgstation/blob/f9a5502f78263690378ca01f660b1cfb2886efd1/code/modules/atmospherics/machinery/components/components_base.dm#L175)
will act like a normal pipe
[unsafe_pressure_release()](https://github.com/tgstation/tgstation/blob/f9a5502f78263690378ca01f660b1cfb2886efd1/code/modules/atmospherics/machinery/atmosmachinery.dm#L447C1-L447C1)
if there is an empty node with air.

- When HFR interface is turned off - UI will be closed.

- Thermomachine and Bluespace sender will always try to connect to pipe
if they are anchored.

- Air inside of nodes will move to connected pipenet after the machinery
is rotated.

## Why It's Good For The Game

This fixes things that essentially had to exist at the same time adding
new possibilities for realization. Even though these aren't critical
bugs, it's still unpleasant enough to lose air.

## Changelog

:cl: mogeoko
fix: Atmospherics components will now move air into connected pipeline
on deconstruction if possible. Otherwise, air will be released to the
outside from open nodes.
fix: Unsafe pressure release on atmos components will now work the same
way it does in the normal pipes if there is an empty node with air.
fix: The HFR user interface would close when the machine is shut down.
fix: Atmospherics machinery will now share air from nodes after being
rotated and reconnected to pipenet.
/:cl:

---------

Co-authored-by: san7890 <the@ san7890.com>

* Fixed atmospherics components air relocation and unsafe pressure release

---------

Co-authored-by: mogeoko <[email protected]>
Co-authored-by: san7890 <the@ san7890.com>
Co-authored-by: NovaBot <[email protected]>
  • Loading branch information
4 people authored and Iajret committed Jan 3, 2024
1 parent 0754ccd commit d5f140a
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 101 deletions.
10 changes: 10 additions & 0 deletions code/modules/atmospherics/machinery/atmosmachinery.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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
110 changes: 85 additions & 25 deletions code/modules/atmospherics/machinery/components/components_base.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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

/**
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
15 changes: 15 additions & 0 deletions code/modules/atmospherics/machinery/components/fusion/hfr_core.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
21 changes: 3 additions & 18 deletions code/modules/atmospherics/machinery/components/fusion/hfr_parts.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"]"
Expand All @@ -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()
. = ..()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 ..()
Expand All @@ -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"
Expand All @@ -101,24 +102,26 @@ 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!")
return ITEM_INTERACT_SUCCESS
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
Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit d5f140a

Please sign in to comment.