diff --git a/code/__DEFINES/strippable.dm b/code/__DEFINES/strippable.dm index 9988861dbf9..bd2a22f77f4 100644 --- a/code/__DEFINES/strippable.dm +++ b/code/__DEFINES/strippable.dm @@ -29,3 +29,6 @@ /// This slot can't be seen, but can be accessed. #define STRIPPABLE_OBSCURING_HIDDEN 2 + +/// This slot can be seen, but cannot be accessed +#define STRIPPABLE_OBSCURING_INACCESSIBLE 3 diff --git a/code/datums/components/bloodysoles.dm b/code/datums/components/bloodysoles.dm index bdd8942f2eb..bc2efb11154 100644 --- a/code/datums/components/bloodysoles.dm +++ b/code/datums/components/bloodysoles.dm @@ -48,7 +48,7 @@ * Returns true if the parent item is obscured by something else that the wielder is wearing */ /datum/component/bloodysoles/proc/is_obscured() - return wielder.check_obscured_slots(TRUE) & equipped_slot || is_under_feet_covered() + return wielder.check_covered_slots() & equipped_slot || is_under_feet_covered() /** * Returns true if the parent item is worn in the ITEM_SLOT_ICLOTHING slot and the @@ -318,7 +318,7 @@ /datum/component/bloodysoles/feet/is_obscured() if(wielder.shoes) return TRUE - return wielder.check_obscured_slots(TRUE) & ITEM_SLOT_FEET + return wielder.check_covered_slots() & ITEM_SLOT_FEET /datum/component/bloodysoles/feet/on_moved(datum/source, OldLoc, Dir, Forced) if(wielder.num_legs < 2) diff --git a/code/datums/elements/strippable.dm b/code/datums/elements/strippable.dm index f4e1707b7b5..7f4d9f97204 100644 --- a/code/datums/elements/strippable.dm +++ b/code/datums/elements/strippable.dm @@ -258,13 +258,17 @@ return finish_equip_mob(equipping, source, user) /datum/strippable_item/mob_item_slot/get_obscuring(atom/source) - if (iscarbon(source)) - var/mob/living/carbon/carbon_source = source - return (carbon_source.check_obscured_slots() & item_slot) \ - ? STRIPPABLE_OBSCURING_COMPLETELY \ - : STRIPPABLE_OBSCURING_NONE + if (!iscarbon(source)) + return STRIPPABLE_OBSCURING_NONE - return FALSE + var/mob/living/carbon/carbon_source = source + if (carbon_source.check_obscured_slots() & item_slot) + return STRIPPABLE_OBSCURING_COMPLETELY + + if (carbon_source.check_covered_slots() & item_slot) + return STRIPPABLE_OBSCURING_INACCESSIBLE + + return STRIPPABLE_OBSCURING_NONE /datum/strippable_item/mob_item_slot/start_unequip(atom/source, mob/user) . = ..() @@ -360,8 +364,8 @@ LAZYSET(result, "interacting", TRUE) var/obscuring = item_data.get_obscuring(owner) - if (obscuring != STRIPPABLE_OBSCURING_NONE) - LAZYSET(result, "obscured", obscuring) + LAZYSET(result, "obscured", obscuring) + if (obscuring != STRIPPABLE_OBSCURING_NONE && obscuring != STRIPPABLE_OBSCURING_INACCESSIBLE) items[strippable_key] = result continue @@ -413,7 +417,8 @@ if (!strippable_item.should_show(owner, user)) return - if (strippable_item.get_obscuring(owner) == STRIPPABLE_OBSCURING_COMPLETELY) + var/obscured = strippable_item.get_obscuring(owner) + if (obscured == STRIPPABLE_OBSCURING_COMPLETELY || obscured == STRIPPABLE_OBSCURING_INACCESSIBLE) return var/item = strippable_item.get_item(owner) @@ -479,7 +484,8 @@ if (!strippable_item.should_show(owner, user)) return - if (strippable_item.get_obscuring(owner) == STRIPPABLE_OBSCURING_COMPLETELY) + var/obscured = strippable_item.get_obscuring(owner) + if (obscured == STRIPPABLE_OBSCURING_COMPLETELY || obscured == STRIPPABLE_OBSCURING_INACCESSIBLE) return var/item = strippable_item.get_item(owner) diff --git a/code/modules/forensics/forensics_helpers.dm b/code/modules/forensics/forensics_helpers.dm index e0edfafc9e6..1285b6eca9e 100644 --- a/code/modules/forensics/forensics_helpers.dm +++ b/code/modules/forensics/forensics_helpers.dm @@ -137,7 +137,7 @@ var/dirty_hands = !!(target_flags & (ITEM_SLOT_GLOVES|ITEM_SLOT_HANDS)) var/dirty_feet = !!(target_flags & ITEM_SLOT_FEET) - var/slots_to_bloody = target_flags & ~check_obscured_slots() + var/slots_to_bloody = target_flags & ~check_covered_slots() var/list/all_worn = get_equipped_items() for(var/obj/item/thing as anything in all_worn) if(thing.slot_flags & slots_to_bloody) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 4d3520f82d0..32012537ef5 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1240,47 +1240,21 @@ /mob/living/carbon/wash(clean_types) . = ..() - // Wash equipped stuff that cannot be covered for(var/obj/item/held_thing in held_items) if(held_thing.wash(clean_types)) . = TRUE - if(back?.wash(clean_types)) - update_worn_back(0) - . = TRUE - - // Check and wash stuff that can be covered - var/obscured = check_obscured_slots() - - if(!(obscured & ITEM_SLOT_HEAD) && head?.wash(clean_types)) - update_worn_head() - . = TRUE - - // If the eyes are covered by anything but glasses, that thing will be covering any potential glasses as well. - if(is_eyes_covered(ITEM_SLOT_MASK|ITEM_SLOT_HEAD) && glasses?.wash(clean_types)) - update_worn_glasses() - . = TRUE - - if(!(obscured & ITEM_SLOT_MASK) && wear_mask?.wash(clean_types)) - update_worn_mask() - . = TRUE - - if(!(obscured & ITEM_SLOT_EARS) && ears?.wash(clean_types)) - update_worn_ears() - . = TRUE - - if(!(obscured & ITEM_SLOT_NECK) && wear_neck?.wash(clean_types)) - update_worn_neck() - . = TRUE - - if(!(obscured & ITEM_SLOT_FEET) && shoes?.wash(clean_types)) - update_worn_shoes() - . = TRUE - - if(!(obscured & ITEM_SLOT_GLOVES) && gloves?.wash(clean_types)) - update_worn_gloves() - . = TRUE + // Check and wash stuff that isn't covered + var/covered = check_covered_slots() + for(var/obj/item/worn as anything in get_equipped_items()) + var/slot = get_slot_by_item(worn) + // Don't wash glasses if something other than them is covering our eyes + if(slot == ITEM_SLOT_EYES && is_eyes_covered(ITEM_SLOT_MASK|ITEM_SLOT_HEAD)) + continue + if(!(covered & slot)) + // /obj/item/wash() already updates our clothing slot + . ||= worn.wash(clean_types) /// if any of our bodyparts are bleeding /mob/living/carbon/proc/is_bleeding() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b8beb0ebc4a..fd1004485f8 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -588,8 +588,7 @@ * Returns false if we couldn't wash our hands due to them being obscured, otherwise true */ /mob/living/carbon/human/proc/wash_hands(clean_types) - var/obscured = check_obscured_slots() - if(obscured & ITEM_SLOT_GLOVES) + if(check_covered_slots() & ITEM_SLOT_GLOVES) return FALSE if(gloves) @@ -610,13 +609,10 @@ if(!is_mouth_covered() && clean_lips()) . = TRUE - if(glasses && is_eyes_covered(ITEM_SLOT_MASK|ITEM_SLOT_HEAD) && glasses.wash(clean_types)) - update_worn_glasses() + if(glasses && !is_eyes_covered(ITEM_SLOT_MASK|ITEM_SLOT_HEAD) && glasses.wash(clean_types)) . = TRUE - var/obscured = check_obscured_slots() - if(wear_mask && !(obscured & ITEM_SLOT_MASK) && wear_mask.wash(clean_types)) - update_worn_mask() + if(wear_mask && !(check_covered_slots() & ITEM_SLOT_MASK) && wear_mask.wash(clean_types)) . = TRUE /** @@ -624,28 +620,11 @@ */ /mob/living/carbon/human/wash(clean_types) . = ..() - - // Wash equipped stuff that cannot be covered - if(wear_suit?.wash(clean_types)) - update_worn_oversuit() - . = TRUE - - if(belt?.wash(clean_types)) - update_worn_belt() - . = TRUE - - // Check and wash stuff that can be covered - var/obscured = check_obscured_slots() - - if(!(obscured & ITEM_SLOT_ICLOTHING) && w_uniform?.wash(clean_types)) - update_worn_undersuit() - . = TRUE - if(!is_mouth_covered() && clean_lips()) . = TRUE // Wash hands if exposed - if(!gloves && (clean_types & CLEAN_TYPE_BLOOD) && blood_in_hands > 0 && !(obscured & ITEM_SLOT_GLOVES)) + if(!gloves && (clean_types & CLEAN_TYPE_BLOOD) && blood_in_hands > 0 && !(check_covered_slots() & ITEM_SLOT_GLOVES)) blood_in_hands = 0 update_worn_gloves() . = TRUE diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 5c49907c6f1..1757432818b 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -673,29 +673,29 @@ /mob/living/carbon/human/proc/burn_clothing(seconds_per_tick, stacks) var/list/burning_items = list() - var/obscured = check_obscured_slots(TRUE) + var/covered = check_covered_slots() //HEAD// - if(glasses && !(obscured & ITEM_SLOT_EYES)) + if(glasses && !(covered & ITEM_SLOT_EYES)) burning_items += glasses - if(wear_mask && !(obscured & ITEM_SLOT_MASK)) + if(wear_mask && !(covered & ITEM_SLOT_MASK)) burning_items += wear_mask - if(wear_neck && !(obscured & ITEM_SLOT_NECK)) + if(wear_neck && !(covered & ITEM_SLOT_NECK)) burning_items += wear_neck - if(ears && !(obscured & ITEM_SLOT_EARS)) + if(ears && !(covered & ITEM_SLOT_EARS)) burning_items += ears if(head) burning_items += head //CHEST// - if(w_uniform && !(obscured & ITEM_SLOT_ICLOTHING)) + if(w_uniform && !(covered & ITEM_SLOT_ICLOTHING)) burning_items += w_uniform if(wear_suit) burning_items += wear_suit //ARMS & HANDS// var/obj/item/clothing/arm_clothes = null - if(gloves && !(obscured & ITEM_SLOT_GLOVES)) + if(gloves && !(covered & ITEM_SLOT_GLOVES)) arm_clothes = gloves else if(wear_suit && ((wear_suit.body_parts_covered & HANDS) || (wear_suit.body_parts_covered & ARMS))) arm_clothes = wear_suit @@ -706,7 +706,7 @@ //LEGS & FEET// var/obj/item/clothing/leg_clothes = null - if(shoes && !(obscured & ITEM_SLOT_FEET)) + if(shoes && !(covered & ITEM_SLOT_FEET)) leg_clothes = shoes else if(wear_suit && ((wear_suit.body_parts_covered & FEET) || (wear_suit.body_parts_covered & LEGS))) leg_clothes = wear_suit diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index 8e21a44de98..bb5575cb111 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -91,7 +91,7 @@ There are several things that need to be remembered: if(update_obscured) update_obscured_slots(uniform.flags_inv) - if(HAS_TRAIT(uniform, TRAIT_NO_WORN_ICON) || (check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_ICLOTHING)) + if(HAS_TRAIT(uniform, TRAIT_NO_WORN_ICON) || (check_obscured_slots() & ITEM_SLOT_ICLOTHING)) return var/target_overlay = uniform.icon_state @@ -201,7 +201,7 @@ There are several things that need to be remembered: if(update_obscured) update_obscured_slots(worn_item.flags_inv) - if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_GLOVES)) + if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots() & ITEM_SLOT_GLOVES)) return var/icon_file = 'icons/mob/clothing/hands.dmi' @@ -252,7 +252,7 @@ There are several things that need to be remembered: if(update_obscured) update_obscured_slots(worn_item.flags_inv) - if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_EYES)) + if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots() & ITEM_SLOT_EYES)) return var/icon_file = 'icons/mob/clothing/eyes.dmi' @@ -281,7 +281,7 @@ There are several things that need to be remembered: if(update_obscured) update_obscured_slots(worn_item.flags_inv) - if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_EARS)) + if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots() & ITEM_SLOT_EARS)) return var/icon_file = 'icons/mob/clothing/ears.dmi' @@ -305,7 +305,7 @@ There are several things that need to be remembered: if(update_obscured) update_obscured_slots(worn_item.flags_inv) - if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_NECK)) + if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots() & ITEM_SLOT_NECK)) return var/icon_file = 'icons/mob/clothing/neck.dmi' @@ -334,7 +334,7 @@ There are several things that need to be remembered: if(update_obscured) update_obscured_slots(worn_item.flags_inv) - if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_FEET)) + if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots() & ITEM_SLOT_FEET)) return var/icon_file = DEFAULT_SHOES_FILE @@ -372,7 +372,7 @@ There are several things that need to be remembered: if(update_obscured) update_obscured_slots(worn_item.flags_inv) - if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_SUITSTORE)) + if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots() & ITEM_SLOT_SUITSTORE)) return var/mutable_appearance/s_store_overlay = worn_item.build_worn_icon(default_layer = SUIT_STORE_LAYER, default_icon_file = 'icons/mob/clothing/belt_mirror.dmi') @@ -394,7 +394,7 @@ There are several things that need to be remembered: if(update_obscured) update_obscured_slots(worn_item.flags_inv) - if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_HEAD)) + if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots() & ITEM_SLOT_HEAD)) return var/icon_file = 'icons/mob/clothing/head/default.dmi' @@ -421,7 +421,7 @@ There are several things that need to be remembered: if(update_obscured) update_obscured_slots(worn_item.flags_inv) - if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_BELT)) + if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots() & ITEM_SLOT_BELT)) return var/icon_file = 'icons/mob/clothing/belt.dmi' @@ -499,7 +499,7 @@ There are several things that need to be remembered: if(update_obscured) update_obscured_slots(worn_item.flags_inv) - if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_MASK)) + if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots() & ITEM_SLOT_MASK)) return var/icon_file = 'icons/mob/clothing/mask.dmi' diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index a1b2b842736..5cbd69c6a2a 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -1,12 +1,24 @@ -/mob/living/carbon/proc/check_obscured_slots(transparent_protection) - var/obscured = NONE +/// Returns a list of slots that are *visibly* covered by clothing and thus cannot be seen by others +/mob/living/carbon/proc/check_obscured_slots() var/hidden_slots = NONE for(var/obj/item/equipped_item in get_equipped_items()) hidden_slots |= equipped_item.flags_inv - if(transparent_protection) - hidden_slots |= equipped_item.transparent_protection + return hidden_slots_to_inventory_slots(hidden_slots) + +/// Returns a list of slots that are protected by other clothing, but could possibly be seen by others, via transparent visors and similar stuff +/mob/living/carbon/proc/check_covered_slots() + var/hidden_slots = NONE + + for(var/obj/item/equipped_item in get_equipped_items()) + hidden_slots |= equipped_item.flags_inv | equipped_item.transparent_protection + + return hidden_slots_to_inventory_slots(hidden_slots) + +/// Convers HIDEX to ITEM_SLOT_X, should be phased out in favor of using latter everywhere later +/proc/hidden_slots_to_inventory_slots(hidden_slots) + var/obscured = NONE if(hidden_slots & HIDENECK) obscured |= ITEM_SLOT_NECK if(hidden_slots & HIDEMASK) @@ -27,7 +39,6 @@ obscured |= ITEM_SLOT_SUITSTORE if(hidden_slots & HIDEHEADGEAR) obscured |= ITEM_SLOT_HEAD - return obscured /mob/living/carbon/get_item_by_slot(slot_id) diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm index 5ff3aa14a9b..ae551edbd2b 100644 --- a/code/modules/surgery/organs/internal/eyes/_eyes.dm +++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm @@ -257,7 +257,7 @@ var/mutable_appearance/eye_right = mutable_appearance('icons/mob/human/human_face.dmi', "[eye_icon_state]_r", -BODY_LAYER, parent) var/list/overlays = list(eye_left, eye_right) - var/obscured = parent.check_obscured_slots(TRUE) + var/obscured = parent.check_obscured_slots() if(overlay_ignore_lighting && !(obscured & ITEM_SLOT_EYES)) overlays += emissive_appearance(eye_left.icon, eye_left.icon_state, parent, -BODY_LAYER, alpha = eye_left.alpha) overlays += emissive_appearance(eye_right.icon, eye_right.icon_state, parent, -BODY_LAYER, alpha = eye_right.alpha) diff --git a/icons/ui/inventory/collar.png b/icons/ui/inventory/collar.png index 2e8c875851e..afee6e255b4 100644 Binary files a/icons/ui/inventory/collar.png and b/icons/ui/inventory/collar.png differ diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/MainPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/MainPage.tsx index 46dd281dca1..987bed8c9f6 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/MainPage.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/MainPage.tsx @@ -173,6 +173,10 @@ function ChoicedSelection(props: ChoicedSelectionProps) { image, 'centered-image', ])} + style={{ + transform: + 'translateX(-50%) translateY(-50%) scale(0.8)', + }} /> ); diff --git a/tgui/packages/tgui/interfaces/StripMenu.tsx b/tgui/packages/tgui/interfaces/StripMenu.tsx index 58b8cc30263..53a26e6958c 100644 --- a/tgui/packages/tgui/interfaces/StripMenu.tsx +++ b/tgui/packages/tgui/interfaces/StripMenu.tsx @@ -10,7 +10,7 @@ import { Window } from '../layouts'; const ROWS = 5; const COLUMNS = 6; -const BUTTON_DIMENSIONS = '50px'; +const BUTTON_DIMENSIONS = '64px'; type GridSpotKey = string; @@ -219,6 +219,7 @@ const SLOTS: Record< enum ObscuringLevel { Completely = 1, Hidden = 2, + Inaccessible = 3, } type Interactable = { @@ -243,6 +244,7 @@ type StripMenuItem = icon: string; name: string; alternate?: string[]; + obscured: ObscuringLevel; } | { obscured: ObscuringLevel; @@ -264,7 +266,9 @@ export const StripMenu = (props) => { } return ( - + // (64 + 6) * 6 + 6 = 426 + // (64 + 6) * 5 + 6 + 31 (from title) = + {range(0, ROWS).map((row) => ( @@ -299,8 +303,8 @@ export const StripMenu = (props) => { content = ( { background: 'rgba(0, 0, 0, 0.6)', position: 'absolute', overflow: 'hidden', - margin: '0px', - maxWidth: '22px', // yes I know its not 20 or 25; they look bad. 22px is perfect + margin: '0', + width: '20px', + height: '20px', zIndex: '2', left: `${idx === 0 ? '0' : undefined}`, right: `${idx === 1 ? '0' : undefined}`, bottom: '0', + padding: '0', + textAlign: 'center', }; return ( @@ -343,7 +358,11 @@ export const StripMenu = (props) => { }, ); } - } else if ('obscured' in item) { + } else if ( + 'obscured' in item && + (item.obscured === ObscuringLevel.Hidden || + item.obscured === ObscuringLevel.Completely) + ) { content = ( { } size={3} ml={0} - mt={1.3} + mt={2.5} style={{ textAlign: 'center', + verticalAlign: 'middle', height: '100%', width: '100%', }} @@ -398,11 +418,13 @@ export const StripMenu = (props) => { padding: '0', }} > - {slot.image && ( + {slot.image && !(item && 'name' in item) && ( )} diff --git a/tgui/packages/tgui/styles/atomic/centered-image.scss b/tgui/packages/tgui/styles/atomic/centered-image.scss index cce5bfdf2c1..335ace8d9c5 100644 --- a/tgui/packages/tgui/styles/atomic/centered-image.scss +++ b/tgui/packages/tgui/styles/atomic/centered-image.scss @@ -3,5 +3,5 @@ height: 100%; left: 50%; top: 50%; - transform: translateX(-50%) translateY(-50%) scale(0.8); + transform: translateX(-50%) translateY(-50%); }