diff --git a/code/datums/components/storage/concrete/pockets.dm b/code/datums/components/storage/concrete/pockets.dm
index e00c40e116f8..065a398c3230 100644
--- a/code/datums/components/storage/concrete/pockets.dm
+++ b/code/datums/components/storage/concrete/pockets.dm
@@ -108,6 +108,9 @@
/obj/item/gun/ballistic/automatic/pistol,
/obj/item/gun/ballistic/revolver,
/obj/item/ammo_box))
+ can_hold_max_of_items = typecacheof(list(
+ /obj/item/gun/ballistic = 1
+ ))
/datum/component/storage/concrete/pockets/holster/real_location()
// if the component is reparented to a jumpsuit, the items still go in the protector
@@ -136,17 +139,3 @@
/obj/item/gun/energy/dueling,
/obj/item/gun/ballistic/shotgun,
/obj/item/gun/ballistic/rocketlauncher))
-
-/datum/component/storage/concrete/pockets/holster/chameleon
- max_items = 1
-
-/datum/component/storage/concrete/pockets/holster/chameleon/Initialize()
- original_parent = parent
- . = ..()
- can_hold = typecacheof(list(
- /obj/item/gun/ballistic/automatic/pistol/ringneck,
- /obj/item/gun/ballistic/revolver,
- /obj/item/gun/energy/e_gun/mini,
- /obj/item/gun/energy/disabler,
- /obj/item/gun/energy/pulse/carbine,
- /obj/item/gun/energy/dueling))
diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm
index 765e14e5db64..fab8ffdf3a2c 100644
--- a/code/datums/components/storage/storage.dm
+++ b/code/datums/components/storage/storage.dm
@@ -18,6 +18,7 @@
var/list/cant_hold //if this is set, items, and their children, won't fit
var/list/exception_hold //if set, these items will be the exception to the max size of object that can fit.
var/list/can_hold_trait /// If set can only contain stuff with this single trait present.
+ var/list/can_hold_max_of_items // if set, storage can only hold up to the set amount of said item.
var/can_hold_description
@@ -566,6 +567,16 @@
if(!stop_messages)
to_chat(M, "[host] cannot hold [I]!")
return FALSE
+ if(length(can_hold_max_of_items))
+ if(is_type_in_typecache(I,can_hold_max_of_items))
+ var/amount = 0
+ for(var/_item in contents())
+ if(is_type_in_typecache(_item,can_hold_max_of_items))
+ amount++
+ if(amount >= can_hold_max_of_items[I.type])
+ if(!stop_messages)
+ to_chat(M, "[host] cannot hold another [I]!")
+ return FALSE
if(is_type_in_typecache(I, cant_hold) || HAS_TRAIT(I, TRAIT_NO_STORAGE_INSERT) || (can_hold_trait && !HAS_TRAIT(I, can_hold_trait))) //Items which this container can't hold.
if(!stop_messages)
to_chat(M, "[host] cannot hold [I]!")
diff --git a/code/modules/cargo/blackmarket/blackmarket_items/misc.dm b/code/modules/cargo/blackmarket/blackmarket_items/misc.dm
index 8f51514de804..a9221fb95ecb 100644
--- a/code/modules/cargo/blackmarket/blackmarket_items/misc.dm
+++ b/code/modules/cargo/blackmarket/blackmarket_items/misc.dm
@@ -11,15 +11,15 @@
stock_max = 6
availability_prob = 80
-/datum/blackmarket_item/misc/shoulder_holster
- name = "Shoulder holster"
- desc = "Yeehaw, hardboiled friends! This holster is the first step in your dream of becoming a detective and being allowed to shoot real guns!"
+/datum/blackmarket_item/misc/cham_holster
+ name = "Chameleon Shoulder holster"
+ desc = "Looking to pack some heat without attracting attention? This adapative chameleon shoulder holster can disguise itself and your piece!"
item = /obj/item/clothing/accessory/holster
price_min = 200
price_max = 800
- stock_max = 8
- availability_prob = 60
+ stock_max = 4
+ availability_prob = 40
/datum/blackmarket_item/misc/strange_seed
name = "Strange Seeds"
diff --git a/code/modules/cargo/packs/sec_supply.dm b/code/modules/cargo/packs/sec_supply.dm
index 601d387cb222..86d631024705 100644
--- a/code/modules/cargo/packs/sec_supply.dm
+++ b/code/modules/cargo/packs/sec_supply.dm
@@ -5,6 +5,12 @@
/*
Standard supplies
*/
+/datum/supply_pack/sec_supply/holster
+ name = "Shoulder Holster Crate"
+ desc = "Contains a shoulder holster, capable of holding a single pistol or revolver and your ammo."
+ cost = 600
+ contains = list(/obj/item/clothing/accessory/holster)
+ crate_name = "holster crate"
/datum/supply_pack/sec_supply/chemimp
name = "Chemical Implants Crate"
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 8313beaa408c..c07c52a57e84 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -416,11 +416,19 @@
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
else
- if(attached_accessory)
- remove_accessory(user)
+ if(attached_accessory && ispath(attached_accessory.pocket_storage_component_path) && loc == user)
+ attached_accessory.attack_hand(user)
+ return
else
rolldown()
+/obj/item/clothing/under/CtrlClick(mob/user)
+ if(..())
+ return 1
+ if(attached_accessory)
+ remove_accessory(user)
+
+
/obj/item/clothing/under/verb/jumpsuit_adjust()
set name = "Adjust Jumpsuit Style"
set category = null
diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm
index 8843009813f3..7445eb2ad55a 100644
--- a/code/modules/clothing/under/_under.dm
+++ b/code/modules/clothing/under/_under.dm
@@ -39,6 +39,11 @@
if(accessory_overlay)
. += accessory_overlay
+/obj/item/clothing/under/Destroy()
+ . = ..()
+ if(attached_accessory)
+ attached_accessory.detach(src)
+
/obj/item/clothing/under/attackby(obj/item/I, mob/user, params)
if((has_sensor == BROKEN_SENSORS) && istype(I, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = I
@@ -46,6 +51,9 @@
has_sensor = HAS_SENSORS
to_chat(user,"You repair the suit sensors on [src] with [C].")
return 1
+ if(attached_accessory && ispath(attached_accessory.pocket_storage_component_path) && loc == user)
+ attached_accessory.attackby(I,user)
+ return
if(!attach_accessory(I, user))
return ..()
@@ -180,7 +188,9 @@
if(SENSOR_COORDS)
. += "Its vital tracker and tracking beacon appear to be enabled."
if(attached_accessory)
- . += "\A [attached_accessory] is attached to it."
+ . += "\A [attached_accessory] is attached to it. You could Ctrl-click on it to remove it."
+ if(attached_accessory.pocket_storage_component_path)
+ . += "You could open the storage of \the [attached_accessory] with Alt-click."
/obj/item/clothing/under/rank
dying_key = DYE_REGISTRY_UNDER
diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm
index 81e5da317553..9e66e9572c59 100644
--- a/code/modules/clothing/under/accessories.dm
+++ b/code/modules/clothing/under/accessories.dm
@@ -92,10 +92,11 @@
if(initial(above_suit))
above_suit = !above_suit
to_chat(user, "[src] will be worn [above_suit ? "above" : "below"] your suit.")
+ return ..()
/obj/item/clothing/accessory/examine(mob/user)
. = ..()
- . += "\The [src] can be attached to a uniform. Alt-click to remove it once attached."
+ . += "\The [src] can be attached to a uniform. Ctrl-click to remove it once attached."
if(initial(above_suit))
. += "\The [src] can be worn above or below your suit. Alt-click to toggle."
@@ -431,7 +432,6 @@
name = "syndicate holster"
desc = "A two pouched hip holster that uses chameleon technology to disguise itself and any guns in it."
var/datum/action/item_action/chameleon/change/chameleon_action
- pocket_storage_component_path = /datum/component/storage/concrete/pockets/holster/chameleon
/obj/item/clothing/accessory/holster/chameleon/Initialize()
. = ..()