From e4d1772f1bc24efaee87ebacf12a3abd50b9b1b0 Mon Sep 17 00:00:00 2001
From: SkyratBot <59378654+SkyratBot@users.noreply.github.com>
Date: Tue, 16 Mar 2021 22:49:14 +0100
Subject: [PATCH] [MIRROR] Small ventcrawling refactor (#4183)
* Small ventcrawling refactor (#57707)
Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com>
* Small ventcrawling refactor
Co-authored-by: vincentiusvin <54709710+vincentiusvin@users.noreply.github.com>
Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com>
---
code/__DEFINES/atmospherics.dm | 8 +
.../atmospherics/machinery/atmosmachinery.dm | 49 +++---
.../components/unary_devices/cryo.dm | 4 +-
.../components/unary_devices/passive_vent.dm | 4 +-
.../components/unary_devices/vent_pump.dm | 4 +-
.../components/unary_devices/vent_scrubber.dm | 4 +-
code/modules/mob/living/ventcrawling.dm | 153 ++++++++----------
7 files changed, 102 insertions(+), 124 deletions(-)
diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm
index da4c77fd79b..f212ce5a801 100644
--- a/code/__DEFINES/atmospherics.dm
+++ b/code/__DEFINES/atmospherics.dm
@@ -544,3 +544,11 @@ GLOBAL_LIST_INIT(pipe_paint_colors, sortList(list(
#define EUPHORIA_INACTIVE 0
#define EUPHORIA_ACTIVE 1
#define EUPHORIA_LAST_FLAG 2
+
+// Ventcrawling bitflags, handled in var/vent_movement
+///Allows for ventcrawling to occur. All atmospheric machines have this flag on by default. Cryo is the exception
+#define VENTCRAWL_ALLOWED (1<<0)
+///Allows mobs to enter or leave from atmospheric machines. On for passive, unary, and scrubber vents.
+#define VENTCRAWL_ENTRANCE_ALLOWED (1<<1)
+///Used to check if a machinery is visible. Called by update_pipe_vision(). On by default for all except cryo.
+#define VENTCRAWL_CAN_SEE (1<<2)
diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm
index b399ee7dd11..68af7ff11ad 100644
--- a/code/modules/atmospherics/machinery/atmosmachinery.dm
+++ b/code/modules/atmospherics/machinery/atmosmachinery.dm
@@ -56,12 +56,15 @@
///Whether it can be painted
var/paintable = FALSE
- ///Is the thing being rebuilt by SSair or not. Prevents list blaot
+ ///Is the thing being rebuilt by SSair or not. Prevents list bloat
var/rebuilding = FALSE
+ ///The bitflag that's being checked on ventcrawling. Default is to allow ventcrawling and seeing pipes.
+ var/vent_movement = VENTCRAWL_ALLOWED | VENTCRAWL_CAN_SEE
+
/obj/machinery/atmospherics/examine(mob/user)
. = ..()
- if(is_type_in_list(src, GLOB.ventcrawl_machinery) && isliving(user))
+ if((vent_movement & VENTCRAWL_ENTRANCE_ALLOWED) && isliving(user))
var/mob/living/L = user
if(HAS_TRAIT(L, TRAIT_VENTCRAWLER_NUDE) || HAS_TRAIT(L, TRAIT_VENTCRAWLER_ALWAYS))
. += "Alt-click to crawl through it."
@@ -429,6 +432,7 @@
#define VENT_SOUND_DELAY 30
+// Handles mob movement inside a pipenet
/obj/machinery/atmospherics/relaymove(mob/living/user, direction)
direction &= initialize_directions
if(!direction || !(direction in GLOB.cardinals)) //cant go this way.
@@ -439,40 +443,29 @@
var/obj/machinery/atmospherics/target_move = findConnecting(direction, user.ventcrawl_layer)
if(target_move)
- if(target_move.can_crawl_through())
- if(is_type_in_typecache(target_move, GLOB.ventcrawl_machinery))
- user.forceMove(target_move.loc) //handle entering and so on.
- user.visible_message("You hear something squeezing through the ducts...", "You climb out the ventilation system.")
- else
- var/list/pipenetdiff = returnPipenets() ^ target_move.returnPipenets()
- if(pipenetdiff.len)
- user.update_pipe_vision(target_move)
- user.forceMove(target_move)
- user.client.eye = target_move //Byond only updates the eye every tick, This smooths out the movement
- if(world.time - user.last_played_vent > VENT_SOUND_DELAY)
- user.last_played_vent = world.time
- playsound(src, 'sound/machines/ventcrawl.ogg', 50, TRUE, -3)
- else if(is_type_in_typecache(src, GLOB.ventcrawl_machinery) && can_crawl_through()) //if we move in a way the pipe can connect, but doesn't - or we're in a vent
- user.forceMove(loc)
- user.visible_message("You hear something squeezing through the ducts...", "You climb out the ventilation system.")
+ if(target_move.vent_movement & VENTCRAWL_ALLOWED)
+ user.forceMove(target_move)
+ user.client.eye = target_move //Byond only updates the eye every tick, This smooths out the movement
+ var/list/pipenetdiff = returnPipenets() ^ target_move.returnPipenets()
+ if(pipenetdiff.len)
+ user.update_pipe_vision()
+ if(world.time - user.last_played_vent > VENT_SOUND_DELAY)
+ user.last_played_vent = world.time
+ playsound(src, 'sound/machines/ventcrawl.ogg', 50, TRUE, -3)
+ //Would be great if this could be implemented when someone alt-clicks the image.
+ if (target_move.vent_movement & VENTCRAWL_ENTRANCE_ALLOWED)
+ user.handle_ventcrawl(target_move)
//PLACEHOLDER COMMENT FOR ME TO READD THE 1 (?) DS DELAY THAT WAS IMPLEMENTED WITH A... TIMER?
/obj/machinery/atmospherics/AltClick(mob/living/L)
- if(istype(L) && is_type_in_list(src, GLOB.ventcrawl_machinery))
+ if(!(vent_movement & VENTCRAWL_ALLOWED)) // Early return for machines which does not allow ventcrawling at all.
+ return
+ if(istype(L))
L.handle_ventcrawl(src)
return
..()
-/**
- * Getter for vent crawling
- *
- * returns TRUE or FALSE, many devices overrides this (like cryo, or vents)
- * called by relaymove()
- */
-/obj/machinery/atmospherics/proc/can_crawl_through()
- return TRUE
-
/**
* Getter of a list of pipenets
*
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
index 468cf23acb4..cfcf780b0f0 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
@@ -94,6 +94,7 @@
var/obj/item/radio/radio
var/radio_key = /obj/item/encryptionkey/headset_med
var/radio_channel = RADIO_CHANNEL_MEDICAL
+ vent_movement = NONE
/// Visual content - Occupant
var/atom/movable/visual/cryo_occupant/occupant_vis
@@ -510,9 +511,6 @@ GLOBAL_VAR_INIT(cryo_overlay_cover_off, mutable_appearance('icons/obj/cryogenics
/obj/machinery/atmospherics/components/unary/cryo_cell/get_remote_view_fullscreens(mob/user)
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1)
-/obj/machinery/atmospherics/components/unary/cryo_cell/can_crawl_through()
- return // can't ventcrawl in or out of cryo.
-
/obj/machinery/atmospherics/components/unary/cryo_cell/can_see_pipes()
return FALSE // you can't see the pipe network when inside a cryo cell.
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
index 51e833a6e9f..df116cd34ce 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
@@ -10,6 +10,7 @@
shift_underlay_only = FALSE
pipe_state = "pvent"
+ vent_movement = VENTCRAWL_ALLOWED | VENTCRAWL_CAN_SEE | VENTCRAWL_ENTRANCE_ALLOWED
/obj/machinery/atmospherics/components/unary/passive_vent/update_icon_nopipes()
cut_overlays()
@@ -28,9 +29,6 @@
air_update_turf(FALSE, FALSE)
update_parents()
-/obj/machinery/atmospherics/components/unary/passive_vent/can_crawl_through()
- return TRUE
-
/obj/machinery/atmospherics/components/unary/passive_vent/layer2
piping_layer = 2
icon_state = "passive_vent_map-2"
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
index 99c01dbdc14..c7ad0fd35f9 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
@@ -33,6 +33,7 @@
var/radio_filter_in
pipe_state = "uvent"
+ vent_movement = VENTCRAWL_ALLOWED | VENTCRAWL_CAN_SEE | VENTCRAWL_ENTRANCE_ALLOWED
/obj/machinery/atmospherics/components/unary/vent_pump/New()
if(!id_tag)
@@ -286,9 +287,6 @@
. = ..()
update_icon_nopipes()
-/obj/machinery/atmospherics/components/unary/vent_pump/can_crawl_through()
- return !welded
-
/obj/machinery/atmospherics/components/unary/vent_pump/attack_alien(mob/user, list/modifiers)
if(!welded || !(do_after(user, 20, target = src)))
return
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
index 084ae919afd..f31f82aedc4 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
@@ -28,6 +28,7 @@
var/radio_filter_in
pipe_state = "scrubber"
+ vent_movement = VENTCRAWL_ALLOWED | VENTCRAWL_CAN_SEE | VENTCRAWL_ENTRANCE_ALLOWED
/obj/machinery/atmospherics/components/unary/vent_scrubber/New()
if(!id_tag)
@@ -295,9 +296,6 @@
if(welded)
. += "It seems welded shut."
-/obj/machinery/atmospherics/components/unary/vent_scrubber/can_crawl_through()
- return !welded
-
/obj/machinery/atmospherics/components/unary/vent_scrubber/attack_alien(mob/user, list/modifiers)
if(!welded || !(do_after(user, 20, target = src)))
return
diff --git a/code/modules/mob/living/ventcrawling.dm b/code/modules/mob/living/ventcrawling.dm
index 49b4d12ec45..4adf7dbe5a4 100644
--- a/code/modules/mob/living/ventcrawling.dm
+++ b/code/modules/mob/living/ventcrawling.dm
@@ -1,12 +1,12 @@
+// VENTCRAWLING
+// Handles the entrance and exit on ventcrawling
+/mob/living/proc/handle_ventcrawl(obj/machinery/atmospherics/components/ventcrawl_target)
+ // Being able to always ventcrawl trumps being only able to ventcrawl when wearing nothing
+ var/required_nudity = HAS_TRAIT(src, TRAIT_VENTCRAWLER_NUDE) && !HAS_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS)
+ // Cache the vent_movement bitflag var from atmos machineries
+ var/vent_movement = ventcrawl_target.vent_movement
-GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
- /obj/machinery/atmospherics/components/unary/vent_pump,
- /obj/machinery/atmospherics/components/unary/vent_scrubber)))
-
-//VENTCRAWLING
-
-/mob/living/proc/handle_ventcrawl(atom/A)
- if(!Adjacent(A))
+ if(!Adjacent(ventcrawl_target))
return
if(!HAS_TRAIT(src, TRAIT_VENTCRAWLER_NUDE) && !HAS_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS))
return
@@ -14,7 +14,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
to_chat(src, "You must be conscious to do this!")
return
if(HAS_TRAIT(src, TRAIT_IMMOBILIZED))
- to_chat(src, "You can't move into the vent!")
+ to_chat(src, "You currently can't move into the vent!")
return
if(HAS_TRAIT(src, TRAIT_HANDS_BLOCKED))
to_chat(src, "You need to be able to use your hands to ventcrawl!")
@@ -25,49 +25,41 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
if(buckled)
to_chat(src, "You can't vent crawl while buckled!")
return
+ if(iscarbon(src) && required_nudity)
+ if(length(get_equipped_items(include_pockets = TRUE)) || get_num_held_items())
+ to_chat(src, "You can't crawl around in the ventilation ducts with items!")
+ return
+ if(ventcrawl_target.welded)
+ to_chat(src, "You can't crawl around a welded vent!")
+ return
- var/obj/machinery/atmospherics/components/unary/vent_found
-
-
- if(A)
- vent_found = A
- if(!istype(vent_found) || !vent_found.can_crawl_through())
- vent_found = null
-
- if(!vent_found)
- for(var/obj/machinery/atmospherics/machine in range(1,src))
- if(is_type_in_typecache(machine, GLOB.ventcrawl_machinery))
- vent_found = machine
-
- if(!vent_found.can_crawl_through())
- vent_found = null
-
- if(vent_found)
- break
-
- // Being able to always ventcrawl trumps being only able to ventcrawl when wearing nothing
- var/required_nudity = HAS_TRAIT(src, TRAIT_VENTCRAWLER_NUDE) && !HAS_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS)
-
- if(vent_found)
- var/datum/pipeline/vent_found_parent = vent_found.parents[1]
- if(vent_found_parent && (vent_found_parent.members.len || vent_found_parent.other_atmosmch))
- visible_message("[src] begins climbing into the ventilation system..." ,"You begin climbing into the ventilation system...")
-
- if(!do_after(src, 25, target = vent_found))
- return
-
+ if(vent_movement & VENTCRAWL_ENTRANCE_ALLOWED)
+ //Handle the exit here
+ if(HAS_TRAIT(src, TRAIT_MOVE_VENTCRAWLING) && istype(loc, /obj/machinery/atmospherics) && movement_type & VENTCRAWLING)
+ visible_message("[src] begins climbing out from the ventilation system..." ,"You begin climbing out from the ventilation system...")
if(!client)
return
+ visible_message("[src] scrambles out from the ventilation ducts!","You out from the ventilation ducts.")
+ forceMove(ventcrawl_target.loc)
+ REMOVE_TRAIT(src, TRAIT_MOVE_VENTCRAWLING, VENTCRAWLING_TRAIT)
+ update_pipe_vision()
- if(iscarbon(src) && required_nudity)
- if(length(get_equipped_items(include_pockets = TRUE)) || get_num_held_items())
- to_chat(src, "You can't crawl around in the ventilation ducts with items!")
+ //Entrance here
+ else
+ var/datum/pipeline/vent_parent = ventcrawl_target.parents[1]
+ if(vent_parent && (vent_parent.members.len || vent_parent.other_atmosmch))
+ visible_message("[src] begins climbing into the ventilation system..." ,"You begin climbing into the ventilation system...")
+ if(!do_after(src, 2.5 SECONDS, target = ventcrawl_target))
return
+ if(!client)
+ return
+ visible_message("[src] scrambles into the ventilation ducts!","You climb into the ventilation ducts.")
+ forceMove(ventcrawl_target)
+ ADD_TRAIT(src, TRAIT_MOVE_VENTCRAWLING, VENTCRAWLING_TRAIT)
+ update_pipe_vision()
+ else
+ to_chat(src, "This ventilation duct is not connected to anything!")
- visible_message("[src] scrambles into the ventilation ducts!","You climb into the ventilation ducts.")
- forceMove(vent_found)
- else
- to_chat(src, "This ventilation duct is not connected to anything!")
/mob/living/simple_animal/slime/handle_ventcrawl(atom/A)
if(buckled)
@@ -75,47 +67,40 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
return
return ..()
-
-/mob/living/proc/add_ventcrawl(obj/machinery/atmospherics/starting_machine)
- if(!istype(starting_machine) || !starting_machine.can_see_pipes())
- return
- var/list/totalMembers = list()
-
- for(var/datum/pipeline/P in starting_machine.returnPipenets())
- totalMembers += P.members
- totalMembers += P.other_atmosmch
-
- if(!totalMembers.len)
- return
-
- if(client)
- for(var/X in totalMembers)
- var/obj/machinery/atmospherics/A = X //all elements in totalMembers are necessarily of this type.
- if(in_view_range(client.mob, A))
- if(!A.pipe_vision_img)
- A.pipe_vision_img = image(A, A.loc, layer = ABOVE_HUD_LAYER, dir = A.dir)
- A.pipe_vision_img.plane = ABOVE_HUD_PLANE
- client.images += A.pipe_vision_img
- pipes_shown += A.pipe_vision_img
- ADD_TRAIT(src, TRAIT_MOVE_VENTCRAWLING, VENTCRAWLING_TRAIT)
-
-/mob/living/proc/remove_ventcrawl()
- if(client)
+/**
+ * Everything related to pipe vision on ventcrawling is handled by update_pipe_vision().
+ * Called on exit, entrance, and pipenet differences (e.g. moving to a new pipenet).
+ * One important thing to note however is that the movement of the client's eye is handled by the relaymove() proc in /obj/machinery/atmospherics.
+ * We move first and then call update. Dont flip this around
+ */
+/mob/living/proc/update_pipe_vision()
+ // Take the pipe images from the client
+ if (!isnull(client))
for(var/image/current_image in pipes_shown)
client.images -= current_image
- pipes_shown.len = 0
- REMOVE_TRAIT(src, TRAIT_MOVE_VENTCRAWLING, VENTCRAWLING_TRAIT)
+ pipes_shown.len = 0
+ // Give the pipe images to the client
+ if(HAS_TRAIT(src, TRAIT_MOVE_VENTCRAWLING) && istype(loc, /obj/machinery/atmospherics) && movement_type & VENTCRAWLING)
+ var/list/total_members = list()
+ var/obj/machinery/atmospherics/current_location = loc
+ for(var/datum/pipeline/location_pipeline in current_location.returnPipenets())
+ total_members += location_pipeline.members
+ total_members += location_pipeline.other_atmosmch
+ if(!total_members.len)
+ return
+ if(client)
+ for(var/obj/machinery/atmospherics/pipenet_part in total_members)
+ // If the machinery is not in view or is not meant to be seen, continue
+ if(!in_view_range(client.mob, pipenet_part))
+ continue
+ if(!pipenet_part.vent_movement & VENTCRAWL_CAN_SEE)
+ continue
-//OOP
-/atom/proc/update_pipe_vision(atom/new_loc = null)
- return
-
-/mob/living/update_pipe_vision(atom/new_loc = null)
- . = loc
- if(new_loc)
- . = new_loc
- remove_ventcrawl()
- add_ventcrawl(.)
+ if(!pipenet_part.pipe_vision_img)
+ pipenet_part.pipe_vision_img = image(pipenet_part, pipenet_part.loc, layer = ABOVE_HUD_LAYER, dir = pipenet_part.dir)
+ pipenet_part.pipe_vision_img.plane = ABOVE_HUD_PLANE
+ client.images += pipenet_part.pipe_vision_img
+ pipes_shown += pipenet_part.pipe_vision_img