Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Soulifies Backpacks & Duffels #3865

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
8 changes: 4 additions & 4 deletions code/__DEFINES/storage.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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( \
Expand Down
68 changes: 60 additions & 8 deletions code/datums/components/storage/storage.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -222,7 +228,7 @@
SIGNAL_HANDLER

if(locked)
to_chat(M, "<span class='warning'>[parent] seems to be [locked_flavor]!</span>")
to_chat(M, "<span class='warning'>[parent] [locked_flavor]</span>")
return FALSE
if((M.get_active_held_item() == parent) && allow_quick_empty)
INVOKE_ASYNC(src, PROC_REF(quick_empty), M)
Expand All @@ -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, "<span class='warning'>[parent] seems to be [locked_flavor]!</span>")
to_chat(M, "<span class='warning'>[parent] [locked_flavor]</span>")
return FALSE
var/obj/item/I = O
if(collection_mode == COLLECT_ONE)
Expand Down Expand Up @@ -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, "<span class='warning'>[parent] seems to be [locked_flavor]!</span>")
return FALSE
Expand Down Expand Up @@ -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, "<span class='warning'>[parent] seems to be [locked_flavor]!</span>")
return FALSE
Expand Down Expand Up @@ -530,6 +542,8 @@
if(locked && !force)
to_chat(M, "<span class='warning'>[parent] seems to be [locked_flavor]!</span>")
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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -755,6 +772,8 @@

if(A.loc == user)
. = COMPONENT_NO_ATTACK_HAND
if(!access_check())
return FALSE
if(locked)
to_chat(user, "<span class='warning'>[parent] seems to be [locked_flavor]!</span>")
else
Expand All @@ -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

Expand All @@ -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, "<span class='warning'>[parent] seems to be [locked_flavor]!</span>")
return
Expand Down Expand Up @@ -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
8 changes: 8 additions & 0 deletions code/game/objects/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 19 additions & 1 deletion code/game/objects/items/storage/backpack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Sun-Soaked marked this conversation as resolved.
Show resolved Hide resolved

/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
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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."
Expand Down Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion code/game/objects/items/storage/ration.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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, "<span class='notice'>You tear open \the [src].</span>")
Expand Down
2 changes: 1 addition & 1 deletion code/modules/clothing/outfits/ert/roumain_ert.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions code/modules/clothing/outfits/factions/minutemen.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/carbon/human/species.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/carbon/inventory.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Loading