diff --git a/code/__DEFINES/storage.dm b/code/__DEFINES/storage.dm index 01d77e0df2f2..ac23c09538e6 100644 --- a/code/__DEFINES/storage.dm +++ b/code/__DEFINES/storage.dm @@ -76,16 +76,16 @@ GLOBAL_LIST_INIT(default_weight_class_to_volume, list( // #define MAX_WEIGHT_CLASS_S_CONTAINER WEIGHT_CLASS_SMALL #define MAX_WEIGHT_CLASS_M_CONTAINER WEIGHT_CLASS_NORMAL -#define MAX_WEIGHT_CLASS_BACKPACK WEIGHT_CLASS_NORMAL +#define MAX_WEIGHT_CLASS_BACKPACK WEIGHT_CLASS_BULKY #define MAX_WEIGHT_CLASS_DUFFEL WEIGHT_CLASS_BULKY // max_volume for storages #define STORAGE_VOLUME_CONTAINER_S DEFAULT_VOLUME_NORMAL //4 small items #define STORAGE_VOLUME_CONTAINER_M (DEFAULT_VOLUME_NORMAL * 2) //8 small items #define STORAGE_VOLUME_SATCHEL (DEFAULT_VOLUME_NORMAL * 4) //4 normal items -#define STORAGE_VOLUME_BACKPACK (DEFAULT_VOLUME_NORMAL * 6) //1.5x satchel, 3 bulky items -#define STORAGE_VOLUME_DUFFLEBAG (DEFAULT_VOLUME_NORMAL * 8) // 2 huge items, or 4 bulky items -#define STORAGE_VOLUME_BAG_OF_HOLDING (DEFAULT_VOLUME_NORMAL * 9) //1.5X backpack +#define STORAGE_VOLUME_BACKPACK (DEFAULT_VOLUME_NORMAL * 6) //3 bulky items +#define STORAGE_VOLUME_DUFFLEBAG (DEFAULT_VOLUME_NORMAL * 10) //~1.4X backpack, 5 bulky items +#define STORAGE_VOLUME_BAG_OF_HOLDING (DEFAULT_VOLUME_NORMAL * 10) //Whitelist for the suit storage slot on medical suits #define MEDICAL_SUIT_ALLOWED_ITEMS list( \ diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index fab8ffdf3a2c..58002de8ce36 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -25,7 +25,12 @@ var/list/mob/is_using //lazy list of mobs looking at the contents of this storage. var/locked = FALSE //when locked nothing can see inside or use it. - var/locked_flavor = "locked" //prevents tochat messages related to locked from sending + var/locked_flavor = "seems to be locked!" //prevents tochat messages related to locked from sending + + /// If the storage object can be accessed while equipped to slot by mob(e.g. backpack in back slot) + var/worn_access = TRUE + /// If the storage object can be accessed while being held anywhere on a mob + var/carry_access = TRUE /// Storage flags, including what kinds of limiters we use for how many items we can hold var/storage_flags = STORAGE_FLAGS_LEGACY_DEFAULT @@ -110,6 +115,7 @@ RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, PROC_REF(preattack_intercept)) RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(attack_self)) RegisterSignal(parent, COMSIG_ITEM_PICKUP, PROC_REF(signal_on_pickup)) + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(signal_on_equip)) RegisterSignal(parent, COMSIG_MOVABLE_POST_THROW, PROC_REF(close_all)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) @@ -222,7 +228,7 @@ SIGNAL_HANDLER if(locked) - to_chat(M, "[parent] seems to be [locked_flavor]!") + to_chat(M, "[parent] [locked_flavor]") return FALSE if((M.get_active_held_item() == parent) && allow_quick_empty) INVOKE_ASYNC(src, PROC_REF(quick_empty), M) @@ -233,8 +239,10 @@ if(!isitem(O) || !click_gather || SEND_SIGNAL(O, COMSIG_CONTAINS_STORAGE)) return FALSE . = COMPONENT_NO_ATTACK + if(!access_check()) + return FALSE if(locked) - to_chat(M, "[parent] seems to be [locked_flavor]!") + to_chat(M, "[parent] [locked_flavor]") return FALSE var/obj/item/I = O if(collection_mode == COLLECT_ONE) @@ -309,6 +317,8 @@ var/atom/A = parent if(!M.canUseStorage() || !A.Adjacent(M) || M.incapacitated()) return + if(!access_check()) + return FALSE if(locked) to_chat(M, "[parent] seems to be [locked_flavor]!") return FALSE @@ -426,6 +436,8 @@ var/atom/A = parent var/atom/dump_destination = dest_object.get_dumping_location() if(M.CanReach(A) && dump_destination && M.CanReach(dump_destination)) + if(!access_check()) + return FALSE if(locked) to_chat(M, "[parent] seems to be [locked_flavor]!") return FALSE @@ -530,6 +542,8 @@ if(locked && !force) to_chat(M, "[parent] seems to be [locked_flavor]!") return FALSE + if(!access_check()) + return FALSE if(force || M.CanReach(parent, view_only = TRUE)) if(use_sound && !silent) playsound(A, use_sound, 50, TRUE, -5) @@ -548,7 +562,7 @@ //This proc return 1 if the item can be picked up and 0 if it can't. //Set the stop_messages to stop it from printing messages -/datum/component/storage/proc/can_be_inserted(obj/item/I, stop_messages = FALSE, mob/M) +/datum/component/storage/proc/can_be_inserted(obj/item/I, stop_messages = FALSE, mob/M, bypass_access = FALSE) if(!istype(I) || (I.item_flags & ABSTRACT)) return FALSE //Not an item if(I == parent) @@ -557,6 +571,9 @@ var/atom/host = parent if(real_location == I.loc) return FALSE //Means the item is already in the storage item + if(!bypass_access)//For stuff like setting up outfits, setting up roundstart backpacks, etc. + if(!access_check()) + return FALSE if(locked) if(M && !stop_messages) host.add_fingerprint(M) @@ -660,17 +677,17 @@ var/obj/O = parent O.update_appearance() -/datum/component/storage/proc/signal_insertion_attempt(datum/source, obj/item/I, mob/M, silent = FALSE, force = FALSE) +/datum/component/storage/proc/signal_insertion_attempt(datum/source, obj/item/I, mob/M, silent = FALSE, force = FALSE, bypass_access = FALSE) SIGNAL_HANDLER - if((!force && !can_be_inserted(I, TRUE, M)) || (I == parent)) + if((!force && !can_be_inserted(I, TRUE, M, bypass_access)) || (I == parent)) return FALSE return handle_item_insertion(I, silent, M) -/datum/component/storage/proc/signal_can_insert(datum/source, obj/item/I, mob/M, silent = FALSE) +/datum/component/storage/proc/signal_can_insert(datum/source, obj/item/I, mob/M, silent = FALSE, bypass_access = FALSE) SIGNAL_HANDLER - return can_be_inserted(I, silent, M) + return can_be_inserted(I, silent, M, bypass_access) /datum/component/storage/proc/show_to_ghost(datum/source, mob/dead/observer/M) SIGNAL_HANDLER @@ -755,6 +772,8 @@ if(A.loc == user) . = COMPONENT_NO_ATTACK_HAND + if(!access_check()) + return FALSE if(locked) to_chat(user, "[parent] seems to be [locked_flavor]!") else @@ -769,6 +788,12 @@ for(var/mob/M in can_see_contents() - user) close(M) +/datum/component/storage/proc/signal_on_equip(datum/source, mob/user) + SIGNAL_HANDLER + + if(!worn_access) + close(user) + /datum/component/storage/proc/signal_take_obj(datum/source, atom/movable/AM, new_loc, force = FALSE) SIGNAL_HANDLER @@ -794,6 +819,8 @@ /datum/component/storage/proc/on_alt_click_async(datum/source, mob/user) if(!isliving(user) || !user.CanReach(parent) || user.incapacitated()) return + if(!access_check()) + return FALSE if(locked) to_chat(user, "[parent] seems to be [locked_flavor]!") return @@ -833,3 +860,28 @@ //Gets our max volume /datum/component/storage/proc/get_max_volume() return max_volume || AUTO_SCALE_STORAGE_VOLUME(max_w_class, max_combined_w_class) + +//checks for mob-related storage access conditions +/datum/component/storage/proc/access_check(message = TRUE) + var/atom/ourparent = parent + var/datum/component/storage/otherstorage + + //if we are inside another storage object, let's move up and check access there instead + if(istype(ourparent.loc, /obj/item/storage)) + ourparent = ourparent.loc + //get our parent's storage component so we can check their access vars + otherstorage = ourparent.GetComponent(/datum/component/storage) + + if(ismob(ourparent.loc)) + var/mob/holder = ourparent.loc + + if(otherstorage? !otherstorage.carry_access : !carry_access) + if(message) + to_chat(holder, span_warning( "[ourparent] is too cumbersome to open inhand, you're going to have to set it down!")) + return FALSE + + if((otherstorage? !otherstorage.worn_access : !worn_access) && !holder.held_items.Find(ourparent)) + if(message) + to_chat(holder, span_warning( "Your arms aren't long enough to reach [ourparent] while it's on your back!")) + return FALSE + return TRUE diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 58cbaabc5e86..4bbd88745752 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -413,6 +413,14 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb if(anchored) return + //check if the item is inside another item's storage + if(istype(loc, /obj/item/storage)) + //if so, can we actually access it? + var/datum/component/storage/ourstorage = loc.GetComponent(/datum/component/storage) + if(!ourstorage.access_check()) + SEND_SIGNAL(loc, COMSIG_TRY_STORAGE_HIDE_FROM, user)//you're not supposed to be in here right now, punk! + return + if(resistance_flags & ON_FIRE) var/mob/living/carbon/C = user var/can_handle_hot = FALSE diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index 34eba9a25191..dc3fa7e790f3 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -39,6 +39,15 @@ STR.max_volume = STORAGE_VOLUME_BACKPACK STR.max_w_class = MAX_WEIGHT_CLASS_BACKPACK STR.use_sound = 'sound/items/storage/unzip.ogg' + STR.worn_access = FALSE + +/obj/machinery/examine(mob/user) + . = ..() + var/datum/component/storage/bpack = GetComponent(/datum/component/storage) + if(bpack.worn_access == FALSE) + . += span_notice("You won't be able to open this once it's on your back.") + if(bpack.carry_access == FALSE) + . += span_notice("You'll have to set this down on the floor if you want to open it.") /* * Backpack Types @@ -184,8 +193,9 @@ /obj/item/storage/backpack/satchel/ComponentInitialize() . = ..() var/datum/component/storage/STR = GetComponent(/datum/component/storage) - STR.max_volume = STORAGE_VOLUME_BACKPACK + STR.max_volume = STORAGE_VOLUME_SATCHEL STR.max_w_class = MAX_WEIGHT_CLASS_M_CONTAINER + STR.worn_access = TRUE /obj/item/storage/backpack/satchel/leather name = "leather satchel" @@ -316,6 +326,13 @@ greyscale_icon_state = "satchel" greyscale_colors = list(list(15, 16), list(19, 13), list(13, 18)) +/obj/item/storage/backpack/messenger/ComponentInitialize() + . = ..() + var/datum/component/storage/STR = GetComponent(/datum/component/storage) + STR.max_volume = STORAGE_VOLUME_SATCHEL + STR.max_w_class = MAX_WEIGHT_CLASS_M_CONTAINER + STR.worn_access = TRUE + /obj/item/storage/backpack/messenger/chem name = "chemistry messenger bag" desc = "A sterile backpack worn over one shoulder. This one is in Chemistry colors." @@ -396,6 +413,7 @@ STR.max_w_class = MAX_WEIGHT_CLASS_DUFFEL LAZYINITLIST(STR.exception_hold) // This code allows you to fit one mob holder into a duffel bag STR.exception_hold += typecacheof(/obj/item/clothing/head/mob_holder) + STR.carry_access = FALSE /obj/item/storage/backpack/duffelbag/captain name = "captain's duffel bag" diff --git a/code/game/objects/items/storage/ration.dm b/code/game/objects/items/storage/ration.dm index 9a9e4a5a2617..9254e3014f7b 100644 --- a/code/game/objects/items/storage/ration.dm +++ b/code/game/objects/items/storage/ration.dm @@ -32,7 +32,7 @@ /obj/item/reagent_containers/food, /obj/item/ration_heater)) STR.locked = TRUE - STR.locked_flavor = "sealed closed" + STR.locked_flavor = "seems to be sealed closed!" /obj/item/storage/ration/proc/open_ration(mob/user) to_chat(user, "You tear open \the [src].") diff --git a/code/modules/clothing/outfits/ert/roumain_ert.dm b/code/modules/clothing/outfits/ert/roumain_ert.dm index efe7828173be..74802bdbba0b 100644 --- a/code/modules/clothing/outfits/ert/roumain_ert.dm +++ b/code/modules/clothing/outfits/ert/roumain_ert.dm @@ -32,7 +32,7 @@ l_pocket = /obj/item/ammo_box/a44roum_speedloader - backpack_contents = list(/obj/item/ammo_box/magazine/c45_firestorm_mag/pan = 3, /obj/item/ammo_box/a44roum_speedloader = 2, /obj/item/storage/box/ammo/a44roum) + backpack_contents = list(/obj/item/ammo_box/magazine/c45_firestorm_mag/pan = 2, /obj/item/ammo_box/a44roum_speedloader = 2, /obj/item/storage/box/ammo/a44roum) /datum/outfit/job/roumain/ert/vickland name = "ERT - Saint-Roumain Hunter (Vickland)" // vickland and candor diff --git a/code/modules/clothing/outfits/factions/minutemen.dm b/code/modules/clothing/outfits/factions/minutemen.dm index 3f99cc85087f..040acb06d7c4 100644 --- a/code/modules/clothing/outfits/factions/minutemen.dm +++ b/code/modules/clothing/outfits/factions/minutemen.dm @@ -224,8 +224,7 @@ l_hand = /obj/item/storage/briefcase - backpack = /obj/item/storage/backpack/satchel/leather - satchel = /obj/item/storage/backpack/satchel/leather + backpack = /obj/item/storage/backpack/industrial l_pocket = /obj/item/toy/crayon/white r_pocket = /obj/item/radio diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index cbacb2099a0d..5067b4b5bf38 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1273,7 +1273,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) return TRUE if(ITEM_SLOT_BACKPACK) if(H.back) - if(SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_CAN_INSERT, I, H, TRUE)) + if(SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_CAN_INSERT, I, H, TRUE, TRUE)) return TRUE return FALSE return FALSE //Unsupported slot diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index 9525ebd6ec9b..eddb352a47ee 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -106,7 +106,7 @@ put_in_hands(I) update_inv_hands() if(ITEM_SLOT_BACKPACK) - if(!back || !SEND_SIGNAL(back, COMSIG_TRY_STORAGE_INSERT, I, src, TRUE)) + if(!back || !SEND_SIGNAL(back, COMSIG_TRY_STORAGE_INSERT, I, src, TRUE, FALSE, TRUE)) not_handled = TRUE if(ITEM_SLOT_ID) if(!wear_id || !SEND_SIGNAL(wear_id, COMSIG_TRY_STORAGE_INSERT, I, src, TRUE))