diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index f5e8a30b70c..6aff54abbb5 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -390,6 +390,3 @@
/// Possible value of [/atom/movable/buckle_lying]. If set to a different (positive-or-zero) value than this, the buckling thing will force a lying angle on the buckled.
#define NO_BUCKLE_LYING -1
-// Return values for [/mob/living/proc/handle_ventcrawl()]
-#define VENTCRAWL_IN_SUCCESS 1
-#define VENTCRAWL_OUT_SUCCESS 2
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
index 73f0605413a..9f1484930f8 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
@@ -147,9 +147,9 @@
stat("Resources:",resources)
-/mob/living/simple_animal/hostile/swarmer/handle_ventcrawl(obj/machinery/atmospherics/ventcrawl_target)
+/mob/living/simple_animal/hostile/swarmer/move_into_vent(obj/machinery/atmospherics/ventcrawl_target, message = TRUE)
. = ..()
- if(. == VENTCRAWL_IN_SUCCESS && light_on)
+ if(. && light_on)
ToggleLight()
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 6a615a761be..836eeb0e78f 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -1275,8 +1275,7 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/g
return
-/// Conditional proc that allows ventcrawling with this item, if it has TRAIT_VENTCRAWLER_ITEM_BASED trait.
-/// Always allows by default.
+/// Conditional proc that allows ventcrawling with an item, if it has trait TRAIT_VENTCRAWLER_ITEM_BASED.
/obj/item/proc/used_for_ventcrawling(mob/living/user, provide_feedback = TRUE)
- return TRUE
+ return FALSE
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index 42318e8bed9..f7fcab7fa10 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -867,18 +867,18 @@
clothing_traits = list(TRAIT_VENTCRAWLER_ITEM_BASED)
-/obj/item/clothing/under/contortionist/used_for_ventcrawling(mob/living/user, provide_feedback = TRUE)
- // Allowed to wear: glasses, shoes, gloves, pockets, mask, and jumpsuit (obviously)
- var/slots_must_be_empty = ITEM_SLOT_BACK|ITEM_SLOT_BELT|ITEM_SLOT_HEAD|ITEM_SLOT_CLOTH_OUTER|ITEM_SLOT_HANDS|ITEM_SLOT_HANDCUFFED|ITEM_SLOT_LEGCUFFED
-
- for(var/obj/item/item as anything in user.get_equipped_items(include_hands = TRUE))
- if(item.slot_flags & slots_must_be_empty)
- if(provide_feedback)
- to_chat(user, span_warning("Вы не можете ползать по вентиляции с [item.name]."))
- return FALSE
+/// Allowed to wear: glasses, shoes, gloves, mask, ears, pockets, id, pda and jumpsuit (obviously)
+#define CONTORTIONIST_ALLOWED_SLOTS (ITEM_SLOT_CLOTH_INNER|ITEM_SLOT_ID|ITEM_SLOT_PDA|ITEM_SLOT_GLOVES|ITEM_SLOT_FEET|ITEM_SLOT_MASK|ITEM_SLOT_EYES|ITEM_SLOT_EARS|ITEM_SLOT_POCKETS)
+/obj/item/clothing/under/contortionist/used_for_ventcrawling(mob/living/user, provide_feedback = TRUE)
+ if(user.get_equipped_slots(include_hands = TRUE) & ~CONTORTIONIST_ALLOWED_SLOTS)
+ if(provide_feedback)
+ to_chat(user, span_warning("Вы можете ползать по вентиляции только с перчатками, обувью, маской, очками, наушниками, а также комбинезоном с ID-картой и PDA."))
+ return FALSE
return TRUE
+#undef CONTORTIONIST_ALLOWED_SLOTS
+
/obj/item/clothing/under/cursedclown
name = "cursed clown suit"
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index 799cf7cd771..750c6ae8417 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -616,11 +616,10 @@
* and not actually wearing it in any REAL equipment slot.
*/
/mob/proc/is_general_slot(slot)
- return (slot & (ITEM_SLOT_HANDS|ITEM_SLOT_POCKETS|ITEM_SLOT_BACKPACK|ITEM_SLOT_HANDCUFFED|ITEM_SLOT_LEGCUFFED))
+ return (slot & (ITEM_SLOT_HANDS|ITEM_SLOT_POCKETS|ITEM_SLOT_BACKPACK|ITEM_SLOT_HANDCUFFED|ITEM_SLOT_LEGCUFFED|ITEM_SLOT_ACCESSORY))
-//Outdated but still in use apparently. This should at least be a human proc.
-//Daily reminder to murder this - Remie.
+/// Collects all items in possibly equipped slots.
/mob/proc/get_equipped_items(include_pockets = FALSE, include_hands = FALSE)
var/list/items = list()
if(back)
@@ -635,6 +634,20 @@
return items
+/// Same as above but we get slots, not items.
+/mob/proc/get_equipped_slots(include_pockets = FALSE, include_hands = FALSE)
+ . = NONE
+ if(back)
+ . |= ITEM_SLOT_BACK
+ if(wear_mask)
+ . |= ITEM_SLOT_MASK
+ if(include_hands)
+ if(l_hand)
+ . |= ITEM_SLOT_HAND_LEFT
+ if(r_hand)
+ . |= ITEM_SLOT_HAND_RIGHT
+
+
/mob/proc/get_all_slots()
return list(wear_mask, back, l_hand, r_hand)
diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
index 0e312050531..fc08585f6a6 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
@@ -154,3 +154,13 @@
items += l_store
return items
+
+/mob/living/carbon/alien/humanoid/get_equipped_slots(include_pockets = FALSE, include_hands = FALSE)
+ . = ..()
+ if(!include_pockets)
+ return .
+ if(r_store)
+ . |= ITEM_SLOT_POCKET_RIGHT
+ if(l_store)
+ . |= ITEM_SLOT_POCKET_LEFT
+
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index ee5d86ac819..a9bd98bbde5 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -609,6 +609,37 @@
return items
+/mob/living/carbon/human/get_equipped_slots(include_pockets = FALSE, include_hands = FALSE)
+ . = ..()
+ if(belt)
+ . |= ITEM_SLOT_BELT
+ if(l_ear)
+ . |= ITEM_SLOT_EAR_LEFT
+ if(r_ear)
+ . |= ITEM_SLOT_EAR_RIGHT
+ if(glasses)
+ . |= ITEM_SLOT_EYES
+ if(gloves)
+ . |= ITEM_SLOT_GLOVES
+ if(neck)
+ . |= ITEM_SLOT_NECK
+ if(shoes)
+ . |= ITEM_SLOT_FEET
+ if(wear_id)
+ . |= ITEM_SLOT_ID
+ if(wear_pda)
+ . |= ITEM_SLOT_PDA
+ if(w_uniform)
+ . |= ITEM_SLOT_CLOTH_INNER
+ if(include_pockets)
+ if(r_store)
+ . |= ITEM_SLOT_POCKET_RIGHT
+ if(l_store)
+ . |= ITEM_SLOT_POCKET_LEFT
+ if(s_store)
+ . |= ITEM_SLOT_SUITSTORE
+
+
/mob/living/carbon/human/equipped_speed_mods()
. = ..()
for(var/obj/item/thing as anything in get_equipped_items())
diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm
index 9bdd0fb7d23..8685bd8db8c 100644
--- a/code/modules/mob/living/carbon/inventory.dm
+++ b/code/modules/mob/living/carbon/inventory.dm
@@ -496,6 +496,14 @@
return items
+/mob/living/carbon/get_equipped_slots(include_pockets = FALSE, include_hands = FALSE)
+ . = ..()
+ if(wear_suit)
+ . |= ITEM_SLOT_CLOTH_OUTER
+ if(head)
+ . |= ITEM_SLOT_HEAD
+
+
/mob/living/carbon/update_equipment_speed_mods()
. = ..()
update_limbless_slowdown() // in case we get crutches
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 7e74f02cba6..2b3aeae4257 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -193,11 +193,12 @@
return TRUE
-/mob/living/silicon/handle_ventcrawl(obj/machinery/atmospherics/ventcrawl_target)
+/mob/living/silicon/move_into_vent(obj/machinery/atmospherics/ventcrawl_target, message = TRUE)
. = ..()
- if(. == VENTCRAWL_IN_SUCCESS && inventory_head)
- drop_hat()
- visible_message("[name] опрокинул шляпу при залезании в вентиляцию!", "Помеха корпуса была утеряна.")
+ if(. && inventory_head)
+ drop_hat(drop_on_turf = TRUE)
+ if(message)
+ ventcrawl_target.visible_message("[name] опрокинул шляпу при залезании в вентиляцию!")
/mob/living/silicon/robot/welder_act(mob/user, obj/item/I)
diff --git a/code/modules/mob/living/silicon/silicon_hat.dm b/code/modules/mob/living/silicon/silicon_hat.dm
index 94abb2e102f..9a137255af8 100644
--- a/code/modules/mob/living/silicon/silicon_hat.dm
+++ b/code/modules/mob/living/silicon/silicon_hat.dm
@@ -235,9 +235,13 @@
return TRUE
-/mob/living/silicon/proc/drop_hat()
+
+/mob/living/silicon/proc/drop_hat(drop_on_turf = FALSE)
if(inventory_head)
- drop_item_ground(inventory_head)
+ if(drop_on_turf)
+ transfer_item_to_loc(inventory_head, get_turf(src))
+ else
+ drop_item_ground(inventory_head)
null_hat()
regenerate_icons()
diff --git a/code/modules/mob/living/ventcrawling.dm b/code/modules/mob/living/ventcrawling.dm
index 4b9476d89cb..4e7980f1115 100644
--- a/code/modules/mob/living/ventcrawling.dm
+++ b/code/modules/mob/living/ventcrawling.dm
@@ -46,7 +46,7 @@
if(HAS_TRAIT(src, TRAIT_VENTCRAWLER_ITEM_BASED))
var/item_allowed = FALSE
- for(var/obj/item/item as anything in get_equipped_items(include_pockets = TRUE, include_hands = TRUE))
+ for(var/obj/item/item as anything in get_equipped_items(include_pockets = TRUE))
if(item.used_for_ventcrawling(src, provide_feedback))
item_allowed = TRUE
break
@@ -64,20 +64,19 @@
//Handle the exit here
if(HAS_TRAIT(src, TRAIT_MOVE_VENTCRAWLING) && is_ventcrawling(src) && (movement_type & VENTCRAWLING))
if(!can_ventcrawl(ventcrawl_target))
- return
+ return FALSE
to_chat(src, span_notice("Вы начинаете вылезать из вентиляции..."))
if(!do_after(src, 1 SECONDS, target = ventcrawl_target))
- return
+ return FALSE
if(has_client && isnull(client))
- return
+ return FALSE
if(!can_ventcrawl(ventcrawl_target))
- return
- stop_ventcrawling()
- return VENTCRAWL_OUT_SUCCESS
+ return FALSE
+ return stop_ventcrawling(ventcrawl_target)
//Entrance here
if(!can_ventcrawl(ventcrawl_target, entering = TRUE))
- return
+ return FALSE
var/crawl_overlay = image('icons/effects/vent_indicator.dmi', "arrow", ABOVE_MOB_LAYER, dir = get_dir(src.loc, ventcrawl_target.loc))
//ventcrawl_target.flick_overlay_static(image('icons/effects/vent_indicator.dmi', "arrow", ABOVE_MOB_LAYER, dir = get_dir(src.loc, ventcrawl_target.loc)), 2 SECONDS)
@@ -88,15 +87,14 @@
)
if(!do_after(src, 4.5 SECONDS, target = ventcrawl_target))
ventcrawl_target?.cut_overlay(crawl_overlay)
- return
+ return FALSE
ventcrawl_target?.cut_overlay(crawl_overlay)
if(has_client && isnull(client))
- return
+ return FALSE
if(!can_ventcrawl(ventcrawl_target, entering = TRUE))
- return
+ return FALSE
ventcrawl_target.flick_overlay_static(image('icons/effects/vent_indicator.dmi', "insert", ABOVE_MOB_LAYER), 1 SECONDS)
- move_into_vent(ventcrawl_target)
- return VENTCRAWL_IN_SUCCESS
+ return move_into_vent(ventcrawl_target)
/**
@@ -104,8 +102,13 @@
*
* Arguments:
* * ventcrawl_target - The vent into which we are moving the mob
+ * * message - if TRUE shows visible message to everyone
+ *
+ * Returns `TRUE` on success.
*/
/mob/living/proc/move_into_vent(obj/machinery/atmospherics/ventcrawl_target, message = TRUE)
+ SHOULD_CALL_PARENT(TRUE)
+
if(message)
visible_message(
span_notice("[name] залез[genderize_ru(gender, "", "ла", "ло", "ли")] в вентиляцию!"),
@@ -114,15 +117,21 @@
abstract_move(ventcrawl_target)
ADD_TRAIT(src, TRAIT_MOVE_VENTCRAWLING, VENTCRAWLING_TRAIT)
update_pipe_vision()
+ return TRUE
/**
* Moves living mob to the turf contents and cleanse ventcrawling stuff
*
* Arguments:
+ * * ventcrawl_target - The vent from which we are moved from
* * message - if TRUE shows visible message to everyone
+ *
+ * Returns `TRUE` on success.
*/
-/mob/living/proc/stop_ventcrawling(message = TRUE)
+/mob/living/proc/stop_ventcrawling(obj/machinery/atmospherics/ventcrawl_target, message = TRUE)
+ SHOULD_CALL_PARENT(TRUE)
+
if(!is_ventcrawling(src))
return FALSE
var/turf/new_turf = get_turf(src)