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