/obj/item/clothing/head/mob_holder -> /obj/item/mob_holder (#91893)

## About The Pull Request
title
## Why It's Good For The Game
it inherits a lot of behavior from clothing which leads to lots of bugs
when it isn't actually clothes, for example: shredded overlays. this
should be better.
probably fixes a bunch of bugs
## Changelog
🆑
code: mob holders are no longer subtypes of clothes, report any issues
/🆑

---------

Co-authored-by: Jacquerel <hnevard@gmail.com>
This commit is contained in:
grungussuss
2025-07-01 16:20:48 +03:00
committed by GitHub
parent 7b8a7e9be6
commit 613581897e
15 changed files with 47 additions and 43 deletions

View File

@@ -269,7 +269,7 @@ GLOBAL_LIST_INIT(turfs_pass_meteor, typecacheof(list(
#define isclothing(A) (istype(A, /obj/item/clothing))
#define ispickedupmob(A) (istype(A, /obj/item/clothing/head/mob_holder)) // Checks if clothing item is actually a held mob
#define ispickedupmob(A) (istype(A, /obj/item/mob_holder)) // Checks if clothing item is actually a held mob
#define iscash(A) (istype(A, /obj/item/coin) || istype(A, /obj/item/stack/spacecash) || istype(A, /obj/item/holochip))

View File

@@ -64,14 +64,14 @@
)
. = ..()
set_holdable(list(
/obj/item/clothing/head/mob_holder,
/obj/item/mob_holder,
/obj/item/food/deadmouse
))
/datum/storage/pockets/chefhat/can_insert(obj/item/to_insert, mob/user, messages, force)
. = ..()
if(ispickedupmob(to_insert))
var/obj/item/clothing/head/mob_holder/mausholder = to_insert
var/obj/item/mob_holder/mausholder = to_insert
if(locate(/mob/living/basic/mouse) in mausholder.contents)
return
return FALSE

View File

@@ -299,7 +299,7 @@ GLOBAL_LIST_INIT(dye_registry, list(
if(!can_adjust && adjusted == ALT_STYLE) //we deadjust the uniform if it's now unadjustable
toggle_jumpsuit_adjust()
/obj/item/clothing/head/mob_holder/machine_wash(obj/machinery/washing_machine/washer)
/obj/item/mob_holder/machine_wash(obj/machinery/washing_machine/washer)
..()
held_mob.machine_wash(washer)

View File

@@ -199,7 +199,7 @@
user.visible_message(span_suicide("[user] opens [src] and gets consumed by [p_them()]! It looks like [user.p_theyre()] trying to commit suicide!"))
playsound(user, 'sound/misc/scary_horn.ogg', 70, vary = TRUE)
forceMove(user.drop_location())
var/obj/item/clothing/head/mob_holder/consumed = new(src, user)
var/obj/item/mob_holder/consumed = new(src, user)
consumed.desc = "It's [user.real_name]! It looks like [user.p_they()] committed suicide!"
return OXYLOSS

View File

@@ -47,7 +47,7 @@
/obj/item/clothing/head/utility/chefhat/proc/get_mouse(atom/possible_mouse)
if (!ispickedupmob(possible_mouse))
return
var/obj/item/clothing/head/mob_holder/mousey_holder = possible_mouse
var/obj/item/mob_holder/mousey_holder = possible_mouse
return locate(/mob/living/basic) in mousey_holder.contents
/// Relays emotes emoted by your boss to the hat wearer for full immersion

View File

@@ -73,7 +73,7 @@ GLOBAL_LIST_INIT(typecache_holodeck_linked_floorcheck_ok, typecacheof(list(/turf
///special locs that can mess with derez'ing holo spawned objects
var/list/special_locs = list(
/obj/item/clothing/head/mob_holder,
/obj/item/mob_holder,
)
///TRUE if the holodeck is using extra power because of a program, FALSE otherwise

View File

@@ -214,9 +214,9 @@
. = ..()
if(!QDELETED(src) && gone == myseed)
set_seed(null, FALSE)
if(!istype(gone, /obj/item/clothing/head/mob_holder/snail))
if(!istype(gone, /obj/item/mob_holder/snail))
return
var/obj/item/clothing/head/mob_holder/snail_object = gone
var/obj/item/mob_holder/snail_object = gone
if(snail_object.held_mob)
UnregisterSignal(snail_object.held_mob, list(
COMSIG_LIVING_DEATH,
@@ -1140,7 +1140,7 @@
/obj/machinery/hydroponics/proc/empty_tray(mob/user)
reagents.clear_reagents()
for(var/obj/item/clothing/head/mob_holder/snail/possible_snail in contents)
for(var/obj/item/mob_holder/snail/possible_snail in contents)
possible_snail.forceMove(drop_location())
to_chat(user, span_warning("You empty [src]'s nutrient tank."))
@@ -1274,12 +1274,12 @@
/obj/machinery/hydroponics/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
. = ..()
if(!istype(arrived, /obj/item/clothing/head/mob_holder/snail))
if(!istype(arrived, /obj/item/mob_holder/snail))
return
our_snail = new
vis_contents += our_snail
our_snail.layer = layer + 0.01
var/obj/item/clothing/head/mob_holder/snail = arrived
var/obj/item/mob_holder/snail = arrived
RegisterSignals(snail.held_mob, list(COMSIG_MOVABLE_ATTEMPTED_MOVE, COMSIG_LIVING_DEATH), PROC_REF(remove_snail)) //rip

View File

@@ -75,7 +75,7 @@
/mob/living/basic/bee/mob_pickup(mob/living/picker)
if(flags_1 & HOLOGRAM_1)
return
var/obj/item/clothing/head/mob_holder/destructible/holder = new(get_turf(src), src, held_state, head_icon, held_lh, held_rh, worn_slot_flags)
var/obj/item/mob_holder/destructible/holder = new(get_turf(src), src, held_state, head_icon, held_lh, held_rh, worn_slot_flags)
var/list/reee = list(/datum/reagent/consumable/nutriment/vitamin = 5)
if(beegent)
reee[beegent.type] = 5

View File

@@ -78,7 +78,7 @@
apply_damage(500) //ouch
/mob/living/basic/snail/mob_pickup(mob/living/user)
var/obj/item/clothing/head/mob_holder/snail/holder = new(get_turf(src), src, held_state, head_icon, held_lh, held_rh, worn_slot_flags)
var/obj/item/mob_holder/snail/holder = new(get_turf(src), src, held_state, head_icon, held_lh, held_rh, worn_slot_flags)
var/display_message = "[user] [HAS_TRAIT(src, TRAIT_MOVE_FLOATING) ? "scoops up [src]" : "peels [src] off the ground"]!"
user.visible_message(span_warning(display_message))
user.put_in_hands(holder)
@@ -108,9 +108,9 @@
///snail's custom holder object
/obj/item/clothing/head/mob_holder/snail
/obj/item/mob_holder/snail
/obj/item/clothing/head/mob_holder/snail/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
/obj/item/mob_holder/snail/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
if(!istype(interacting_with, /obj/machinery/hydroponics))
return NONE

View File

@@ -142,8 +142,8 @@
if(!gibbed)
var/make_a_corpse = TRUE
var/place_to_make_corpse = loc
if(istype(loc, /obj/item/clothing/head/mob_holder))//If our mouse is dying in place holder we want to put the dead mouse where the place holder was
var/obj/item/clothing/head/mob_holder/found_holder = loc
if(istype(loc, /obj/item/mob_holder))//If our mouse is dying in place holder we want to put the dead mouse where the place holder was
var/obj/item/mob_holder/found_holder = loc
place_to_make_corpse = found_holder.loc
if(istype(found_holder.loc, /obj/machinery/microwave))//Microwaves gib things that die when cooked, so we don't need to make a dead body too
make_a_corpse = FALSE

View File

@@ -1,6 +1,6 @@
//Generic system for picking up mobs.
//Currently works for head and hands.
/obj/item/clothing/head/mob_holder
/obj/item/mob_holder
name = "bugged mob"
desc = "Yell at coderbrush."
icon = null
@@ -10,8 +10,12 @@
var/mob/living/held_mob
/// True if we've started being destroyed
var/destroying = FALSE
lefthand_file = 'icons/mob/inhands/clothing/hats_lefthand.dmi'
righthand_file = 'icons/mob/inhands/clothing/hats_righthand.dmi'
body_parts_covered = HEAD
slot_flags = ITEM_SLOT_HEAD
/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/held_mob, worn_state, head_icon, lh_icon, rh_icon, worn_slot_flags = NONE)
/obj/item/mob_holder/Initialize(mapload, mob/living/held_mob, worn_state, head_icon, lh_icon, rh_icon, worn_slot_flags = NONE)
if(head_icon)
worn_icon = head_icon
if(worn_state)
@@ -26,13 +30,13 @@
insert_mob(held_mob)
return ..()
/obj/item/clothing/head/mob_holder/Destroy()
/obj/item/mob_holder/Destroy()
destroying = TRUE
if(held_mob)
release()
return ..()
/obj/item/clothing/head/mob_holder/proc/insert_mob(mob/living/new_prisoner)
/obj/item/mob_holder/proc/insert_mob(mob/living/new_prisoner)
if(!istype(new_prisoner))
return FALSE
new_prisoner.setDir(SOUTH)
@@ -44,7 +48,7 @@
desc = new_prisoner.desc
return TRUE
/obj/item/clothing/head/mob_holder/proc/on_mob_deleted()
/obj/item/mob_holder/proc/on_mob_deleted()
SIGNAL_HANDLER
held_mob = null
if (isliving(loc))
@@ -52,10 +56,10 @@
holder.temporarilyRemoveItemFromInventory(src, force = TRUE)
qdel(src)
/obj/item/clothing/head/mob_holder/proc/update_visuals(mob/living/held_guy)
/obj/item/mob_holder/proc/update_visuals(mob/living/held_guy)
appearance = held_guy.appearance
/obj/item/clothing/head/mob_holder/on_thrown(mob/living/carbon/user, atom/target)
/obj/item/mob_holder/on_thrown(mob/living/carbon/user, atom/target)
if((item_flags & ABSTRACT) || HAS_TRAIT(src, TRAIT_NODROP))
return
if(HAS_TRAIT(user, TRAIT_PACIFISM))
@@ -67,12 +71,12 @@
release()
return throw_mob
/obj/item/clothing/head/mob_holder/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change)
/obj/item/mob_holder/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change)
. = ..()
if(held_mob && isturf(loc))
release()
/obj/item/clothing/head/mob_holder/proc/release(display_messages = TRUE)
/obj/item/mob_holder/proc/release(display_messages = TRUE)
if(!held_mob)
if(!destroying)
qdel(src)
@@ -93,31 +97,31 @@
qdel(src)
return TRUE
/obj/item/clothing/head/mob_holder/relaymove(mob/living/user, direction)
/obj/item/mob_holder/relaymove(mob/living/user, direction)
release()
/obj/item/clothing/head/mob_holder/container_resist_act()
/obj/item/mob_holder/container_resist_act()
release()
/obj/item/clothing/head/mob_holder/Exited(atom/movable/gone, direction)
/obj/item/mob_holder/Exited(atom/movable/gone, direction)
. = ..()
if(held_mob == gone)
release()
/obj/item/clothing/head/mob_holder/on_found(mob/finder)
/obj/item/mob_holder/on_found(mob/finder)
if(held_mob?.will_escape_storage())
to_chat(finder, span_warning("\A [held_mob.name] pops out! "))
finder.visible_message(span_warning("\A [held_mob.name] pops out of the container [finder] is opening!"), ignored_mobs = finder)
release(display_messages = FALSE)
return
/obj/item/clothing/head/mob_holder/drone/Initialize(mapload, mob/living/M, worn_state, head_icon, lh_icon, rh_icon, worn_slot_flags = NONE)
/obj/item/mob_holder/drone/Initialize(mapload, mob/living/M, worn_state, head_icon, lh_icon, rh_icon, worn_slot_flags = NONE)
//If we're not being put onto a drone, end it all
if(!isdrone(M))
return INITIALIZE_HINT_QDEL
return ..()
/obj/item/clothing/head/mob_holder/drone/insert_mob(mob/living/new_prisoner)
/obj/item/mob_holder/drone/insert_mob(mob/living/new_prisoner)
. = ..()
if(!isdrone(new_prisoner))
qdel(src)
@@ -125,32 +129,32 @@
name = "drone (hiding)"
desc = "This drone is scared and has curled up into a ball!"
/obj/item/clothing/head/mob_holder/drone/update_visuals(mob/living/contained)
/obj/item/mob_holder/drone/update_visuals(mob/living/contained)
var/mob/living/basic/drone/drone = contained
if(!drone)
return ..()
icon = 'icons/mob/silicon/drone.dmi'
icon_state = "[drone.visualAppearance]_hat"
/obj/item/clothing/head/mob_holder/destructible
/obj/item/mob_holder/destructible
/obj/item/clothing/head/mob_holder/destructible/Destroy()
/obj/item/mob_holder/destructible/Destroy()
if(held_mob)
release(display_messages = TRUE, delete_mob = TRUE)
return ..()
/obj/item/clothing/head/mob_holder/destructible/release(display_messages = TRUE, delete_mob = FALSE)
/obj/item/mob_holder/destructible/release(display_messages = TRUE, delete_mob = FALSE)
if(delete_mob && held_mob)
QDEL_NULL(held_mob)
return ..()
/obj/item/clothing/head/mob_holder/attack_self(mob/user, modifiers)
/obj/item/mob_holder/attack_self(mob/user, modifiers)
. = ..()
if(. || !held_mob) //overriden or mob missing
return
user.UnarmedAttack(held_mob, proximity_flag = TRUE, modifiers = modifiers)
/obj/item/clothing/head/mob_holder/base_item_interaction(mob/living/user, obj/item/tool, list/modifiers)
/obj/item/mob_holder/base_item_interaction(mob/living/user, obj/item/tool, list/modifiers)
. = ..()
if(. || !held_mob) // Another interaction was performed
return

View File

@@ -1955,7 +1955,7 @@ GLOBAL_LIST_EMPTY(fire_appearances)
return ..()
/mob/living/proc/mob_pickup(mob/living/user)
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, held_state, head_icon, held_lh, held_rh, worn_slot_flags)
var/obj/item/mob_holder/holder = new(get_turf(src), src, held_state, head_icon, held_lh, held_rh, worn_slot_flags)
user.visible_message(span_warning("[user] scoops up [src]!"))
user.put_in_hands(holder)

View File

@@ -81,7 +81,7 @@
visible_message(span_notice("[src] dematerialises!"))
stop_pulling()
if(ispickedupmob(loc))
var/obj/item/clothing/head/mob_holder/mob_head = loc
var/obj/item/mob_holder/mob_head = loc
mob_head.release(display_messages = FALSE)
if(client)
client.perspective = EYE_PERSPECTIVE

View File

@@ -10,7 +10,7 @@
continue
wearable_item_paths |= item_path
for(var/obj/item/clothing/clothing_path in (subtypesof(/obj/item/clothing) - typesof(/obj/item/clothing/head/mob_holder) - typesof(/obj/item/clothing/suit/space/santa))) //mob_holder is a psuedo abstract item. santa suit is a VERY SNOWFLAKE admin spawn suit that can hold /every/ possible item.
for(var/obj/item/clothing/clothing_path in (subtypesof(/obj/item/clothing) - typesof(/obj/item/clothing/suit/space/santa))) //santa suit is a VERY SNOWFLAKE admin spawn suit that can hold /every/ possible item.
for(var/path in clothing_path::allowed) //find all usable suit storage stuff.
wearable_item_paths |= path

View File

@@ -342,7 +342,7 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests())
//Needs a linked mecha
returnable_list += typesof(/obj/effect/skyfall_landingzone)
//Expects a mob to holderize, we have nothing to give
returnable_list += typesof(/obj/item/clothing/head/mob_holder)
returnable_list += typesof(/obj/item/mob_holder)
//Needs cards passed into the initilazation args
returnable_list += typesof(/obj/item/toy/cards/cardhand)
//Needs a holodeck area linked to it which is not guarenteed to exist and technically is supposed to have a 1:1 relationship with computer anyway.