From 8f8bfb22efcb93daa31f8ad018bedf045364041b Mon Sep 17 00:00:00 2001 From: Leland Kemble <70413276+lelandkemble@users.noreply.github.com> Date: Fri, 10 Oct 2025 18:16:35 -0400 Subject: [PATCH] Allows head-equippable items that are not /obj/item/clothing to be attached to /datum/component/hat_stabilizer (#93345) ## About The Pull Request the `/datum/component/hat_stabilizer` component, which is the thing on the magnate MODsuit(and apparently on other spacesuits(and wigs)) that allows you to attach an additional piece of headwear on top of the helm, was `istype()`ed to only allowing `/obj/item/clothing`. This prevented many non- `/clothing` items from being attached, despite being equippable to the head, the only one of which I care about being flowers. This pr changes the `istype()` check to checking for the head slot flag, and modifies surrounding logic to account for this. The only items I can think of that are non-clothing and are equippable to the head are various flowers and `mob_holder`s for various animals. Also fixes an unrelated bug where updating the appearance of the holding item would change the offset of any loose-hat holders over and over again, causing it to move around over your head if you, for example, toggled a MOD flashlight on and off repeatedly. Also fixes an unrelated bug where the hat taken off would never be put in your hands when it was seemingly intended to, due to always returning the hat rather than `put_in_active_hand()` (unless the parent isn't clothing, but there's no non-clothing items with the component attached) ## Why It's Good For The Game I want to put flowers on my helmet, and I don't see any possible negative ramifications. ## Changelog :cl: qol: Flowers can now be attached to space helmets. qol: Taking hats off of helmets will now put them in your hand. fix: MOD flashlights won't move hats on them when toggling. /:cl: --- code/datums/components/hat_stabilizer.dm | 45 ++++++++++++++---------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/code/datums/components/hat_stabilizer.dm b/code/datums/components/hat_stabilizer.dm index 44545f273a4..b7d1a4a3ce2 100644 --- a/code/datums/components/hat_stabilizer.dm +++ b/code/datums/components/hat_stabilizer.dm @@ -2,7 +2,7 @@ /datum/component/hat_stabilizer dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS /// Currently "stored" hat. No armor or function will be inherited, only the icon and cover flags. - var/obj/item/clothing/head/attached_hat + var/obj/item/attached_hat /// If TRUE, the hat will fall to the ground when the owner does so. It can also be shot off. var/loose_hat = FALSE /// Original cover flags for the helmet, before a hat is placed @@ -12,6 +12,8 @@ var/use_worn_icon = TRUE /// Pixel z offset for the hat var/pixel_z_offset + /// Which way a loose hat is offset + var/head_angle = 1 /datum/component/hat_stabilizer/Initialize(use_worn_icon = FALSE, pixel_z_offset = 0, loose_hat = FALSE) if(!ismovable(parent)) @@ -114,7 +116,7 @@ if(loose_hat) var/matrix/tilt_trix = matrix(worn_overlay.transform) var/angle = 5 - tilt_trix.Turn(angle * pick(1, -1)) + tilt_trix.Turn(angle * head_angle) worn_overlay.transform = tilt_trix worn_overlay.pixel_z = pixel_z_offset + attached_hat.worn_y_offset overlays += worn_overlay @@ -132,7 +134,7 @@ if(loose_hat) var/matrix/tilt_trix = matrix(worn_overlay.transform) var/angle = 5 - tilt_trix.Turn(angle * pick(1, -1)) + tilt_trix.Turn(angle * head_angle) worn_overlay.transform = tilt_trix worn_overlay.pixel_z = pixel_z_offset + attached_hat.worn_y_offset overlays += worn_overlay @@ -147,41 +149,44 @@ SIGNAL_HANDLER var/atom/movable/movable_parent = parent - if(!istype(hitting_item, /obj/item/clothing/head)) + if(!(hitting_item.slot_flags & ITEM_SLOT_HEAD)) return if(attached_hat) movable_parent.balloon_alert(user, "hat already attached!") return + if(isclothing(hitting_item)) + var/obj/item/clothing/hat = hitting_item + if(hat.clothing_flags & STACKABLE_HELMET_EXEMPT) + movable_parent.balloon_alert(user, "invalid hat!") + return - var/obj/item/clothing/hat = hitting_item - if(hat.clothing_flags & STACKABLE_HELMET_EXEMPT) - movable_parent.balloon_alert(user, "invalid hat!") + if(!user.transferItemToLoc(hitting_item, parent, force = FALSE, silent = TRUE)) return - if(!user.transferItemToLoc(hat, parent, force = FALSE, silent = TRUE)) - return + attach_hat(hitting_item, user) - attach_hat(hat, user) - -/datum/component/hat_stabilizer/proc/attach_hat(obj/item/clothing/hat, mob/user) +/datum/component/hat_stabilizer/proc/attach_hat(obj/item/hat, mob/user) var/atom/movable/movable_parent = parent attached_hat = hat RegisterSignal(hat, COMSIG_MOVABLE_MOVED, PROC_REF(on_hat_movement)) + head_angle = pick(1, -1) if (!isnull(user)) movable_parent.balloon_alert(user, "hat attached") - if (!istype(parent, /obj/item/clothing)) + if (!isclothing(parent)) movable_parent.update_appearance() return var/obj/item/clothing/apparel = parent - apparel.attach_clothing_traits(attached_hat.clothing_traits) + if(isclothing(attached_hat)) + var/obj/item/clothing/realhat = attached_hat + apparel.attach_clothing_traits(realhat.clothing_traits) + apparel.visor_flags_cover |= realhat.visor_flags_cover former_flags = apparel.flags_cover former_visor_flags = apparel.visor_flags_cover apparel.flags_cover |= attached_hat.flags_cover - apparel.visor_flags_cover |= attached_hat.visor_flags_cover apparel.update_appearance() if (ismob(apparel.loc)) @@ -220,14 +225,16 @@ else movable_parent.balloon_alert_to_viewers("the hat falls to the floor!") - if (!istype(parent, /obj/item/clothing)) + if (!isclothing(parent)) attached_hat = null movable_parent.update_appearance() return var/former_hat = attached_hat var/obj/item/clothing/apparel = parent - apparel.detach_clothing_traits(attached_hat.clothing_traits) + if(isclothing(attached_hat)) + var/obj/item/clothing/truehat = attached_hat + apparel.detach_clothing_traits(truehat.clothing_traits) apparel.flags_cover = former_flags apparel.visor_flags_cover = former_visor_flags apparel.update_appearance() @@ -235,8 +242,8 @@ if (ismob(apparel.loc)) var/mob/wearer = apparel.loc wearer.update_clothing(wearer.get_slot_by_item(apparel)) - - return former_hat + if(isnull(user)) + return former_hat /datum/component/hat_stabilizer/proc/on_requesting_context_from_item(atom/source, list/context, obj/item/held_item, mob/user) SIGNAL_HANDLER