[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>
This commit is contained in:
SkyratBot
2021-03-16 21:49:14 +00:00
committed by GitHub
co-authored by Mothblocks vincentiusvin
parent 2077bd9c5e
commit e4d1772f1b
7 changed files with 102 additions and 124 deletions
+8
View File
@@ -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)
@@ -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))
. += "<span class='notice'>Alt-click to crawl through it.</span>"
@@ -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("<span class='notice'>You hear something squeezing through the ducts...</span>", "<span class='notice'>You climb out the ventilation system.</span>")
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("<span class='notice'>You hear something squeezing through the ducts...</span>", "<span class='notice'>You climb out the ventilation system.</span>")
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
*
@@ -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.
@@ -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"
@@ -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
@@ -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
+69 -84
View File
@@ -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, "<span class='warning'>You must be conscious to do this!</span>")
return
if(HAS_TRAIT(src, TRAIT_IMMOBILIZED))
to_chat(src, "<span class='warning'>You can't move into the vent!</span>")
to_chat(src, "<span class='warning'>You currently can't move into the vent!</span>")
return
if(HAS_TRAIT(src, TRAIT_HANDS_BLOCKED))
to_chat(src, "<span class='warning'>You need to be able to use your hands to ventcrawl!</span>")
@@ -25,49 +25,41 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
if(buckled)
to_chat(src, "<span class='warning'>You can't vent crawl while buckled!</span>")
return
if(iscarbon(src) && required_nudity)
if(length(get_equipped_items(include_pockets = TRUE)) || get_num_held_items())
to_chat(src, "<span class='warning'>You can't crawl around in the ventilation ducts with items!</span>")
return
if(ventcrawl_target.welded)
to_chat(src, "<span class='warning'>You can't crawl around a welded vent!</span>")
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("<span class='notice'>[src] begins climbing into the ventilation system...</span>" ,"<span class='notice'>You begin climbing into the ventilation system...</span>")
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("<span class='notice'>[src] begins climbing out from the ventilation system...</span>" ,"<span class='notice'>You begin climbing out from the ventilation system...</span>")
if(!client)
return
visible_message("<span class='notice'>[src] scrambles out from the ventilation ducts!</span>","<span class='notice'>You out from the ventilation ducts.</span>")
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, "<span class='warning'>You can't crawl around in the ventilation ducts with items!</span>")
//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("<span class='notice'>[src] begins climbing into the ventilation system...</span>" ,"<span class='notice'>You begin climbing into the ventilation system...</span>")
if(!do_after(src, 2.5 SECONDS, target = ventcrawl_target))
return
if(!client)
return
visible_message("<span class='notice'>[src] scrambles into the ventilation ducts!</span>","<span class='notice'>You climb into the ventilation ducts.</span>")
forceMove(ventcrawl_target)
ADD_TRAIT(src, TRAIT_MOVE_VENTCRAWLING, VENTCRAWLING_TRAIT)
update_pipe_vision()
else
to_chat(src, "<span class='warning'>This ventilation duct is not connected to anything!</span>")
visible_message("<span class='notice'>[src] scrambles into the ventilation ducts!</span>","<span class='notice'>You climb into the ventilation ducts.</span>")
forceMove(vent_found)
else
to_chat(src, "<span class='warning'>This ventilation duct is not connected to anything!</span>")
/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