From 12afcb911ef04ff0f5d615361b1d1b78b63c2dda Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Mon, 5 Feb 2024 13:42:03 -0600 Subject: [PATCH] Comprehensive cleanup of storage datum, replaces the weakrefs with just refs (because they were managed already) (#81120) ## About The Pull Request - Large amount of storage datum cleanup. - Documentation. - Maybe more consistent use of parent vs real_location. - Removes the weakrefs, replaces it with just references. - These were already managed references anyways so why bother? - Removes a bunch of arguments no one used and would ever used so only the most useful args are left. - Some bugfixes. ## Why It's Good For The Game Aiming to make storage easier to work with. The whole intent of this was to bugfix the whole "weight class" thing that keeps popping up but I had to do this first. ## Changelog :cl: Melbert fix: When placing an item into storage (such as backpacks), all nearby mobs now get a message, rather than just the first mob. fix: TGC decks of cards should act a bit less odd when looking inside. refactor: Refactored a bit of storage, cleaned up a fair bit of its code. Let me know if you notice anything funky about storage (like backpacks). /:cl: --- code/__DEFINES/dcs/signals/signals_object.dm | 4 +- code/__HELPERS/atoms.dm | 10 - code/datums/storage/storage.dm | 803 ++++++++---------- .../datums/storage/subtypes/bag_of_holding.dm | 43 +- code/datums/storage/subtypes/cards.dm | 93 +- code/datums/storage/subtypes/duffel_bag.dm | 7 +- .../storage/subtypes/extract_inventory.dm | 27 +- code/datums/storage/subtypes/fish_case.dm | 57 +- code/datums/storage/subtypes/implant.dm | 9 +- code/datums/storage/subtypes/pockets.dm | 129 ++- code/datums/storage/subtypes/rped.dm | 44 +- code/datums/storage/subtypes/surgery_tray.dm | 7 +- code/datums/storage/subtypes/trash.dm | 17 +- code/game/atom/atom_storage.dm | 18 +- code/game/objects/items.dm | 3 +- code/game/objects/items/crayons.dm | 8 +- code/game/objects/items/dice.dm | 2 +- .../objects/items/implants/implant_storage.dm | 2 +- code/game/objects/items/melee/misc.dm | 8 +- code/game/objects/items/storage/backpack.dm | 2 +- code/game/objects/items/storage/bags.dm | 33 +- code/game/objects/items/storage/belt.dm | 18 +- .../objects/items/storage/boxes/food_boxes.dm | 6 +- .../items/storage/boxes/medical_boxes.dm | 2 +- .../items/storage/boxes/science_boxes.dm | 4 +- .../items/storage/boxes/service_boxes.dm | 4 +- code/game/objects/items/storage/fancy.dm | 16 +- code/game/objects/items/storage/garment.dm | 4 +- code/game/objects/items/storage/lockbox.dm | 2 +- code/game/objects/items/storage/medkit.dm | 20 +- code/game/objects/items/storage/sixpack.dm | 4 +- code/game/objects/items/storage/storage.dm | 12 +- code/game/objects/items/surgery_tray.dm | 25 - code/game/objects/items/tcg/tcg.dm | 2 +- code/game/objects/structures/secure_safe.dm | 2 +- code/game/objects/structures/toiletbong.dm | 6 +- code/modules/clothing/outfits/vv_outfit.dm | 3 +- .../under/accessories/_accessories.dm | 7 +- code/modules/explorer_drone/exodrone.dm | 5 +- code/modules/fishing/fishing_equipment.dm | 4 +- .../food_and_drinks/machinery/coffeemaker.dm | 2 +- .../food_and_drinks/machinery/griddle.dm | 10 +- code/modules/mining/lavaland/tendril_loot.dm | 2 - code/modules/mob/inventory.dm | 4 +- .../mob/living/carbon/human/inventory.dm | 5 +- code/modules/mob/living/living.dm | 15 +- code/modules/mod/modules/modules_general.dm | 5 +- code/modules/photography/photos/album.dm | 11 +- .../guns/ballistic/bows/bow_quivers.dm | 4 +- .../projectiles/guns/energy/dueling.dm | 2 +- code/modules/recycling/disposal/bin.dm | 12 +- 51 files changed, 715 insertions(+), 829 deletions(-) diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index d65cb835116..442309289f0 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -138,8 +138,10 @@ #define COMSIG_ITEM_PICKUP "item_pickup" ///from base of obj/item/on_outfit_equip(): (mob/equipper, visuals_only, slot) #define COMSIG_ITEM_EQUIPPED_AS_OUTFIT "item_equip_as_outfit" -///from base of datum/storage/attempt_insert(): () +///from base of datum/storage/handle_enter(): (datum/storage/storage) #define COMSIG_ITEM_STORED "item_stored" +///from base of datum/storage/handle_exit(): (datum/storage/storage) +#define COMSIG_ITEM_UNSTORED "item_unstored" ///from base of obj/item/apply_fantasy_bonuses(): (bonus) #define COMSIG_ITEM_APPLY_FANTASY_BONUSES "item_apply_fantasy_bonuses" diff --git a/code/__HELPERS/atoms.dm b/code/__HELPERS/atoms.dm index 9845593c084..406ea75143c 100644 --- a/code/__HELPERS/atoms.dm +++ b/code/__HELPERS/atoms.dm @@ -314,16 +314,6 @@ rough example of the "cone" made by the 3 dirs checked /proc/pass(...) return -///Returns a list of the parents of all storage components that contain the target item -/proc/get_storage_locs(obj/item/target) - . = list() - if(!istype(target) || !(target.item_flags & IN_STORAGE)) - return - var/datum/storage/storage_datum = target.loc.atom_storage - if(!storage_datum) - return - . += storage_datum.real_location?.resolve() - /// Returns an x and y value require to reverse the transformations made to center an oversized icon /atom/proc/get_oversized_icon_offsets() if (pixel_x == 0 && pixel_y == 0) diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index acfa2e40f18..915bdea22d4 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -5,142 +5,134 @@ * If you're looking to create custom storage type behaviors, check ../subtypes */ /datum/storage - /// the actual item we're attached to - var/datum/weakref/parent - /// the actual item we're storing in - var/datum/weakref/real_location + /** + * A reference to the atom linked to this storage object + * If the parent goes, we go. Will never be null. + */ + VAR_FINAL/atom/parent + /** + * A reference to the atom where the items are actually stored. + * By default this is parent. Should generally never be null. + * Sometimes it's not the parent, that's what is called "dissassociated storage". + * + * Do NOT set this directly, use set_real_location. + */ + VAR_FINAL/atom/real_location - /// if this is set, only items, and their children, will fit - var/list/can_hold - /// if this is set, items, and their children, won't fit - var/list/cant_hold - /// if set, these items will be the exception to the max size of object that can fit. - var/list/exception_hold - /// if exception_hold is set, how many exception items can we hold at any one time? - var/exception_max = INFINITE - /// if set can only contain stuff with this single trait present. - var/list/can_hold_trait + /// List of all the mobs currently viewing the contents of this storage. + VAR_PRIVATE/list/mob/is_using = list() - /// whether or not we should have those cute little animations + /// The storage display screen object. + VAR_PRIVATE/atom/movable/screen/storage/boxes + /// The 'close button' screen object. + VAR_PRIVATE/atom/movable/screen/close/closer + + /// Typecache of items that can be inserted into this storage. + /// By default, all item types can be inserted (assuming other conditions are met). + /// Do not set directly, use set_holdable + VAR_FINAL/list/obj/item/can_hold + /// Typecache of items that cannot be inserted into this storage. + /// By default, no item types are barred from insertion. + /// Do not set directly, use set_holdable + VAR_FINAL/list/obj/item/cant_hold + /// Typecache of items that can always be inserted into this storage, regardless of size. + VAR_FINAL/list/obj/item/exception_hold + /// For use with an exception typecache: + /// The maximum amount of items of the exception type that can be inserted into this storage. + var/exception_max = INFINITY + + /// Determines whether we play a rustle animation when inserting/removing items. var/animated = TRUE + /// Determines whether we play a rustle sound when inserting/removing items. + var/rustle_sound = TRUE + /// The maximum amount of items that can be inserted into this storage. var/max_slots = 7 - /// max weight class for a single item being inserted + /// The largest weight class that can be inserted into this storage, inclusive. var/max_specific_storage = WEIGHT_CLASS_NORMAL - /// max combined weight classes the storage can hold - var/max_total_storage = 14 - - /// list of all the mobs currently viewing the contents - var/list/is_using = list() + /// Determines the maximum amount of weight that can be inserted into this storage. + /// Weight is calculated by the sum of all of our content's weight classes. + var/max_total_storage = WEIGHT_CLASS_SMALL * 7 + /// Whether the storage is currently locked (inaccessible). See [code/__DEFINES/storage.dm] var/locked = STORAGE_NOT_LOCKED - /// whether or not we should open when clicked + + /// Whether we open when attack_handed (clicked on with an empty hand). var/attack_hand_interact = TRUE - /// whether or not we allow storage objects of the same size inside + + /// Whether we allow storage objects of the same size inside. var/allow_big_nesting = FALSE - /// should we be allowed to pickup an object by clicking it + /// If TRUE, we can click on items with the storage object to pick them up and insert them. var/allow_quick_gather = FALSE - /// show we allow emptying all contents by using the storage object in hand + /// The mode for collection when allow_quick_gather is enabled. See [code/__DEFINES/storage.dm] + var/collection_mode = COLLECT_EVERYTHING + + /// If TRUE, we can use-in-hand the storage object to dump all of its contents. var/allow_quick_empty = FALSE - /// the mode for collection when allow_quick_gather is enabled - var/collection_mode = COLLECT_ONE + /// If we support smartly removing/inserting things from ourselves var/supports_smart_equip = TRUE - /// shows what we can hold in examine text + /// An additional description shown on double-examine. + /// Is autogenerated to the can_hold list if not set. var/can_hold_description - /// contents shouldn't be emped - var/emp_shielded - - /// you put things *in* a bag, but *on* a plate + /// The preposition used when inserting items into this storage. + /// IE: You put things *in* a bag, but *on* a plate. var/insert_preposition = "in" - /// don't show any chat messages regarding inserting items + /// If TRUE, chat messages for inserting/removing items will not be shown. var/silent = FALSE - /// same as above but only for the user, useful to cut on chat spam without removing feedback for other players + /// Same as above but only for the user. + /// Useful to cut on chat spam without removing feedback for other players. var/silent_for_user = FALSE - /// play a rustling sound when interacting with the bag - var/rustle_sound = TRUE - /// alt click takes an item out instead of opening up storage + /// if TRUE, alt-click takes an item out instantly rather than opening up storage. var/quickdraw = FALSE - /// instead of displaying multiple items of the same type, display them as numbered contents + /// Instead of displaying multiple items of the same type, display them as numbered contents. var/numerical_stacking = FALSE - /// storage display object - var/atom/movable/screen/storage/boxes - /// close button object - var/atom/movable/screen/close/closer - - /// maximum amount of columns a storage object can have + /// Maximum amount of columns a storage object can have var/screen_max_columns = 7 + /// Maximum amount of rows a storage object can have var/screen_max_rows = INFINITY - /// pixel location of the boxes and close button + /// X-pixel location of the boxes and close button var/screen_pixel_x = 16 + /// Y-pixel location of the boxes and close button var/screen_pixel_y = 16 - /// where storage starts being rendered, screen_loc wise + /// Where storage starts being rendered, x-screen_loc wise var/screen_start_x = 4 + /// Where storage starts being rendered, y-screen_loc wise var/screen_start_y = 2 - var/datum/weakref/modeswitch_action_ref + /// Ref to the item action that toggles collectmode. + VAR_PRIVATE/datum/action/item_action/storage_gather_mode/modeswitch_action - /// If true shows the contents of the storage in open_storage + /// If TRUE, shows the contents of the storage in open_storage var/display_contents = TRUE -/datum/storage/New(atom/parent, max_slots, max_specific_storage, max_total_storage, numerical_stacking, allow_quick_gather, allow_quick_empty, collection_mode, attack_hand_interact) +/datum/storage/New( + atom/parent, + max_slots = src.max_slots, + max_specific_storage = src.max_specific_storage, + max_total_storage = src.max_total_storage, +) + if(!istype(parent)) + stack_trace("Storage datum ([type]) created without a [isnull(parent) ? "null parent" : "invalid parent ([parent.type])"]!") + qdel(src) + return + boxes = new(null, null, src) closer = new(null, null, src) - src.parent = WEAKREF(parent) - src.real_location = src.parent - src.max_slots = max_slots || src.max_slots - src.max_specific_storage = max_specific_storage || src.max_specific_storage - src.max_total_storage = max_total_storage || src.max_total_storage - src.numerical_stacking = numerical_stacking || src.numerical_stacking - src.allow_quick_gather = allow_quick_gather || src.allow_quick_gather - src.allow_quick_empty = allow_quick_empty || src.allow_quick_empty - src.collection_mode = collection_mode || src.collection_mode - src.attack_hand_interact = attack_hand_interact || src.attack_hand_interact + set_parent(parent) + set_real_location(parent) - var/atom/resolve_parent = src.parent?.resolve() - var/atom/resolve_location = src.real_location?.resolve() - - if(!resolve_parent) - stack_trace("storage could not resolve parent weakref") - qdel(src) - return - - if(!resolve_location) - stack_trace("storage could not resolve location weakref") - qdel(src) - return - - RegisterSignals(resolve_parent, list(COMSIG_ATOM_ATTACK_PAW, COMSIG_ATOM_ATTACK_HAND), PROC_REF(on_attack)) - RegisterSignal(resolve_parent, COMSIG_MOUSEDROP_ONTO, PROC_REF(on_mousedrop_onto)) - RegisterSignal(resolve_parent, COMSIG_MOUSEDROPPED_ONTO, PROC_REF(on_mousedropped_onto)) - - RegisterSignal(resolve_parent, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp_act)) - RegisterSignal(resolve_parent, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) - RegisterSignal(resolve_parent, COMSIG_ITEM_PRE_ATTACK, PROC_REF(on_preattack)) - RegisterSignal(resolve_parent, COMSIG_OBJ_DECONSTRUCT, PROC_REF(on_deconstruct)) - - RegisterSignal(resolve_parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(mass_empty)) - - RegisterSignals(resolve_parent, list(COMSIG_CLICK_ALT, COMSIG_ATOM_ATTACK_GHOST, COMSIG_ATOM_ATTACK_HAND_SECONDARY), PROC_REF(open_storage_on_signal)) - RegisterSignal(resolve_parent, COMSIG_ATOM_ATTACKBY_SECONDARY, PROC_REF(open_storage_attackby_secondary)) - - RegisterSignal(resolve_location, COMSIG_ATOM_ENTERED, PROC_REF(handle_enter)) - RegisterSignal(resolve_location, COMSIG_ATOM_EXITED, PROC_REF(handle_exit)) - RegisterSignal(resolve_parent, COMSIG_MOVABLE_MOVED, PROC_REF(close_distance)) - RegisterSignal(resolve_parent, COMSIG_ITEM_EQUIPPED, PROC_REF(update_actions)) - - RegisterSignal(resolve_parent, COMSIG_TOPIC, PROC_REF(topic_handle)) - - RegisterSignal(resolve_parent, COMSIG_ATOM_EXAMINE, PROC_REF(handle_examination)) - RegisterSignal(resolve_parent, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(handle_extra_examination)) + src.max_slots = max_slots + src.max_specific_storage = max_specific_storage + src.max_total_storage = max_total_storage orient_to_hud() @@ -173,15 +165,11 @@ if(!istype(arrived)) return - var/atom/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - - resolve_parent.update_appearance(UPDATE_ICON_STATE) - arrived.item_flags |= IN_STORAGE refresh_views() arrived.on_enter_storage(src) + SEND_SIGNAL(arrived, COMSIG_ITEM_STORED, src) + parent.update_appearance() /// Automatically ran on all object removals: flag marking and view refreshing. /datum/storage/proc/handle_exit(datum/source, obj/item/gone) @@ -190,67 +178,97 @@ if(!istype(gone)) return - var/atom/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - - resolve_parent.update_appearance(UPDATE_ICON_STATE) - gone.item_flags &= ~IN_STORAGE remove_and_refresh(gone) gone.on_exit_storage(src) + SEND_SIGNAL(gone, COMSIG_ITEM_UNSTORED, src) + parent.update_appearance() + +/// Set the passed atom as the parent +/datum/storage/proc/set_parent(atom/new_parent) + PRIVATE_PROC(TRUE) + + ASSERT(isnull(parent)) + + parent = new_parent + // a few of theses should probably be on the real_location rather than the parent + RegisterSignals(parent, list(COMSIG_ATOM_ATTACK_PAW, COMSIG_ATOM_ATTACK_HAND), PROC_REF(on_attack)) + RegisterSignal(parent, COMSIG_MOUSEDROP_ONTO, PROC_REF(on_mousedrop_onto)) + RegisterSignal(parent, COMSIG_MOUSEDROPPED_ONTO, PROC_REF(on_mousedropped_onto)) + RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) + RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, PROC_REF(on_preattack)) + RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(mass_empty)) + RegisterSignals(parent, list(COMSIG_CLICK_ALT, COMSIG_ATOM_ATTACK_GHOST, COMSIG_ATOM_ATTACK_HAND_SECONDARY), PROC_REF(open_storage_on_signal)) + RegisterSignal(parent, COMSIG_ATOM_ATTACKBY_SECONDARY, PROC_REF(open_storage_attackby_secondary)) + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(close_distance)) + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(update_actions)) + RegisterSignal(parent, COMSIG_TOPIC, PROC_REF(topic_handle)) + RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(handle_examination)) + RegisterSignal(parent, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(handle_extra_examination)) + RegisterSignal(parent, COMSIG_OBJ_DECONSTRUCT, PROC_REF(on_deconstruct)) + RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp_act)) /** * Sets where items are physically being stored in the case it shouldn't be on the parent. * - * @param atom/real the new real location of the datum - * @param should_drop if TRUE, all the items in the old real location will be dropped + * Does not handle moving any existing items, that must be done manually. + * + * Arguments + * * atom/new_real_location - the new real location of the datum + * * should_drop - if TRUE, all the items in the old real location will be dropped. */ -/datum/storage/proc/set_real_location(atom/real, should_drop = FALSE) - if(!real) +/datum/storage/proc/set_real_location(atom/new_real_location, should_drop = FALSE) + if(!isnull(real_location)) + UnregisterSignal(real_location, list( + COMSIG_ATOM_ENTERED, + COMSIG_ATOM_EXITED, + COMSIG_QDELETING, + COMSIG_ATOM_EMP_ACT, + )) + real_location.flags_1 &= ~HAS_DISASSOCIATED_STORAGE_1 + if(should_drop) + remove_all() + + if(isnull(new_real_location)) return - var/atom/resolve_location = src.real_location?.resolve() - if(!resolve_location) - return + real_location = new_real_location + if(real_location != parent) + real_location.flags_1 |= HAS_DISASSOCIATED_STORAGE_1 + RegisterSignal(real_location, COMSIG_ATOM_ENTERED, PROC_REF(handle_enter)) + RegisterSignal(real_location, COMSIG_ATOM_EXITED, PROC_REF(handle_exit)) + RegisterSignal(real_location, COMSIG_QDELETING, PROC_REF(real_location_deleted)) - var/atom/resolve_parent = src.parent?.resolve() - if(!resolve_parent) - return +/// Signal handler for when the real location is deleted. +/datum/storage/proc/real_location_deleted(datum/deleting_real_location) + SIGNAL_HANDLER - if(should_drop) - remove_all(get_turf(resolve_parent)) - - resolve_location.flags_1 &= ~HAS_DISASSOCIATED_STORAGE_1 - real.flags_1 |= HAS_DISASSOCIATED_STORAGE_1 - - UnregisterSignal(resolve_location, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_EXITED)) - - RegisterSignal(real, COMSIG_ATOM_ENTERED, PROC_REF(handle_enter)) - RegisterSignal(real, COMSIG_ATOM_EXITED, PROC_REF(handle_exit)) - - real_location = WEAKREF(real) + set_real_location(null) /datum/storage/proc/topic_handle(datum/source, user, href_list) SIGNAL_HANDLER + if(isnull(can_hold_description)) + return + if(href_list["show_valid_pocket_items"]) - handle_show_valid_items(source, user) + to_chat(user, span_notice("[source] can hold: [can_hold_description]")) /datum/storage/proc/handle_examination(datum/source, mob/user, list/examine_list) SIGNAL_HANDLER - if(!isnull(can_hold_description)) - examine_list += span_notice("You can examine this further to check what kind of extra items it can hold.") + if(isnull(can_hold_description)) + return + + examine_list += span_notice("You can examine this further to check what kind of extra items it can hold.") /datum/storage/proc/handle_extra_examination(datum/source, mob/user, list/examine_list) SIGNAL_HANDLER - if(!isnull(can_hold_description)) - examine_list += handle_show_valid_items(source, user) + if(isnull(can_hold_description)) + return -/datum/storage/proc/handle_show_valid_items(datum/source, user) - to_chat(user, span_notice("[source] can hold: [can_hold_description]")) + examine_list += span_notice("[source] can hold: [can_hold_description]") /// Almost 100% of the time the lists passed into set_holdable are reused for each instance /// Just fucking cache it 4head @@ -261,21 +279,22 @@ /// ~Lemon GLOBAL_LIST_EMPTY(cached_storage_typecaches) -/datum/storage/proc/set_holdable(list/can_hold_list = null, list/cant_hold_list = null) - if(!islist(can_hold_list)) +/datum/storage/proc/set_holdable(list/can_hold_list, list/cant_hold_list) + if(!isnull(can_hold_list) && !islist(can_hold_list)) can_hold_list = list(can_hold_list) - if(!islist(cant_hold_list)) + if(!isnull(cant_hold_list) && !islist(cant_hold_list)) cant_hold_list = list(cant_hold_list) - can_hold_description = generate_hold_desc(can_hold_list) + if (!isnull(can_hold_list)) + if(isnull(can_hold_description)) + can_hold_description = generate_hold_desc(can_hold_list) - if (can_hold_list) var/unique_key = can_hold_list.Join("-") if(!GLOB.cached_storage_typecaches[unique_key]) GLOB.cached_storage_typecaches[unique_key] = typecacheof(can_hold_list) can_hold = GLOB.cached_storage_typecaches[unique_key] - if (cant_hold_list != null) + if (!isnull(cant_hold_list)) var/unique_key = cant_hold_list.Join("-") if(!GLOB.cached_storage_typecaches[unique_key]) GLOB.cached_storage_typecaches[unique_key] = typecacheof(cant_hold_list) @@ -285,8 +304,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /datum/storage/proc/generate_hold_desc(can_hold_list) var/list/desc = list() - for(var/valid_type in can_hold_list) - var/obj/item/valid_item = valid_type + for(var/obj/item/valid_item as anything in can_hold_list) desc += "\a [initial(valid_item.name)]" return "\n\t[span_notice("[desc.Join("\n\t")]")]" @@ -295,21 +313,18 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /datum/storage/proc/update_actions(atom/source, mob/equipper, slot) SIGNAL_HANDLER - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) + if(!allow_quick_gather) + QDEL_NULL(modeswitch_action) + return + if(!isnull(modeswitch_action)) + return + if(!isitem(parent)) return - if(!istype(resolve_parent) || !allow_quick_gather) - QDEL_NULL(modeswitch_action_ref) - return - - var/datum/action/existing = modeswitch_action_ref?.resolve() - if(!QDELETED(existing)) - return - - var/datum/action/modeswitch_action = resolve_parent.add_item_action(/datum/action/item_action/storage_gather_mode) + var/obj/item/item_parent = parent + modeswitch_action = item_parent.add_item_action(/datum/action/item_action/storage_gather_mode) RegisterSignal(modeswitch_action, COMSIG_ACTION_TRIGGER, PROC_REF(action_trigger)) - modeswitch_action_ref = WEAKREF(modeswitch_action) + RegisterSignal(modeswitch_action, COMSIG_QDELETING, PROC_REF(action_deleted)) /// Refreshes and item to be put back into the real world, out of storage. /datum/storage/proc/reset_item(obj/item/thing) @@ -321,33 +336,23 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) thing.maptext = "" /** - * Checks if an item is capable of being inserted into the storage + * Checks if an item is capable of being inserted into the storage. * - * @param obj/item/to_insert the item we're checking - * @param messages if TRUE, will print out a message if the item is not valid - * @param force bypass locked storage up to a certain level. See [code/__DEFINES/storage.dm] + * Arguments + * * obj/item/to_insert - the item we're checking + * * messages - if TRUE, will print out a message if the item is not valid + * * force - bypass locked storage up to a certain level. See [code/__DEFINES/storage.dm] */ /datum/storage/proc/can_insert(obj/item/to_insert, mob/user, messages = TRUE, force = STORAGE_NOT_LOCKED) - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) - return - - if(QDELETED(to_insert)) - return FALSE - - if(!isitem(to_insert)) + if(QDELETED(to_insert) || !istype(to_insert)) return FALSE if(locked > force) - if(user && messages) + if(messages && user) user.balloon_alert(user, "closed!") return FALSE - if((to_insert == resolve_parent) || (to_insert == real_location)) + if((to_insert == parent) || (to_insert == real_location)) return FALSE if(to_insert.w_class > max_specific_storage) @@ -355,52 +360,45 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) if(messages && user) user.balloon_alert(user, "too big!") return FALSE - if(exception_max != INFINITE && exception_max <= exception_count()) + if(exception_max <= get_exception_count()) if(messages && user) user.balloon_alert(user, "no room!") return FALSE - if(resolve_location.contents.len >= max_slots) + if(real_location.contents.len >= max_slots) if(messages && user && !silent_for_user) user.balloon_alert(user, "no room!") return FALSE - var/total_weight = to_insert.w_class - - for(var/obj/item/thing in resolve_location) - total_weight += thing.w_class - - if(total_weight > max_total_storage) + if(to_insert.w_class + get_total_weight() > max_total_storage) if(messages && user && !silent_for_user) user.balloon_alert(user, "no room!") return FALSE - if(length(can_hold)) - if(!is_type_in_typecache(to_insert, can_hold)) - if(messages && user) - user.balloon_alert(user, "can't hold!") - return FALSE - - if(is_type_in_typecache(to_insert, cant_hold) || HAS_TRAIT(to_insert, TRAIT_NO_STORAGE_INSERT) || (can_hold_trait && !HAS_TRAIT(to_insert, can_hold_trait))) + var/can_hold_it = isnull(can_hold) || is_type_in_typecache(to_insert, can_hold) + var/cant_hold_it = is_type_in_typecache(to_insert, cant_hold) + var/trait_says_no = HAS_TRAIT(to_insert, TRAIT_NO_STORAGE_INSERT) + if(!can_hold_it || cant_hold_it || trait_says_no) if(messages && user) user.balloon_alert(user, "can't hold!") return FALSE if(HAS_TRAIT(to_insert, TRAIT_NODROP)) - if(messages) + if(messages && user) user.balloon_alert(user, "stuck on your hand!") return FALSE - var/datum/storage/biggerfish = resolve_parent.loc.atom_storage // this is valid if the container our resolve_parent is being held in is a storage item - - if(biggerfish && biggerfish.max_specific_storage < max_specific_storage) + // this is valid if the container our location is being held in is a storage item + var/datum/storage/bigger_fish = parent.loc.atom_storage + if(bigger_fish && bigger_fish.max_specific_storage < max_specific_storage) if(messages && user) - user.balloon_alert(user, "[lowertext(resolve_parent.loc.name)] is in the way!") + user.balloon_alert(user, "[lowertext(parent.loc.name)] is in the way!") return FALSE - if(istype(resolve_parent)) - var/datum/storage/item_storage = to_insert.atom_storage - if((to_insert.w_class >= resolve_parent.w_class) && item_storage && !allow_big_nesting) + if(isitem(parent)) + var/obj/item/item_parent = parent + var/datum/storage/smaller_fish = to_insert.atom_storage + if(smaller_fish && !allow_big_nesting && to_insert.w_class >= item_parent.w_class) if(messages && user) user.balloon_alert(user, "too big!") return FALSE @@ -408,63 +406,60 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) return TRUE /// Returns a count of how many items held due to exception_hold we have -/datum/storage/proc/exception_count() - var/obj/item/storage = real_location?.resolve() +/datum/storage/proc/get_exception_count() var/count = 0 - for(var/obj/item/thing in storage) + for(var/obj/item/thing in real_location) if(thing.w_class > max_specific_storage && is_type_in_typecache(thing, exception_hold)) count += 1 return count +/// Returns a sum of all of our content's weight classes +/datum/storage/proc/get_total_weight() + var/total_weight = 0 + for(var/obj/item/thing in real_location) + total_weight += thing.w_class + return total_weight + /** * Attempts to insert an item into the storage * - * @param datum/source used by the signal handler - * @param obj/item/to_insert the item we're inserting - * @param mob/user the user who is inserting the item - * @param override see item_insertion_feedback() - * @param force bypass locked storage up to a certain level. See [code/__DEFINES/storage.dm] + * Arguments + * * obj/item/to_insert - the item we're inserting + * * mob/user - (optional) the user who is inserting the item. + * * override - see item_insertion_feedback() + * * force - bypass locked storage up to a certain level. See [code/__DEFINES/storage.dm] */ /datum/storage/proc/attempt_insert(obj/item/to_insert, mob/user, override = FALSE, force = STORAGE_NOT_LOCKED) - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) - return FALSE + SHOULD_NOT_SLEEP(TRUE) if(!can_insert(to_insert, user, force = force)) return FALSE - SEND_SIGNAL(resolve_location, COMSIG_STORAGE_STORED_ITEM, to_insert, user, force) - - to_insert.item_flags |= IN_STORAGE - to_insert.forceMove(resolve_location) + SEND_SIGNAL(parent, COMSIG_STORAGE_STORED_ITEM, to_insert, user, force) + to_insert.forceMove(real_location) item_insertion_feedback(user, to_insert, override) - resolve_location.update_appearance() - SEND_SIGNAL(to_insert, COMSIG_ITEM_STORED) + parent.update_appearance() return TRUE /** * Inserts every item in a given list, with a progress bar * - * @param mob/user the user who is inserting the items - * @param list/things the list of items to insert - * @param atom/thing_loc the location of the items (used to make sure an item hasn't moved during pickup) - * @param list/rejections a list used to make sure we only complain once about an invalid insertion - * @param datum/progressbar/progress the progressbar used to show the progress of the insertion + * Arguments + * * mob/user - the user who is inserting the items + * * list/things - the list of items to insert + * * atom/thing_loc - the location of the items (used to make sure an item hasn't moved during pickup) + * * list/rejections - a list used to make sure we only complain once about an invalid insertion + * * datum/progressbar/progress - the progressbar used to show the progress of the insertion */ /datum/storage/proc/handle_mass_pickup(mob/user, list/things, atom/thing_loc, list/rejections, datum/progressbar/progress) - var/obj/item/resolve_parent = parent?.resolve() - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_parent || !resolve_location) - return - for(var/obj/item/thing in things) things -= thing if(thing.loc != thing_loc) continue if(thing.type in rejections) // To limit bag spamming: any given type only complains once continue - if(!attempt_insert(thing, user, TRUE)) // Note can_be_inserted still makes noise when the answer is no - if(resolve_location.contents.len >= max_slots) + if(!attempt_insert(thing, user, override = TRUE)) // Note can_be_inserted still makes noise when the answer is no + if(real_location.contents.len >= max_slots) break rejections += thing.type // therefore full bags are still a little spammy continue @@ -479,15 +474,12 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /** * Provides visual feedback in chat for an item insertion * - * @param mob/user the user who is inserting the item - * @param obj/item/thing the item we're inserting - * @param override skip feedback, only do animation check + * Arguments + * * mob/user - the user who is inserting the item + * * obj/item/thing - the item we're inserting + * * override - skip feedback, only do animation check */ /datum/storage/proc/item_insertion_feedback(mob/user, obj/item/thing, override = FALSE) - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - if(animated) animate_parent() @@ -498,117 +490,94 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) return if(rustle_sound) - playsound(resolve_parent, SFX_RUSTLE, 50, TRUE, -5) + playsound(parent, SFX_RUSTLE, 50, TRUE, -5) if(!silent_for_user) - to_chat(user, span_notice("You put [thing] [insert_preposition]to [resolve_parent].")) + to_chat(user, span_notice("You put [thing] [insert_preposition]to [parent].")) + + for(var/mob/viewing in oviewers(user)) + if(in_range(user, viewing) || (thing?.w_class >= WEIGHT_CLASS_NORMAL)) + viewing.show_message(span_notice("[user] puts [thing] [insert_preposition]to [parent]."), MSG_VISUAL) - for(var/mob/viewing in oviewers(user, null)) - if(in_range(user, viewing)) - viewing.show_message(span_notice("[user] puts [thing] [insert_preposition]to [resolve_parent]."), MSG_VISUAL) - return - if(thing && thing.w_class >= 3) - viewing.show_message(span_notice("[user] puts [thing] [insert_preposition]to [resolve_parent]."), MSG_VISUAL) - return /** * Attempts to remove an item from the storage * Ignores removal do_afters. Only use this if you're doing it as part of a dumping action * - * @param obj/item/thing the object we're removing - * @param atom/newLoc where we're placing the item - * @param silent if TRUE, we won't play any exit sounds + * Arguments + * * obj/item/thing - the object we're removing + * * atom/remove_to_loc - where we're placing the item + * * silent - if TRUE, we won't play any exit sounds */ -/datum/storage/proc/attempt_remove(obj/item/thing, atom/newLoc, silent = FALSE) - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return +/datum/storage/proc/attempt_remove(obj/item/thing, atom/remove_to_loc, silent = FALSE) + SHOULD_NOT_SLEEP(TRUE) - if(istype(thing)) - if(ismob(resolve_parent.loc)) - var/mob/mobparent = resolve_parent.loc - thing.dropped(mobparent, TRUE) + if(istype(thing) && ismob(parent.loc)) + var/mob/mob_parent = parent.loc + thing.dropped(mob_parent, /*silent = */TRUE) - if(newLoc) + if(remove_to_loc) reset_item(thing) - thing.forceMove(newLoc) + thing.forceMove(remove_to_loc) if(rustle_sound && !silent) - playsound(resolve_parent, SFX_RUSTLE, 50, TRUE, -5) + playsound(parent, SFX_RUSTLE, 50, TRUE, -5) else thing.moveToNullspace() - thing.item_flags &= ~IN_STORAGE - if(animated) animate_parent() refresh_views() - - if(isobj(resolve_parent)) - resolve_parent.update_appearance() - + parent.update_appearance() return TRUE /** * Removes everything inside of our storage * - * @param atom/target where we're placing the item + * Arguments + * * atom/drop_loc - where we're placing the item */ -/datum/storage/proc/remove_all(atom/target) - var/obj/item/resolve_parent = parent?.resolve() - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_parent || !resolve_location) - return - - if(!target) - target = get_turf(resolve_parent) - - for(var/obj/item/thing in resolve_location) - if(thing.loc != resolve_location) - continue - if(!attempt_remove(thing, target, silent = TRUE)) +/datum/storage/proc/remove_all(atom/drop_loc = parent.drop_location()) + for(var/obj/item/thing in real_location) + if(!attempt_remove(thing, drop_loc, silent = TRUE)) continue thing.pixel_x = thing.base_pixel_x + rand(-8, 8) thing.pixel_y = thing.base_pixel_y + rand(-8, 8) - /** * Allows a mob to attempt to remove a single item from the storage * Allows for hooks into things like removal delays * - * @param mob/removing the mob doing the removing - * @param obj/item/thing the object we're removing - * @param atom/newLoc where we're placing the item - * @param silent if TRUE, we won't play any exit sounds + * Arguments + * * mob/removing - the mob doing the removing + * * obj/item/thing - the object we're removing + * * atom/remove_to_loc - where we're placing the item + * * silent - if TRUE, we won't play any exit sounds */ -/datum/storage/proc/remove_single(mob/removing, obj/item/thing, atom/newLoc, silent = FALSE) - if(!attempt_remove(thing, newLoc, silent)) - return FALSE - return TRUE +/datum/storage/proc/remove_single(mob/removing, obj/item/thing, atom/remove_to_loc, silent = FALSE) + return attempt_remove(thing, remove_to_loc, silent) /** * Removes only a specific type of item from our storage * - * @param type the type of item to remove - * @param amount how many we should attempt to pick up at one time - * @param check_adjacent if TRUE, we'll check adjacent locations for the item type - * @param force if TRUE, we'll bypass the check_adjacent check all together - * @param mob/user the user who is removing the items - * @param list/inserted a list passed to attempt_remove for ultimate removal + * Arguments + * * type - the type of item to remove + * * amount - how many we should attempt to pick up at one time + * * check_adjacent - if TRUE, we'll check adjacent locations for the item type + * * force - if TRUE, we'll bypass the check_adjacent check all together + * * mob/user - the user who is removing the items + * * list/inserted - (optional) allows consumers to pass a list to be filled with all removed items. */ /datum/storage/proc/remove_type(type, atom/destination, amount = INFINITY, check_adjacent = FALSE, force = FALSE, mob/user, list/inserted) - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) - return + if(!force && check_adjacent) + if(isnull(user) || !user.CanReach(destination) || !user.CanReach(parent)) + return FALSE - if(!force) - if(check_adjacent) - if(!user || !user.CanReach(destination) || !user.CanReach(resolve_location)) - return FALSE - var/list/taking = typecache_filter_list(resolve_location.contents, typecacheof(type)) + var/list/taking = typecache_filter_list(real_location.contents, typecacheof(type)) if(taking.len > amount) taking.len = amount + if(inserted) //duplicated code for performance, don't bother checking retval/checking for list every item. for(var/i in taking) if(attempt_remove(i, destination)) @@ -616,41 +585,34 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) else for(var/i in taking) attempt_remove(i, destination) + return TRUE /// Signal handler for remove_all() -/datum/storage/proc/mass_empty(datum/source, atom/location, force) +/datum/storage/proc/mass_empty(datum/source, mob/user) SIGNAL_HANDLER - if(!allow_quick_empty && !force) + if(!allow_quick_empty) return - remove_all(get_turf(location)) + remove_all(user.drop_location()) /** * Recursive proc to get absolutely EVERYTHING inside a storage item, including the contents of inner items. * - * @param list/interface the list we're adding objects to - * @param recursive whether or not we're checking inside of inner items + * Arguments + * * recursive - whether or not we're checking inside of inner items */ -/datum/storage/proc/return_inv(list/interface, recursive = TRUE) - if(!islist(interface)) - return FALSE - - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) - return - +/datum/storage/proc/return_inv(recursive = TRUE) var/list/ret = list() - ret |= resolve_location.contents - if(recursive) - for(var/i in ret.Copy()) - var/atom/atom = i - atom.atom_storage?.return_inv(ret, TRUE) + ret |= real_location.contents - interface |= ret + for(var/atom/found_thing as anything in real_location) + ret |= found_thing + if(recursive) + ret |= found_thing.atom_storage?.return_inv(ret, recursive = TRUE) - return TRUE + return ret /** * Resets an object, removes it from our screen, and refreshes the view. @@ -668,18 +630,14 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) reset_item(gone) refresh_views() -/// Signal handler for the emp_act() of all contents -/datum/storage/proc/on_emp_act(datum/source, severity) +/// Signal handler for emp_act to emp all contents +/datum/storage/proc/on_emp_act(datum/source, severity, protection) SIGNAL_HANDLER - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) + if(protection & EMP_PROTECT_CONTENTS) return - if(emp_shielded) - return - - for(var/atom/thing in resolve_location) + for(var/obj/item/thing in real_location) thing.emp_act(severity) /// Signal handler for preattack from an object. @@ -706,10 +664,6 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) * @param mob/user the user who is picking up the items */ /datum/storage/proc/collect_on_turf(obj/item/thing, mob/user) - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - var/atom/holder = thing.loc var/list/pick_up = holder.contents.Copy() @@ -718,13 +672,13 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) var/amount = length(pick_up) if(!amount) - resolve_parent.balloon_alert(user, "nothing to pick up!") + parent.balloon_alert(user, "nothing to pick up!") return var/datum/progressbar/progress = new(user, amount, thing.loc) var/list/rejections = list() - while(do_after(user, 1 SECONDS, resolve_parent, NONE, FALSE, CALLBACK(src, PROC_REF(handle_mass_pickup), user, pick_up.Copy(), thing.loc, rejections, progress))) + while(do_after(user, 1 SECONDS, parent, NONE, FALSE, CALLBACK(src, PROC_REF(handle_mass_pickup), user, pick_up.Copy(), thing.loc, rejections, progress))) stoplag(1) progress.end_progress() @@ -732,29 +686,23 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) var/list/current_contents = holder.contents.Copy() if(length(pick_up | current_contents) == length(current_contents)) return - resolve_parent.balloon_alert(user, "picked up") + parent.balloon_alert(user, "picked up") /// Signal handler for whenever we drag the storage somewhere. /datum/storage/proc/on_mousedrop_onto(datum/source, atom/over_object, mob/user) SIGNAL_HANDLER - var/obj/item/resolve_parent = parent?.resolve() - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_parent || !resolve_location) - return - if(ismecha(user.loc) || user.incapacitated() || !user.canUseStorage()) return - resolve_parent.add_fingerprint(user) + parent.add_fingerprint(user) if(istype(over_object, /atom/movable/screen/inventory/hand)) - - if(resolve_parent.loc != user) + if(real_location.loc != user) return var/atom/movable/screen/inventory/hand/hand = over_object - user.putItemFromInventoryInHandIfPossible(resolve_parent, hand.held_index) + user.putItemFromInventoryInHandIfPossible(parent, hand.held_index) else if(ismob(over_object)) if(over_object != user) @@ -772,30 +720,25 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) * @param mob/user the user who is dumping the contents */ /datum/storage/proc/dump_content_at(atom/dest_object, mob/user) - var/obj/item/resolve_parent = parent.resolve() - var/obj/item/resolve_location = real_location.resolve() - if(locked) user.balloon_alert(user, "closed!") return - if(!user.CanReach(resolve_parent) || !user.CanReach(dest_object)) + if(!user.CanReach(parent) || !user.CanReach(dest_object)) return - if(SEND_SIGNAL(dest_object, COMSIG_STORAGE_DUMP_CONTENT, resolve_location, user) & STORAGE_DUMP_HANDLED) + if(SEND_SIGNAL(dest_object, COMSIG_STORAGE_DUMP_CONTENT, src, user) & STORAGE_DUMP_HANDLED) return // Storage to storage transfer is instant if(dest_object.atom_storage) - to_chat(user, span_notice("You dump the contents of [resolve_parent] into [dest_object].")) + to_chat(user, span_notice("You dump the contents of [parent] into [dest_object].")) if(rustle_sound) - playsound(resolve_parent, SFX_RUSTLE, 50, TRUE, -5) + playsound(parent, SFX_RUSTLE, 50, TRUE, -5) - for(var/obj/item/to_dump in resolve_location) - if(to_dump.loc != resolve_location) - continue + for(var/obj/item/to_dump in real_location) dest_object.atom_storage.attempt_insert(to_dump, user) - resolve_parent.update_appearance() + parent.update_appearance() SEND_SIGNAL(src, COMSIG_STORAGE_DUMP_POST_TRANSFER, dest_object, user) return @@ -804,7 +747,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) return // Storage to loc transfer requires a do_after - to_chat(user, span_notice("You start dumping out the contents of [resolve_parent] onto [dest_object]...")) + to_chat(user, span_notice("You start dumping out the contents of [parent] onto [dest_object]...")) if(!do_after(user, 2 SECONDS, target = dest_object)) return @@ -814,10 +757,6 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /datum/storage/proc/on_mousedropped_onto(datum/source, obj/item/dropping, mob/user) SIGNAL_HANDLER - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - if(!istype(dropping)) return if(dropping != user.get_active_held_item()) @@ -837,11 +776,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /datum/storage/proc/on_attackby(datum/source, obj/item/thing, mob/user, params) SIGNAL_HANDLER - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - - if(!thing.attackby_storage_insert(src, resolve_parent, user)) + if(!thing.attackby_storage_insert(src, parent, user)) return if(iscyborg(user)) @@ -854,39 +789,32 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /datum/storage/proc/on_attack(datum/source, mob/user) SIGNAL_HANDLER - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return if(!attack_hand_interact) return - if(user.active_storage == src && resolve_parent.loc == user) + if(user.active_storage == src && parent.loc == user) user.active_storage.hide_contents(user) hide_contents(user) return COMPONENT_CANCEL_ATTACK_CHAIN if(ishuman(user)) var/mob/living/carbon/human/hum = user - if(hum.l_store == resolve_parent && !hum.get_active_held_item()) - INVOKE_ASYNC(hum, TYPE_PROC_REF(/mob, put_in_hands), resolve_parent) + if(hum.l_store == parent && !hum.get_active_held_item()) + INVOKE_ASYNC(hum, TYPE_PROC_REF(/mob, put_in_hands), parent) hum.l_store = null return - if(hum.r_store == resolve_parent && !hum.get_active_held_item()) - INVOKE_ASYNC(hum, TYPE_PROC_REF(/mob, put_in_hands), resolve_parent) + if(hum.r_store == parent && !hum.get_active_held_item()) + INVOKE_ASYNC(hum, TYPE_PROC_REF(/mob, put_in_hands), parent) hum.r_store = null return - if(resolve_parent.loc == user) + if(parent.loc == user) INVOKE_ASYNC(src, PROC_REF(open_storage), user) return COMPONENT_CANCEL_ATTACK_CHAIN /// Generates the numbers on an item in storage to show stacking. /datum/storage/proc/process_numerical_display() - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) - return - var/list/toreturn = list() - for(var/obj/item/thing in resolve_location.contents) + for(var/obj/item/thing in real_location) var/total_amnt = 1 if(isstack(thing)) @@ -903,11 +831,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /// Updates the storage UI to fit all objects inside storage. /datum/storage/proc/orient_to_hud() - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) - return - - var/adjusted_contents = resolve_location.contents.len + var/adjusted_contents = real_location.contents.len //Numbered contents display var/list/datum/numbered_display/numbered_contents @@ -924,14 +848,10 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /// Generates the actual UI objects, their location, and alignments whenever we open storage up. /datum/storage/proc/orient_item_boxes(rows, cols, list/obj/item/numerical_display_contents) - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) - return - boxes.screen_loc = "[screen_start_x]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y] to [screen_start_x+cols-1]:[screen_pixel_x],[screen_start_y+rows-1]:[screen_pixel_y]" var/current_x = screen_start_x var/current_y = screen_start_y - var/turf/our_turf = get_turf(resolve_location) + var/turf/our_turf = get_turf(real_location) if(islist(numerical_display_contents)) for(var/type in numerical_display_contents) @@ -953,7 +873,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) break else - for(var/obj/item in resolve_location) + for(var/obj/item in real_location) item.mouse_opacity = MOUSE_OPACITY_OPAQUE item.screen_loc = "[current_x]:[screen_pixel_x],[current_y]:[screen_pixel_y]" item.maptext = "" @@ -991,20 +911,12 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /// Opens the storage to the mob, showing them the contents to their UI. /datum/storage/proc/open_storage(mob/to_show) - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return FALSE - - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) - return FALSE - if(isobserver(to_show)) show_contents(to_show) return FALSE - if(!to_show.CanReach(resolve_parent)) - resolve_parent.balloon_alert(to_show, "can't reach!") + if(!to_show.CanReach(parent)) + parent.balloon_alert(to_show, "can't reach!") return FALSE if(!isliving(to_show) || to_show.incapacitated()) @@ -1012,12 +924,12 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) if(locked) if(!silent) - resolve_parent.balloon_alert(to_show, "closed!") + parent.balloon_alert(to_show, "closed!") return FALSE // If we're quickdrawing boys if(quickdraw && !to_show.get_active_held_item()) - var/obj/item/to_remove = locate() in resolve_location + var/obj/item/to_remove = locate() in real_location if(!to_remove) return TRUE @@ -1025,8 +937,8 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) INVOKE_ASYNC(src, PROC_REF(put_in_hands_async), to_show, to_remove) if(!silent) to_show.visible_message( - span_warning("[to_show] draws [to_remove] from [resolve_parent]!"), - span_notice("You draw [to_remove] from [resolve_parent]."), + span_warning("[to_show] draws [to_remove] from [parent]!"), + span_notice("You draw [to_remove] from [parent]."), ) return TRUE @@ -1038,7 +950,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) animate_parent() if(rustle_sound) - playsound(resolve_parent, SFX_RUSTLE, 50, TRUE, -5) + playsound(parent, SFX_RUSTLE, 50, TRUE, -5) return TRUE @@ -1054,12 +966,8 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /datum/storage/proc/close_distance(datum/source) SIGNAL_HANDLER - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - for(var/mob/user in can_see_contents()) - if (!user.CanReach(resolve_parent)) + if (!user.CanReach(parent)) hide_contents(user) /// Close the storage UI for everyone viewing us. @@ -1085,15 +993,14 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /** * Show our storage to a mob. * - * @param mob/toshow the mob to show the storage to + * Arguments + * * mob/toshow - the mob to show the storage to * - * @returns FALSE if the show failed, TRUE otherwise + * Returns + * * FALSE if the show failed + * * TRUE otherwise */ /datum/storage/proc/show_contents(mob/toshow) - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) - return FALSE - if(!toshow.client) return FALSE @@ -1102,7 +1009,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) return FALSE if(toshow.active_storage != src && (toshow.stat == CONSCIOUS)) - for(var/obj/item/thing in resolve_location) + for(var/obj/item/thing in real_location) if(thing.on_found(toshow)) toshow.active_storage.hide_contents(toshow) @@ -1111,8 +1018,8 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) toshow.active_storage = src - if(ismovable(resolve_location)) - var/atom/movable/movable_loc = resolve_location + if(ismovable(real_location)) + var/atom/movable/movable_loc = real_location movable_loc.become_active_storage(src) orient_to_hud() @@ -1121,39 +1028,41 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) toshow.client.screen |= boxes toshow.client.screen |= closer - toshow.client.screen |= resolve_location.contents + toshow.client.screen |= real_location.contents return TRUE /** * Hide our storage from a mob. * - * @param mob/toshow the mob to hide the storage from + * Arguments + * * mob/toshow - the mob to hide the storage from */ -/datum/storage/proc/hide_contents(mob/toshow) - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) - return - - if(!toshow.client) +/datum/storage/proc/hide_contents(mob/to_hide) + if(!to_hide.client) return TRUE - if(toshow.active_storage == src) - toshow.active_storage = null + if(to_hide.active_storage == src) + to_hide.active_storage = null - if(!length(is_using) && ismovable(resolve_location)) - var/atom/movable/movable_loc = resolve_location + if(!length(is_using) && ismovable(real_location)) + var/atom/movable/movable_loc = real_location movable_loc.lose_active_storage(src) - is_using -= toshow + is_using -= to_hide - toshow.client.screen -= boxes - toshow.client.screen -= closer - toshow.client.screen -= resolve_location.contents + to_hide.client.screen -= boxes + to_hide.client.screen -= closer + to_hide.client.screen -= real_location.contents + return TRUE -/datum/storage/proc/action_trigger(datum/signal_source, datum/action/source) +/datum/storage/proc/action_trigger(datum/source, datum/action/triggered) SIGNAL_HANDLER - toggle_collection_mode(source.owner) - return TRUE + toggle_collection_mode(triggered.owner) + +/datum/storage/proc/action_deleted(datum/source) + SIGNAL_HANDLER + + modeswitch_action = null /** * Toggles the collectmode of our storage. @@ -1161,25 +1070,17 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) * @param mob/toshow the mob toggling us */ /datum/storage/proc/toggle_collection_mode(mob/user) - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - - collection_mode = (collection_mode+1)%3 + collection_mode = (collection_mode + 1) % 3 switch(collection_mode) if(COLLECT_SAME) - resolve_parent.balloon_alert(user, "will now only pick up a single type") + parent.balloon_alert(user, "will now only pick up a single type") if(COLLECT_EVERYTHING) - resolve_parent.balloon_alert(user, "will now pick up everything") + parent.balloon_alert(user, "will now pick up everything") if(COLLECT_ONE) - resolve_parent.balloon_alert(user, "will now pick up one at a time") + parent.balloon_alert(user, "will now pick up one at a time") /// Gives a spiffy animation to our parent to represent opening and closing. /datum/storage/proc/animate_parent() - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - - var/matrix/old_matrix = resolve_parent.transform - animate(resolve_parent, time = 1.5, loop = 0, transform = resolve_parent.transform.Scale(1.07, 0.9)) + var/matrix/old_matrix = parent.transform + animate(parent, time = 1.5, loop = 0, transform = parent.transform.Scale(1.07, 0.9)) animate(time = 2, transform = old_matrix) diff --git a/code/datums/storage/subtypes/bag_of_holding.dm b/code/datums/storage/subtypes/bag_of_holding.dm index 9e3a486cdcd..5abc171e2cb 100644 --- a/code/datums/storage/subtypes/bag_of_holding.dm +++ b/code/datums/storage/subtypes/bag_of_holding.dm @@ -5,33 +5,40 @@ allow_big_nesting = TRUE /datum/storage/bag_of_holding/attempt_insert(obj/item/to_insert, mob/user, override, force) - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - var/list/obj/item/storage/backpack/holding/matching = typecache_filter_list(to_insert.get_all_contents(), typecacheof(/obj/item/storage/backpack/holding)) - matching -= resolve_parent + matching -= parent + matching -= real_location - if((istype(to_insert, /obj/item/storage/backpack/holding) || matching.len) && can_insert(to_insert, user)) - INVOKE_ASYNC(src, PROC_REF(recursive_insertion), to_insert, user, resolve_parent) - return + if((istype(to_insert, /obj/item/storage/backpack/holding) || length(matching)) && can_insert(to_insert, user)) + INVOKE_ASYNC(src, PROC_REF(recursive_insertion), to_insert, user) + return FALSE return ..() -/datum/storage/bag_of_holding/proc/recursive_insertion(obj/item/to_insert, mob/living/user, atom/resolve_parent) +/datum/storage/bag_of_holding/proc/recursive_insertion(obj/item/to_insert, mob/living/user) var/safety = tgui_alert(user, "Doing this will have extremely dire consequences for the station and its crew. Be sure you know what you're doing.", "Put in [to_insert.name]?", list("Proceed", "Abort")) - if(safety != "Proceed" || QDELETED(to_insert) || QDELETED(resolve_parent) || QDELETED(user) || !iscarbon(user) || !user.can_perform_action(resolve_parent, NEED_DEXTERITY) || !can_insert(to_insert, user)) + if(safety != "Proceed" \ + || QDELETED(to_insert) \ + || QDELETED(parent) \ + || QDELETED(real_location) \ + || QDELETED(user) \ + || !user.can_perform_action(parent, NEED_DEXTERITY) \ + || !can_insert(to_insert, user) \ + ) return - var/turf/loccheck = get_turf(resolve_parent) - to_chat(user, span_danger("The Bluespace interfaces of the two devices catastrophically malfunction!")) - qdel(to_insert) - playsound(loccheck,'sound/effects/supermatter.ogg', 200, TRUE) + var/turf/rift_loc = get_turf(parent) + user.visible_message( + span_userdanger("The Bluespace interfaces of the two devices catastrophically malfunction!"), + span_danger("The Bluespace interfaces of the two devices catastrophically malfunction!"), + ) + playsound(rift_loc, 'sound/effects/supermatter.ogg', 200, TRUE) - message_admins("[ADMIN_LOOKUPFLW(user)] detonated a bag of holding at [ADMIN_VERBOSEJMP(loccheck)].") - user.log_message("detonated a bag of holding at [loc_name(loccheck)].", LOG_ATTACK, color="red") + message_admins("[ADMIN_LOOKUPFLW(user)] detonated a bag of holding at [ADMIN_VERBOSEJMP(rift_loc)].") + user.log_message("detonated a bag of holding at [loc_name(rift_loc)].", LOG_ATTACK, color = "red") user.investigate_log("has been gibbed by a bag of holding recursive insertion.", INVESTIGATE_DEATHS) user.gib() - new/obj/boh_tear(loccheck) - qdel(resolve_parent) + new /obj/boh_tear(rift_loc) + qdel(to_insert) + qdel(parent) diff --git a/code/datums/storage/subtypes/cards.dm b/code/datums/storage/subtypes/cards.dm index 19360651dd3..8e6a2bfb369 100644 --- a/code/datums/storage/subtypes/cards.dm +++ b/code/datums/storage/subtypes/cards.dm @@ -5,61 +5,52 @@ max_specific_storage = WEIGHT_CLASS_TINY max_slots = 30 max_total_storage = WEIGHT_CLASS_TINY * 30 - -/datum/storage/tcg/New() - . = ..() - set_holdable(list(/obj/item/tcgcard)) -/datum/storage/tcg/attempt_remove(obj/item/thing, atom/newLoc, silent = FALSE) +/datum/storage/tcg/New( + atom/parent, + max_slots, + max_specific_storage, + max_total_storage, +) . = ..() - handle_empty_deck() + set_holdable(/obj/item/tcgcard) + +/datum/storage/tcg/attempt_remove(obj/item/thing, atom/remove_to_loc, silent = FALSE) + . = ..() + if(!.) + return + + var/obj/item/tcgcard_deck/deck = parent + var/obj/item/tcgcard/card = thing + card.flipped = deck.flipped + card.update_appearance(UPDATE_ICON_STATE) + + if(length(real_location.contents) == 0) + qdel(parent) /datum/storage/tcg/show_contents(mob/to_show) + // sometimes, show contents is called when the mob is already seeing the contents of the deck, to refresh the view. + // to avoid spam, we only show the message if they weren't already seeing the contents. + var/was_already_seeing = to_show.active_storage == src . = ..() + if(!.) + return . + if(!was_already_seeing) + to_show.visible_message( + span_notice("[to_show] starts to look through the contents of [parent]!"), + span_notice("You begin looking into the contents of [parent]."), + ) + return . - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - - to_show.visible_message(span_notice("[to_show] starts to look through the contents of \the [resolve_parent]!"), \ - span_notice("You begin looking into the contents of \the [resolve_parent]!")) - -/datum/storage/tcg/hide_contents() +/datum/storage/tcg/hide_contents(mob/to_hide) + // see above + var/was_actually_seeing = to_hide.active_storage == src . = ..() - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) - return - - resolve_location.visible_message(span_notice("\the [resolve_parent] is shuffled after looking through it.")) - resolve_location.contents = shuffle(resolve_location.contents) - -/datum/storage/tcg/dump_content_at(atom/dest_object, mob/user) - . = ..() - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - - if(!resolve_parent.contents.len) - qdel(resolve_parent) - -/datum/storage/tcg/proc/handle_empty_deck() - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - - var/obj/item/resolve_location = real_location?.resolve() - if(!real_location) - return - - //You can't have a deck of one card! - if(resolve_location.contents.len == 1) - var/obj/item/tcgcard_deck/deck = resolve_location - var/obj/item/tcgcard/card = resolve_location.contents[1] - attempt_remove(card, card.drop_location()) - card.flipped = deck.flipped - card.update_icon_state() - qdel(resolve_parent) + if(!.) + return . + if(QDELING(src)) + return . + if(was_actually_seeing) + real_location.visible_message(span_notice("[parent] is shuffled after looking through it.")) + real_location.contents = shuffle(real_location.contents) + return . diff --git a/code/datums/storage/subtypes/duffel_bag.dm b/code/datums/storage/subtypes/duffel_bag.dm index 02c3e99b78e..cfa073da5e5 100644 --- a/code/datums/storage/subtypes/duffel_bag.dm +++ b/code/datums/storage/subtypes/duffel_bag.dm @@ -10,7 +10,12 @@ silent = TRUE exception_max = 2 -/datum/storage/duffel/syndicate/New() +/datum/storage/duffel/syndicate/New( + atom/parent, + max_slots, + max_specific_storage, + max_total_storage, +) . = ..() var/static/list/exception_type_list = list( diff --git a/code/datums/storage/subtypes/extract_inventory.dm b/code/datums/storage/subtypes/extract_inventory.dm index 8c571dbda1a..0fea7ffed63 100644 --- a/code/datums/storage/subtypes/extract_inventory.dm +++ b/code/datums/storage/subtypes/extract_inventory.dm @@ -8,31 +8,28 @@ rustle_sound = FALSE silent = TRUE -/datum/storage/extract_inventory/New() +/datum/storage/extract_inventory/New( + atom/parent, + max_slots, + max_specific_storage, + max_total_storage, +) . = ..() set_holdable(/obj/item/food/monkeycube) - var/obj/item/slimecross/reproductive/parentSlimeExtract = parent?.resolve() - if(!parentSlimeExtract) - return - - if(!istype(parentSlimeExtract, /obj/item/slimecross/reproductive)) - stack_trace("storage subtype extract_inventory incompatible with [parentSlimeExtract]") + var/obj/item/slimecross/reproductive/parent_slime = parent + if(!istype(parent_slime, /obj/item/slimecross/reproductive)) + stack_trace("storage subtype ([type]) incompatible with [parent_slime] ([parent_slime.type])") qdel(src) /datum/storage/extract_inventory/proc/processCubes(mob/user) - var/obj/item/slimecross/reproductive/parentSlimeExtract = parent?.resolve() - if(!parentSlimeExtract) - return - - if(parentSlimeExtract.contents.len >= max_slots) + var/obj/item/slimecross/reproductive/parentSlimeExtract = parent + if(real_location.contents.len >= max_slots) QDEL_LIST(parentSlimeExtract.contents) createExtracts(user) /datum/storage/extract_inventory/proc/createExtracts(mob/user) - var/obj/item/slimecross/reproductive/parentSlimeExtract = parent?.resolve() - if(!parentSlimeExtract) - return + var/obj/item/slimecross/reproductive/parentSlimeExtract = parent var/cores = rand(1,4) playsound(parentSlimeExtract, 'sound/effects/splat.ogg', 40, TRUE) diff --git a/code/datums/storage/subtypes/fish_case.dm b/code/datums/storage/subtypes/fish_case.dm index bc16f1607bf..dbbb15f47eb 100644 --- a/code/datums/storage/subtypes/fish_case.dm +++ b/code/datums/storage/subtypes/fish_case.dm @@ -1,33 +1,48 @@ /datum/storage/fish_case max_slots = 1 max_specific_storage = WEIGHT_CLASS_HUGE - can_hold_trait = TRAIT_FISH_CASE_COMPATIBILE - can_hold_description = "fish and aquarium equipment" + can_hold_description = "Fish and aquarium equipment" -/** +/datum/storage/fish_case/can_insert(obj/item/to_insert, mob/user, messages, force) + . = ..() + if(!.) + return . + if(!HAS_TRAIT(to_insert, TRAIT_FISH_CASE_COMPATIBILE)) + if(messages && user) + user.balloon_alert(user, "can't hold!") + return FALSE + return . + +/* * Change the size of the storage item to match the inserted item's * Because of that, we also check if conditions to keep it inside another storage or pockets are still met. */ -/datum/storage/fish_case/handle_enter(obj/item/storage/fish_case/source, obj/item/arrived) +/datum/storage/fish_case/handle_enter(datum/source, obj/item/arrived) . = ..() - if(!istype(arrived) || arrived.w_class == source.w_class) + if(!isitem(parent) || !istype(arrived)) return - source.w_class = arrived.w_class - var/obj/item/resolve_parent = parent?.resolve() - if(resolve_parent?.item_flags & IN_STORAGE) - source.moveToNullspace() //temporarily remove source from its location so that attempt_insert may work correctly. - if(!resolve_parent.atom_storage?.attempt_insert(source, override = TRUE)) - source.forceMove(resolve_parent.drop_location()) - source.visible_message("[source] spills out of [resolve_parent] as it expands to hold [arrived]", vision_distance = 1) - else if(!isliving(source.loc)) + var/obj/item/item_parent = parent + if(arrived.w_class <= item_parent.w_class) + return + item_parent.w_class = arrived.w_class + // Since we're changing weight class we need to check if our storage's loc's storage can still hold us + // in the future we need a generic solution to this to solve a bunch of other exploits + var/datum/storage/loc_storage = item_parent.loc.atom_storage + if(!isnull(loc_storage) && !loc_storage.can_insert(item_parent)) + item_parent.forceMove(item_parent.loc.drop_location()) + item_parent.visible_message(span_warning("[item_parent] spills out of [item_parent.loc] as it expands to hold [arrived]!"), vision_distance = 1) return - var/mob/living/living_loc = source.loc - var/equipped_slot = living_loc.get_slot_by_item(source) - if(equipped_slot & (ITEM_SLOT_RPOCKET|ITEM_SLOT_LPOCKET) && source.w_class > WEIGHT_CLASS_SMALL) - source.forceMove(living_loc.drop_location()) - to_chat(living_loc, "[source] drops out of your pockets as it expands to hold [arrived]") -/datum/storage/fish_case/handle_exit(obj/item/storage/fish_case/source, obj/item/gone) + if(isliving(item_parent.loc)) + var/mob/living/living_loc = item_parent.loc + if((living_loc.get_slot_by_item(item_parent) & (ITEM_SLOT_RPOCKET|ITEM_SLOT_LPOCKET)) && item_parent.w_class > WEIGHT_CLASS_SMALL) + item_parent.forceMove(living_loc.drop_location()) + to_chat(living_loc, span_warning("[item_parent] drops out of your pockets as it expands to hold [arrived]!")) + return + +/datum/storage/fish_case/handle_exit(datum/source, obj/item/gone) . = ..() - if(istype(gone)) - source.w_class = initial(source.w_class) + if(!isitem(parent) || !istype(gone)) + return + var/obj/item/item_parent = parent + item_parent.w_class = initial(item_parent.w_class) diff --git a/code/datums/storage/subtypes/implant.dm b/code/datums/storage/subtypes/implant.dm index 998e19a587c..547e79ba81c 100644 --- a/code/datums/storage/subtypes/implant.dm +++ b/code/datums/storage/subtypes/implant.dm @@ -5,6 +5,11 @@ silent = TRUE allow_big_nesting = TRUE -/datum/storage/implant/New() +/datum/storage/implant/New( + atom/parent, + max_slots, + max_specific_storage, + max_total_storage, +) . = ..() - set_holdable(cant_hold_list = list(/obj/item/disk/nuclear)) + set_holdable(cant_hold_list = /obj/item/disk/nuclear) diff --git a/code/datums/storage/subtypes/pockets.dm b/code/datums/storage/subtypes/pockets.dm index 4bd60ba57b6..67a8b2dda78 100644 --- a/code/datums/storage/subtypes/pockets.dm +++ b/code/datums/storage/subtypes/pockets.dm @@ -9,17 +9,13 @@ if(!.) return - var/obj/item/resolve_parent = parent?.resolve() - if(!resolve_parent) - return - if(!silent || override) return if(quickdraw) - to_chat(user, span_notice("You discreetly slip [to_insert] into [resolve_parent]. Right-click [resolve_parent] to remove it.")) + to_chat(user, span_notice("You discreetly slip [to_insert] into [parent]. Right-click to remove it.")) else - to_chat(user, span_notice("You discreetly slip [to_insert] into [resolve_parent].")) + to_chat(user, span_notice("You discreetly slip [to_insert] into [parent].")) /datum/storage/pockets/small max_slots = 1 @@ -31,7 +27,12 @@ max_specific_storage = WEIGHT_CLASS_TINY attack_hand_interact = FALSE -/datum/storage/pockets/small/fedora/New() +/datum/storage/pockets/small/fedora/New( + atom/parent, + max_slots, + max_specific_storage, + max_total_storage, +) . = ..() var/static/list/exception_cache = typecacheof(list( /obj/item/katana, @@ -50,7 +51,12 @@ max_slots = 1 max_specific_storage = WEIGHT_CLASS_NORMAL -/datum/storage/pockets/chefhat/New() +/datum/storage/pockets/chefhat/New( + atom/parent, + max_slots, + max_specific_storage, + max_total_storage, +) . = ..() set_holdable(list( /obj/item/clothing/head/mob_holder, @@ -71,7 +77,12 @@ quickdraw = TRUE silent = TRUE -/datum/storage/pockets/shoes/New() +/datum/storage/pockets/shoes/New( + atom/parent, + max_slots, + max_specific_storage, + max_total_storage, +) . = ..() set_holdable(list( /obj/item/knife, @@ -108,61 +119,80 @@ /obj/item/toy/crayon/spraycan) ) -/datum/storage/pockets/shoes/clown/New() +/datum/storage/pockets/shoes/clown/New( + atom/parent, + max_slots, + max_specific_storage, + max_total_storage, +) . = ..() - set_holdable(list( - /obj/item/knife, - /obj/item/spess_knife, - /obj/item/switchblade, - /obj/item/pen, - /obj/item/scalpel, - /obj/item/reagent_containers/syringe, - /obj/item/dnainjector, - /obj/item/reagent_containers/hypospray/medipen, - /obj/item/reagent_containers/dropper, - /obj/item/implanter, - /obj/item/screwdriver, - /obj/item/weldingtool/mini, - /obj/item/firing_pin, - /obj/item/suppressor, - /obj/item/ammo_box/magazine/m9mm, - /obj/item/ammo_box/magazine/m10mm, - /obj/item/ammo_box/magazine/m45, - /obj/item/ammo_casing, - /obj/item/lipstick, - /obj/item/clothing/mask/cigarette, - /obj/item/lighter, - /obj/item/match, - /obj/item/holochip, - /obj/item/toy/crayon, - /obj/item/bikehorn, - /obj/item/reagent_containers/cup/glass/flask), - list(/obj/item/screwdriver/power, - /obj/item/ammo_casing/rocket, - /obj/item/clothing/mask/cigarette/pipe, - /obj/item/toy/crayon/spraycan) - ) + set_holdable( + can_hold_list = list( + /obj/item/ammo_box/magazine/m10mm, + /obj/item/ammo_box/magazine/m45, + /obj/item/ammo_box/magazine/m9mm, + /obj/item/ammo_casing, + /obj/item/bikehorn, + /obj/item/clothing/mask/cigarette, + /obj/item/dnainjector, + /obj/item/firing_pin, + /obj/item/holochip, + /obj/item/implanter, + /obj/item/knife, + /obj/item/lighter, + /obj/item/lipstick, + /obj/item/match, + /obj/item/pen, + /obj/item/reagent_containers/cup/glass/flask, + /obj/item/reagent_containers/dropper, + /obj/item/reagent_containers/hypospray/medipen, + /obj/item/reagent_containers/syringe, + /obj/item/scalpel, + /obj/item/screwdriver, + /obj/item/spess_knife, + /obj/item/suppressor, + /obj/item/switchblade, + /obj/item/toy/crayon, + /obj/item/weldingtool/mini, + ), + cant_hold_list = list( + /obj/item/ammo_casing/rocket, + /obj/item/clothing/mask/cigarette/pipe, + /obj/item/screwdriver/power, + /obj/item/toy/crayon/spraycan, + ), + ) /datum/storage/pockets/pocketprotector max_slots = 3 max_specific_storage = WEIGHT_CLASS_TINY -/datum/storage/pockets/pocketprotector/New() +/datum/storage/pockets/pocketprotector/New( + atom/parent, + max_slots, + max_specific_storage, + max_total_storage, +) . = ..() set_holdable(list( //Same items as a PDA /obj/item/pen, /obj/item/toy/crayon, /obj/item/lipstick, /obj/item/flashlight/pen, - /obj/item/clothing/mask/cigarette) - ) + /obj/item/lipstick, + )) /datum/storage/pockets/helmet max_slots = 2 quickdraw = TRUE max_total_storage = 6 -/datum/storage/pockets/helmet/New() +/datum/storage/pockets/helmet/New( + atom/parent, + max_slots, + max_specific_storage, + max_total_storage, +) . = ..() set_holdable(list(/obj/item/reagent_containers/cup/glass/bottle/vodka, /obj/item/reagent_containers/cup/glass/bottle/molotov, @@ -175,7 +205,12 @@ max_total_storage = 5 // 2 small items + 1 tiny item, or 1 normal item + 1 small item max_slots = 3 -/datum/storage/pockets/void_cloak/New() +/datum/storage/pockets/void_cloak/New( + atom/parent, + max_slots, + max_specific_storage, + max_total_storage, +) . = ..() set_holdable(list( /obj/item/ammo_box/strilka310/lionhunter, diff --git a/code/datums/storage/subtypes/rped.dm b/code/datums/storage/subtypes/rped.dm index 599d63fd7db..9931cff7372 100644 --- a/code/datums/storage/subtypes/rped.dm +++ b/code/datums/storage/subtypes/rped.dm @@ -32,13 +32,10 @@ /obj/item/stack/sheet/bluespace_crystal, ) -/datum/storage/rped/New(atom/parent, max_slots, max_specific_storage, max_total_storage, numerical_stacking, allow_quick_gather, allow_quick_empty, collection_mode, attack_hand_interact) - . = ..() - var/atom/resolve_parent = src.parent?.resolve() - RegisterSignal(resolve_parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(rped_mass_empty), TRUE) - /datum/storage/rped/can_insert(obj/item/to_insert, mob/user, messages = TRUE, force = FALSE) . = ..() + if(!.) + return . //we check how much of glass,plasteel & cable the user can insert if(isstack(to_insert)) @@ -49,12 +46,8 @@ var/obj/item/stack/the_stack = to_insert var/present_amount = 0 - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) - return FALSE - //we try to count & limit how much the user can insert of each type to prevent them from using it as an normal storage medium - for(var/obj/item/stack/stack_content in resolve_location.contents) + for(var/obj/item/stack/stack_content in real_location) //is user trying to insert any of these listed bluespace stuff if(is_type_in_list(to_insert, allowed_bluespace_types)) //if yes count total bluespace stuff is the RPED and then compare the total amount to the value the user is trying to insert @@ -83,44 +76,35 @@ return . -/// overridden mass_empty, so as to dump only the lowest tier of parts currently in the RPED -/datum/storage/rped/proc/rped_mass_empty(datum/source, atom/location, force) - SIGNAL_HANDLER - - if(!allow_quick_empty && !force) +/datum/storage/rped/mass_empty(datum/source, mob/user) + if(!allow_quick_empty) return - remove_lowest_tier(get_turf(location)) + remove_lowest_tier(user.drop_location()) /** * Searches through everything currently in storage, calculates the lowest tier of parts inside of it, * and then dumps out every part that has the equal tier of parts. Likely a worse implementation of remove_all. * - * @param atom/target where we're placing the item + * Arguments + * * atom/dump_loc - where we're placing the item */ -/datum/storage/rped/proc/remove_lowest_tier(atom/target) // look whatever happens here i'm not proud of this. at all. - var/obj/item/resolve_parent = parent?.resolve() - var/obj/item/resolve_location = real_location?.resolve() +/datum/storage/rped/proc/remove_lowest_tier(atom/dump_loc = parent.drop_location()) var/list/obj/item/parts_list = list() var/current_lowest_tier = INFINITY - if(!resolve_parent || !resolve_location) - return - if(!target) - target = get_turf(resolve_parent) + for(var/obj/item/thing in real_location) + parts_list += thing - for(var/obj/item/thing in resolve_location) - if(thing.loc != resolve_location) - continue - parts_list.Add(thing) if(parts_list.len > 0) parts_list = reverse_range(sortTim(parts_list, GLOBAL_PROC_REF(cmp_rped_sort))) current_lowest_tier = parts_list[1].get_part_rating() - resolve_parent.balloon_alert(resolve_parent.loc, "dropping lowest rated parts...") + if(ismob(parent.loc)) + parent.balloon_alert(parent.loc, "dropping lowest rated parts...") for(var/obj/item/part in parts_list) if(part.get_part_rating() != current_lowest_tier) break - if(!attempt_remove(part, target, silent = TRUE)) + if(!attempt_remove(part, dump_loc, silent = TRUE)) continue part.pixel_x = part.base_pixel_x + rand(-8, 8) part.pixel_y = part.base_pixel_y + rand(-8, 8) diff --git a/code/datums/storage/subtypes/surgery_tray.dm b/code/datums/storage/subtypes/surgery_tray.dm index c5b07b15fe4..c4d8780e051 100644 --- a/code/datums/storage/subtypes/surgery_tray.dm +++ b/code/datums/storage/subtypes/surgery_tray.dm @@ -4,7 +4,12 @@ max_slots = 14 animated = FALSE -/datum/storage/surgery_tray/New() +/datum/storage/surgery_tray/New( + atom/parent, + max_slots, + max_specific_storage, + max_total_storage, +) . = ..() set_holdable(list( /obj/item/autopsy_scanner, diff --git a/code/datums/storage/subtypes/trash.dm b/code/datums/storage/subtypes/trash.dm index 650dcf4bb49..b4f0e4353e3 100644 --- a/code/datums/storage/subtypes/trash.dm +++ b/code/datums/storage/subtypes/trash.dm @@ -1,14 +1,11 @@ /datum/storage/trash -/datum/storage/trash/remove_single(mob/removing, obj/item/thing, atom/newLoc, silent) - var/obj/item/resolve_location = real_location?.resolve() - if(!resolve_location) - return - - resolve_location.visible_message(span_notice("[removing] starts fishing around inside \the [resolve_location]."), - span_notice("You start digging around in \the [resolve_location] to try and pull something out.")) - if(!do_after(removing, 1.5 SECONDS, resolve_location)) - return +/datum/storage/trash/remove_single(mob/removing, obj/item/thing, atom/remove_to_loc, silent) + real_location.visible_message( + span_notice("[removing] starts fishing around inside [parent]."), + span_notice("You start digging around in [parent] to try and pull something out."), + ) + if(!do_after(removing, 1.5 SECONDS, parent)) + return FALSE return ..() - diff --git a/code/game/atom/atom_storage.dm b/code/game/atom/atom_storage.dm index 6273c28fc2e..24ab0887742 100644 --- a/code/game/atom/atom_storage.dm +++ b/code/game/atom/atom_storage.dm @@ -7,32 +7,34 @@ max_slots, max_specific_storage, max_total_storage, - numerical_stacking = FALSE, - allow_quick_gather = FALSE, - allow_quick_empty = FALSE, - collection_mode = COLLECT_ONE, - attack_hand_interact = TRUE, list/canhold, list/canthold, storage_type = /datum/storage, ) + RETURN_TYPE(/datum/storage) if(atom_storage) QDEL_NULL(atom_storage) - atom_storage = new storage_type(src, max_slots, max_specific_storage, max_total_storage, numerical_stacking, allow_quick_gather, collection_mode, attack_hand_interact) + atom_storage = new storage_type(src, max_slots, max_specific_storage, max_total_storage) if(canhold || canthold) atom_storage.set_holdable(canhold, canthold) return atom_storage -/// A quick and easy way to /clone/ a storage datum for an atom (does not copy over contents, only the datum details) +/** + * A quick and easy way to /clone/ a storage datum for an atom (does not copy over contents, only the datum details) + * + * Imperfect, does not copy over ALL variables, only important ones (max storage size, etc) + */ /atom/proc/clone_storage(datum/storage/cloning) + RETURN_TYPE(/datum/storage) + if(atom_storage) QDEL_NULL(atom_storage) - atom_storage = new cloning.type(src, cloning.max_slots, cloning.max_specific_storage, cloning.max_total_storage, cloning.numerical_stacking, cloning.allow_quick_gather, cloning.collection_mode, cloning.attack_hand_interact) + atom_storage = new cloning.type(src, cloning.max_slots, cloning.max_specific_storage, cloning.max_total_storage) if(cloning.can_hold || cloning.cant_hold) if(!atom_storage.can_hold && !atom_storage.cant_hold) //In the event that the can/can't hold lists are already in place (such as from storage objects added on initialize). diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 3adfaec914a..4fde70adbeb 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -766,8 +766,7 @@ /obj/item/on_exit_storage(datum/storage/master_storage) . = ..() - var/atom/location = master_storage.real_location?.resolve() - do_drop_animation(location) + do_drop_animation(master_storage.parent) /obj/item/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(QDELETED(hit_atom)) diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 3090842b65a..395faaa5449 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -691,12 +691,14 @@ /obj/item/storage/crayons/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/toy/crayon), - list( + atom_storage.set_holdable( + can_hold_list = /obj/item/toy/crayon, + cant_hold_list = list( /obj/item/toy/crayon/spraycan, /obj/item/toy/crayon/mime, /obj/item/toy/crayon/rainbow, - )) + ), + ) /obj/item/storage/crayons/PopulateContents() new /obj/item/toy/crayon/red(src) diff --git a/code/game/objects/items/dice.dm b/code/game/objects/items/dice.dm index 4e63fc00c43..6f425b7df6e 100644 --- a/code/game/objects/items/dice.dm +++ b/code/game/objects/items/dice.dm @@ -13,7 +13,7 @@ /obj/item/storage/dice/Initialize(mapload) . = ..() atom_storage.allow_quick_gather = TRUE - atom_storage.set_holdable(list(/obj/item/dice)) + atom_storage.set_holdable(/obj/item/dice) /obj/item/storage/dice/PopulateContents() new /obj/item/dice/d4(src) diff --git a/code/game/objects/items/implants/implant_storage.dm b/code/game/objects/items/implants/implant_storage.dm index bfbf8cf1c24..5734beb7683 100644 --- a/code/game/objects/items/implants/implant_storage.dm +++ b/code/game/objects/items/implants/implant_storage.dm @@ -19,7 +19,7 @@ atom_storage.remove_all() implantee.visible_message(span_warning("A bluespace pocket opens around [src] as it exits [implantee], spewing out its contents and rupturing the surrounding tissue!")) implantee.apply_damage(20, BRUTE, BODY_ZONE_CHEST) - qdel(atom_storage) + QDEL_NULL(atom_storage) return ..() /obj/item/implant/storage/implant(mob/living/target, mob/user, silent = FALSE, force = FALSE) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 15f21b93ee9..15c0d678648 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -117,14 +117,10 @@ return ..() /obj/item/melee/sabre/on_exit_storage(datum/storage/container) - var/obj/item/storage/belt/sabre/sabre = container.real_location?.resolve() - if(istype(sabre)) - playsound(sabre, 'sound/items/unsheath.ogg', 25, TRUE) + playsound(container.parent, 'sound/items/unsheath.ogg', 25, TRUE) /obj/item/melee/sabre/on_enter_storage(datum/storage/container) - var/obj/item/storage/belt/sabre/sabre = container.real_location?.resolve() - if(istype(sabre)) - playsound(sabre, 'sound/items/sheath.ogg', 25, TRUE) + playsound(container.parent, 'sound/items/sheath.ogg', 25, TRUE) /obj/item/melee/sabre/suicide_act(mob/living/user) user.visible_message(span_suicide("[user] is trying to cut off all [user.p_their()] limbs with [src]! it looks like [user.p_theyre()] trying to commit suicide!")) diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index f5783d30c8d..68463dad2b0 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -385,7 +385,7 @@ . = ..() AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE, INVISIBILITY_OBSERVER, use_anchor = TRUE) atom_storage.max_total_storage = 15 - atom_storage.set_holdable(cant_hold_list = list(/obj/item/storage/backpack/satchel/flat)) //muh recursive backpacks) + atom_storage.set_holdable(cant_hold_list = /obj/item/storage/backpack/satchel/flat) //muh recursive backpacks /obj/item/storage/backpack/satchel/flat/PopulateContents() for(var/items in 1 to 4) diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index 6c4c8a881e9..d72a57f07f1 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -49,7 +49,7 @@ atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL atom_storage.max_total_storage = 30 atom_storage.max_slots = 30 - atom_storage.set_holdable(cant_hold_list = list(/obj/item/disk/nuclear)) + atom_storage.set_holdable(cant_hold_list = /obj/item/disk/nuclear) atom_storage.supports_smart_equip = FALSE RegisterSignal(atom_storage, COMSIG_STORAGE_DUMP_POST_TRANSFER, PROC_REF(post_insertion)) @@ -137,7 +137,7 @@ atom_storage.numerical_stacking = TRUE atom_storage.allow_quick_empty = TRUE atom_storage.allow_quick_gather = TRUE - atom_storage.set_holdable(list(/obj/item/stack/ore)) + atom_storage.set_holdable(/obj/item/stack/ore) atom_storage.silent_for_user = TRUE /obj/item/storage/bag/ore/equipped(mob/user) @@ -245,8 +245,7 @@ /obj/item/grown, /obj/item/food/honeycomb, /obj/item/seeds, - )) -//////// + )) /obj/item/storage/bag/plants/portaseeder name = "portable seed extractor" @@ -290,20 +289,22 @@ icon_state = "sheetsnatcher" worn_icon_state = "satchel" - var/capacity = 300; //the number of sheets it can carry. + var/capacity = 300 //the number of sheets it can carry. /obj/item/storage/bag/sheetsnatcher/Initialize(mapload) . = ..() atom_storage.allow_quick_empty = TRUE atom_storage.allow_quick_gather = TRUE atom_storage.numerical_stacking = TRUE - atom_storage.set_holdable(list( + atom_storage.set_holdable( + can_hold_list = list( /obj/item/stack/sheet - ), - list( + ), + cant_hold_list = list( /obj/item/stack/sheet/mineral/sandstone, /obj/item/stack/sheet/mineral/wood, - )) + ), + ) atom_storage.max_total_storage = capacity / 2 // ----------------------------- @@ -373,7 +374,7 @@ /obj/item/storage/box/matches, /obj/item/storage/fancy, /obj/item/trash, - )) //Should cover: Bottles, Beakers, Bowls, Booze, Glasses, Food, Food Containers, Food Trash, Organs, Tobacco Products, Lighters, and Kitchen Tools. + )) //Should cover: Bottles, Beakers, Bowls, Booze, Glasses, Food, Food Containers, Food Trash, Organs, Tobacco Products, Lighters, and Kitchen Tools. atom_storage.insert_preposition = "on" atom_storage.max_slots = 7 @@ -457,7 +458,7 @@ /obj/item/reagent_containers/medigel, /obj/item/reagent_containers/pill, /obj/item/reagent_containers/syringe, - )) + )) /* * Biowaste bag (mostly for virologists) @@ -487,7 +488,7 @@ /obj/item/reagent_containers/cup/tube, /obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/syringe, - )) + )) /* * Science bag (mostly for xenobiologists) @@ -518,7 +519,7 @@ /obj/item/reagent_containers/syringe, /obj/item/slime_extract, /obj/item/swab, - )) + )) /* * Construction bag (for engineering, holds stock parts and electronics) @@ -547,7 +548,7 @@ /obj/item/stack/ore/bluespace_crystal, /obj/item/stock_parts, /obj/item/wallframe/camera, - )) + )) /obj/item/storage/bag/harpoon_quiver name = "harpoon quiver" @@ -562,9 +563,7 @@ atom_storage.max_specific_storage = WEIGHT_CLASS_TINY atom_storage.max_slots = 40 atom_storage.max_total_storage = 100 - atom_storage.set_holdable(list( - /obj/item/ammo_casing/harpoon - )) + atom_storage.set_holdable(/obj/item/ammo_casing/harpoon) /obj/item/storage/bag/harpoon_quiver/PopulateContents() for(var/i in 1 to 40) diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index 19f6c35ca77..02f9a8be240 100644 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -487,9 +487,7 @@ /obj/item/storage/belt/soulstone/Initialize(mapload) . = ..() atom_storage.max_slots = 6 - atom_storage.set_holdable(list( - /obj/item/soulstone, - )) + atom_storage.set_holdable(/obj/item/soulstone) /obj/item/storage/belt/soulstone/full/PopulateContents() for(var/i in 1 to 6) @@ -510,9 +508,7 @@ /obj/item/storage/belt/champion/Initialize(mapload) . = ..() atom_storage.max_slots = 1 - atom_storage.set_holdable(list( - /obj/item/clothing/mask/luchador, - )) + atom_storage.set_holdable(/obj/item/clothing/mask/luchador) /obj/item/storage/belt/military name = "chest rig" @@ -663,9 +659,7 @@ /obj/item/storage/belt/wands/Initialize(mapload) . = ..() atom_storage.max_slots = 6 - atom_storage.set_holdable(list( - /obj/item/gun/magic/wand, - )) + atom_storage.set_holdable(/obj/item/gun/magic/wand) /obj/item/storage/belt/wands/full/PopulateContents() new /obj/item/gun/magic/wand/death(src) @@ -824,11 +818,7 @@ atom_storage.max_slots = 1 atom_storage.rustle_sound = FALSE atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY - atom_storage.set_holdable( - list( - /obj/item/melee/sabre, - ) - ) + atom_storage.set_holdable(/obj/item/melee/sabre) /obj/item/storage/belt/sabre/examine(mob/user) . = ..() diff --git a/code/game/objects/items/storage/boxes/food_boxes.dm b/code/game/objects/items/storage/boxes/food_boxes.dm index 3e23d604f6d..c49fa288eb3 100644 --- a/code/game/objects/items/storage/boxes/food_boxes.dm +++ b/code/game/objects/items/storage/boxes/food_boxes.dm @@ -14,7 +14,7 @@ /obj/item/storage/box/donkpockets/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/food/donkpocket)) + atom_storage.set_holdable(/obj/item/food/donkpocket) /obj/item/storage/box/donkpockets/donkpocketspicy name = "box of spicy-flavoured donk-pockets" @@ -337,7 +337,7 @@ /obj/item/storage/box/gum/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/food/bubblegum)) + atom_storage.set_holdable(/obj/item/food/bubblegum) atom_storage.max_slots = 4 /obj/item/storage/box/gum/PopulateContents() @@ -508,7 +508,7 @@ /obj/item/storage/box/coffeepack/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/food/grown/coffee)) + atom_storage.set_holdable(/obj/item/food/grown/coffee) /obj/item/storage/box/coffeepack/PopulateContents() atom_storage.max_slots = 5 diff --git a/code/game/objects/items/storage/boxes/medical_boxes.dm b/code/game/objects/items/storage/boxes/medical_boxes.dm index 0e3e800bef8..55c5733a51e 100644 --- a/code/game/objects/items/storage/boxes/medical_boxes.dm +++ b/code/game/objects/items/storage/boxes/medical_boxes.dm @@ -151,7 +151,7 @@ /obj/item/stack/medical/bandage, /obj/item/reagent_containers/pill, /obj/item/reagent_containers/pill/patch, - )) + )) /obj/item/storage/box/bandages/PopulateContents() for(var/i in 1 to 5) diff --git a/code/game/objects/items/storage/boxes/science_boxes.dm b/code/game/objects/items/storage/boxes/science_boxes.dm index cc8d0e7f3d0..f0654cdf024 100644 --- a/code/game/objects/items/storage/boxes/science_boxes.dm +++ b/code/game/objects/items/storage/boxes/science_boxes.dm @@ -43,7 +43,7 @@ /obj/item/storage/box/monkeycubes/Initialize(mapload) . = ..() atom_storage.max_slots = 7 - atom_storage.set_holdable(list(/obj/item/food/monkeycube)) + atom_storage.set_holdable(/obj/item/food/monkeycube) /obj/item/storage/box/monkeycubes/PopulateContents() for(var/i in 1 to 5) @@ -62,7 +62,7 @@ /obj/item/storage/box/gorillacubes/Initialize(mapload) . = ..() atom_storage.max_slots = 3 - atom_storage.set_holdable(list(/obj/item/food/monkeycube)) + atom_storage.set_holdable(/obj/item/food/monkeycube) /obj/item/storage/box/gorillacubes/PopulateContents() for(var/i in 1 to 3) diff --git a/code/game/objects/items/storage/boxes/service_boxes.dm b/code/game/objects/items/storage/boxes/service_boxes.dm index 56f59b5572e..14656f0f5f7 100644 --- a/code/game/objects/items/storage/boxes/service_boxes.dm +++ b/code/game/objects/items/storage/boxes/service_boxes.dm @@ -63,7 +63,7 @@ /obj/item/storage/box/snappops/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/toy/snappop)) + atom_storage.set_holdable(/obj/item/toy/snappop) atom_storage.max_slots = 8 /obj/item/storage/box/snappops/PopulateContents() @@ -90,7 +90,7 @@ /obj/item/storage/box/matches/Initialize(mapload) . = ..() atom_storage.max_slots = 10 - atom_storage.set_holdable(list(/obj/item/match)) + atom_storage.set_holdable(/obj/item/match) /obj/item/storage/box/matches/PopulateContents() for(var/i in 1 to 10) diff --git a/code/game/objects/items/storage/fancy.dm b/code/game/objects/items/storage/fancy.dm index e1c21d1305c..a7fbe6e7452 100644 --- a/code/game/objects/items/storage/fancy.dm +++ b/code/game/objects/items/storage/fancy.dm @@ -106,7 +106,7 @@ /obj/item/storage/fancy/donut_box/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/food/donut)) + atom_storage.set_holdable(/obj/item/food/donut) /obj/item/storage/fancy/donut_box/PopulateContents() . = ..() @@ -153,7 +153,7 @@ /obj/item/storage/fancy/egg_box/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/food/egg)) + atom_storage.set_holdable(/obj/item/food/egg) /* * Fertile Egg Box @@ -186,7 +186,7 @@ /obj/item/storage/fancy/candle_box/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/flashlight/flare/candle)) + atom_storage.set_holdable(/obj/item/flashlight/flare/candle) //////////// //CIG PACK// @@ -405,7 +405,7 @@ /obj/item/storage/fancy/rollingpapers/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/rollingpaper)) + atom_storage.set_holdable(/obj/item/rollingpaper) /obj/item/storage/fancy/rollingpapers/update_overlays() . = ..() @@ -431,7 +431,7 @@ /obj/item/storage/fancy/cigarettes/cigars/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/clothing/mask/cigarette/cigar)) + atom_storage.set_holdable(/obj/item/clothing/mask/cigarette/cigar) /obj/item/storage/fancy/cigarettes/cigars/update_icon_state() . = ..() @@ -486,7 +486,7 @@ /obj/item/storage/fancy/heart_box/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/food/bonbon)) + atom_storage.set_holdable(/obj/item/food/bonbon) /obj/item/storage/fancy/nugget_box @@ -501,7 +501,7 @@ /obj/item/storage/fancy/nugget_box/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/food/nugget)) + atom_storage.set_holdable(/obj/item/food/nugget) /* * Jar of pickles @@ -523,7 +523,7 @@ /obj/item/storage/fancy/pickles_jar/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/food/pickle)) + atom_storage.set_holdable(/obj/item/food/pickle) /obj/item/storage/fancy/pickles_jar/update_icon_state() . = ..() diff --git a/code/game/objects/items/storage/garment.dm b/code/game/objects/items/storage/garment.dm index f4875b61b2f..e30fe85e02c 100644 --- a/code/game/objects/items/storage/garment.dm +++ b/code/game/objects/items/storage/garment.dm @@ -45,9 +45,7 @@ atom_storage.max_total_storage = 200 atom_storage.max_slots = 15 atom_storage.insert_preposition = "in" - atom_storage.set_holdable(list( - /obj/item/clothing, - )) + atom_storage.set_holdable(/obj/item/clothing) /obj/item/storage/bag/garment/captain/PopulateContents() new /obj/item/clothing/under/rank/captain(src) diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm index aab4db962f8..902af39bbea 100644 --- a/code/game/objects/items/storage/lockbox.dm +++ b/code/game/objects/items/storage/lockbox.dm @@ -113,7 +113,7 @@ atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL atom_storage.max_slots = 10 atom_storage.max_total_storage = 20 - atom_storage.set_holdable(list(/obj/item/clothing/accessory/medal)) + atom_storage.set_holdable(/obj/item/clothing/accessory/medal) /obj/item/storage/lockbox/medal/examine(mob/user) . = ..() diff --git a/code/game/objects/items/storage/medkit.dm b/code/game/objects/items/storage/medkit.dm index 23d7f2a9284..e389b990a4c 100644 --- a/code/game/objects/items/storage/medkit.dm +++ b/code/game/objects/items/storage/medkit.dm @@ -666,12 +666,16 @@ /obj/item/storage/organbox/Initialize(mapload) . = ..() - create_storage(storage_type = /datum/storage/organ_box, max_specific_storage = WEIGHT_CLASS_BULKY, max_total_storage = 21) - atom_storage.set_holdable(list( - /obj/item/organ, - /obj/item/bodypart, - /obj/item/food/icecream - )) + create_storage( + storage_type = /datum/storage/organ_box, + max_specific_storage = WEIGHT_CLASS_BULKY, + max_total_storage = 21, + canhold = list( + /obj/item/organ, + /obj/item/bodypart, + /obj/item/food/icecream, + ), + ) create_reagents(100, TRANSPARENT) START_PROCESSING(SSobj, src) @@ -766,9 +770,7 @@ atom_storage.max_slots = 8 atom_storage.screen_max_columns = 4 atom_storage.screen_max_rows = 2 - atom_storage.set_holdable(list( - /obj/item/reagent_containers/cup/tube, - )) + atom_storage.set_holdable(/obj/item/reagent_containers/cup/tube) /obj/item/storage/test_tube_rack/attack_self(mob/user) emptyStorage() diff --git a/code/game/objects/items/storage/sixpack.dm b/code/game/objects/items/storage/sixpack.dm index 8a447b4dfb1..a6e36bf0592 100644 --- a/code/game/objects/items/storage/sixpack.dm +++ b/code/game/objects/items/storage/sixpack.dm @@ -30,8 +30,8 @@ /obj/item/reagent_containers/cup/soda_cans, /obj/item/reagent_containers/cup/glass/bottle/beer, /obj/item/reagent_containers/cup/glass/bottle/ale, - /obj/item/reagent_containers/cup/glass/waterbottle - )) + /obj/item/reagent_containers/cup/glass/waterbottle, + )) /obj/item/storage/cans/sixsoda name = "soda bottle ring" diff --git a/code/game/objects/items/storage/storage.dm b/code/game/objects/items/storage/storage.dm index 501d3d2624b..cfdfef8a459 100644 --- a/code/game/objects/items/storage/storage.dm +++ b/code/game/objects/items/storage/storage.dm @@ -53,17 +53,13 @@ max_slots, max_specific_storage, max_total_storage, - numerical_stacking, - allow_quick_gather, - allow_quick_empty, - collection_mode, - attack_hand_interact, list/canhold, list/canthold, + storage_type = /datum/storage, storage_type, - ) - if(!storage_type) // If no type was passed in, default to what we already have - storage_type = src.storage_type +) + // If no type was passed in, default to what we already have + storage_type ||= src.storage_type return ..() diff --git a/code/game/objects/items/surgery_tray.dm b/code/game/objects/items/surgery_tray.dm index 002b4cab040..e31b8f24cb8 100644 --- a/code/game/objects/items/surgery_tray.dm +++ b/code/game/objects/items/surgery_tray.dm @@ -1,28 +1,3 @@ -/datum/storage/surgery_tray - max_total_storage = 30 - max_specific_storage = WEIGHT_CLASS_NORMAL - max_slots = 14 - -/datum/storage/surgery_tray/New() - . = ..() - set_holdable(list( - /obj/item/autopsy_scanner, - /obj/item/blood_filter, - /obj/item/bonesetter, - /obj/item/cautery, - /obj/item/circular_saw, - /obj/item/clothing/mask/surgical, - /obj/item/hemostat, - /obj/item/razor, - /obj/item/reagent_containers/medigel, - /obj/item/retractor, - /obj/item/scalpel, - /obj/item/stack/medical/bone_gel, - /obj/item/stack/sticky_tape/surgical, - /obj/item/surgical_drapes, - /obj/item/surgicaldrill, - )) - /** * Surgery Trays * A storage object that displays tools in its contents based on tier, better tools are more visible. diff --git a/code/game/objects/items/tcg/tcg.dm b/code/game/objects/items/tcg/tcg.dm index ced4919c448..61d0dbe071d 100644 --- a/code/game/objects/items/tcg/tcg.dm +++ b/code/game/objects/items/tcg/tcg.dm @@ -414,7 +414,7 @@ GLOBAL_LIST_EMPTY(tcgcard_radial_choices) /obj/item/storage/card_binder/Initialize(mapload) . = ..() - atom_storage.set_holdable(list(/obj/item/tcgcard)) + atom_storage.set_holdable(/obj/item/tcgcard) atom_storage.max_total_storage = 120 atom_storage.max_slots = 60 diff --git a/code/game/objects/structures/secure_safe.dm b/code/game/objects/structures/secure_safe.dm index c13fe9d6085..43027090e5b 100644 --- a/code/game/objects/structures/secure_safe.dm +++ b/code/game/objects/structures/secure_safe.dm @@ -60,7 +60,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/secure_safe/caps_spare, 32) /obj/structure/secure_safe/caps_spare/Initialize(mapload) . = ..() - atom_storage.set_holdable(can_hold_list = list(/obj/item/card/id)) + atom_storage.set_holdable(/obj/item/card/id) AddComponent(/datum/component/lockable_storage, \ lock_code = SSid_access.spare_id_safe_code, \ can_hack_open = FALSE, \ diff --git a/code/game/objects/structures/toiletbong.dm b/code/game/objects/structures/toiletbong.dm index 45ce79f9c32..a0aaeeaa4bb 100644 --- a/code/game/objects/structures/toiletbong.dm +++ b/code/game/objects/structures/toiletbong.dm @@ -11,11 +11,9 @@ /obj/structure/toiletbong/Initialize(mapload) . = ..() - create_storage() + create_storage(max_total_storage = 100, max_slots = 12, canhold = /obj/item/food) atom_storage.attack_hand_interact = FALSE - atom_storage.set_holdable(list(/obj/item/food/)) - atom_storage.max_total_storage = 100 - atom_storage.max_slots = 12 + weed_overlay = mutable_appearance('icons/obj/watercloset.dmi', "toiletbong_overlay") START_PROCESSING(SSobj, src) diff --git a/code/modules/clothing/outfits/vv_outfit.dm b/code/modules/clothing/outfits/vv_outfit.dm index ec459634115..6277b5c1dd8 100644 --- a/code/modules/clothing/outfits/vv_outfit.dm +++ b/code/modules/clothing/outfits/vv_outfit.dm @@ -120,9 +120,8 @@ //Copy backpack contents if exist. var/obj/item/backpack = get_item_by_slot(ITEM_SLOT_BACK) if(istype(backpack) && backpack.atom_storage) - var/list/bp_stuff = list() + var/list/bp_stuff = backpack.atom_storage.return_inv(recursive = FALSE) var/list/typecounts = list() - backpack.atom_storage.return_inv(bp_stuff, FALSE) for(var/obj/item/backpack_item in bp_stuff) if(typecounts[backpack_item.type]) typecounts[backpack_item.type] += 1 diff --git a/code/modules/clothing/under/accessories/_accessories.dm b/code/modules/clothing/under/accessories/_accessories.dm index 8ecc3962abd..67c2768ad23 100644 --- a/code/modules/clothing/under/accessories/_accessories.dm +++ b/code/modules/clothing/under/accessories/_accessories.dm @@ -59,7 +59,7 @@ . = ..() var/obj/item/clothing/under/attached_to = loc - + if(!istype(attached_to)) return @@ -79,8 +79,10 @@ SHOULD_CALL_PARENT(TRUE) if(atom_storage) + atom_storage.close_all() attach_to.clone_storage(atom_storage) attach_to.atom_storage.set_real_location(src) + attach_to.atom_storage.rustle_sound = TRUE // it's on the suit now var/num_other_accessories = LAZYLEN(attach_to.attached_accessories) layer = FLOAT_LAYER + clamp(attach_to.max_number_of_accessories - num_other_accessories, 0, 10) @@ -118,9 +120,8 @@ /obj/item/clothing/accessory/proc/detach(obj/item/clothing/under/detach_from) SHOULD_CALL_PARENT(TRUE) - if(IS_WEAKREF_OF(src, detach_from.atom_storage?.real_location)) + if(detach_from.atom_storage?.real_location == src) // Ensure void items do not stick around - atom_storage.close_all() detach_from.atom_storage.close_all() // And clean up the storage we made QDEL_NULL(detach_from.atom_storage) diff --git a/code/modules/explorer_drone/exodrone.dm b/code/modules/explorer_drone/exodrone.dm index 5c73f5755df..5754ccc4a5e 100644 --- a/code/modules/explorer_drone/exodrone.dm +++ b/code/modules/explorer_drone/exodrone.dm @@ -70,9 +70,8 @@ GLOBAL_LIST_EMPTY(exodrone_launchers) else name_counter[name] = 1 GLOB.exodrones += src - /// Cargo storage - create_storage(max_slots = EXODRONE_CARGO_SLOTS) - atom_storage.set_holdable(cant_hold_list = GLOB.blacklisted_cargo_types) + // Cargo storage + create_storage(max_slots = EXODRONE_CARGO_SLOTS, canthold = GLOB.blacklisted_cargo_types) /obj/item/exodrone/Destroy() . = ..() diff --git a/code/modules/fishing/fishing_equipment.dm b/code/modules/fishing/fishing_equipment.dm index 2a18b1c46e8..b1e5ddc4c18 100644 --- a/code/modules/fishing/fishing_equipment.dm +++ b/code/modules/fishing/fishing_equipment.dm @@ -202,10 +202,10 @@ /obj/item/storage/toolbox/fishing/Initialize(mapload) . = ..() // Can hold fishing rod despite the size - var/static/list/exception_cache = typecacheof( + var/static/list/exception_cache = typecacheof(list( /obj/item/fishing_rod, /obj/item/fishing_line, - ) + )) atom_storage.exception_hold = exception_cache /obj/item/storage/toolbox/fishing/PopulateContents() diff --git a/code/modules/food_and_drinks/machinery/coffeemaker.dm b/code/modules/food_and_drinks/machinery/coffeemaker.dm index 5f6ef410413..36ef9a76384 100644 --- a/code/modules/food_and_drinks/machinery/coffeemaker.dm +++ b/code/modules/food_and_drinks/machinery/coffeemaker.dm @@ -489,7 +489,7 @@ /obj/item/storage/fancy/coffee_cart_rack/Initialize(mapload) . = ..() atom_storage.max_slots = 4 - atom_storage.set_holdable(list(/obj/item/coffee_cartridge)) + atom_storage.set_holdable(/obj/item/coffee_cartridge) /* * impressa coffee maker diff --git a/code/modules/food_and_drinks/machinery/griddle.dm b/code/modules/food_and_drinks/machinery/griddle.dm index 5fe48cca50a..80646a8ab09 100644 --- a/code/modules/food_and_drinks/machinery/griddle.dm +++ b/code/modules/food_and_drinks/machinery/griddle.dm @@ -151,23 +151,21 @@ default_unfasten_wrench(user, tool, time = 2 SECONDS) return ITEM_INTERACT_SUCCESS -/obj/machinery/griddle/proc/on_storage_dump(datum/source, obj/item/storage_source, mob/user) +/obj/machinery/griddle/proc/on_storage_dump(datum/source, datum/storage/storage, mob/user) SIGNAL_HANDLER - for(var/obj/item/to_dump in storage_source) - if(to_dump.loc != storage_source) - continue + for(var/obj/item/to_dump in storage.real_location) if(griddled_objects.len >= max_items) break - if(!storage_source.atom_storage.attempt_remove(to_dump, src, silent = TRUE)) + if(!storage.attempt_remove(to_dump, src, silent = TRUE)) continue to_dump.pixel_x = to_dump.base_pixel_x + rand(-5, 5) to_dump.pixel_y = to_dump.base_pixel_y + rand(-5, 5) AddToGrill(to_dump, user) - to_chat(user, span_notice("You dump out [storage_source] onto [src].")) + to_chat(user, span_notice("You dump out [storage.parent] onto [src].")) return STORAGE_DUMP_HANDLED /obj/machinery/griddle/process(seconds_per_tick) diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index a098d25d57d..3470822b689 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -467,8 +467,6 @@ resistance_flags = INDESTRUCTIBLE /obj/item/shared_storage/red - name = "paradox bag" - desc = "Somehow, it's in two places at once." /obj/item/shared_storage/red/Initialize(mapload) . = ..() diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 219d8e357e7..15f45694c29 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -562,9 +562,7 @@ while(i < length(processing_list)) var/atom/A = processing_list[++i] if(A.atom_storage) - var/list/item_stuff = list() - A.atom_storage.return_inv(item_stuff) - processing_list += item_stuff + processing_list += A.atom_storage.return_inv() return processing_list /// Returns a list of things that the provided mob has, including any storage-capable implants. diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 1f44dfb2c4f..2fcf967e757 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -438,11 +438,10 @@ if(!equipped_item.atom_storage?.attempt_insert(thing, src)) to_chat(src, span_warning("You can't fit [thing] into your [equipped_item.name]!")) return - var/atom/real_location = storage.real_location?.resolve() - if(!real_location.contents.len) // nothing to take out + if(!storage.real_location.contents.len) // nothing to take out to_chat(src, span_warning("There's nothing in your [equipped_item.name] to take out!")) return - var/obj/item/stored = real_location.contents[real_location.contents.len] + var/obj/item/stored = storage.real_location.contents[storage.real_location.contents.len] if(!stored || stored.on_found(src)) return stored.attack_hand(src) // take out thing from item in storage slot diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index e8e89a66659..f518e29a2b4 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -726,10 +726,10 @@ /mob/living/get_contents() var/list/ret = list() ret |= contents //add our contents - for(var/atom/iter_atom as anything in ret.Copy()) //iterate storage objects - iter_atom.atom_storage?.return_inv(ret) - for(var/obj/item/folder/F in ret.Copy()) //very snowflakey-ly iterate folders - ret |= F.contents + for(var/atom/iter_atom as anything in ret) //iterate storage objects + ret |= iter_atom.atom_storage?.return_inv() + for(var/obj/item/folder/folder in ret) //very snowflakey-ly iterate folders + ret |= folder.contents return ret /** @@ -1004,8 +1004,11 @@ var/mob/living/L = pulledby L.set_pull_offsets(src, pulledby.grab_state) - if(active_storage && !((active_storage.parent?.resolve() in important_recursive_contents?[RECURSIVE_CONTENTS_ACTIVE_STORAGE]) || CanReach(active_storage.parent?.resolve(),view_only = TRUE))) - active_storage.hide_contents(src) + if(active_storage) + var/storage_is_important_recurisve = (active_storage.parent in important_recursive_contents?[RECURSIVE_CONTENTS_ACTIVE_STORAGE]) + var/can_reach_active_storage = CanReach(active_storage.parent, view_only = TRUE) + if(!storage_is_important_recurisve && !can_reach_active_storage) + active_storage.hide_contents(src) if(body_position == LYING_DOWN && !buckled && prob(getBruteLoss()*200/maxHealth)) makeTrail(newloc, T, old_direction) diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index 4acff57f6dc..354d5564b10 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -31,11 +31,10 @@ RegisterSignal(mod.chestplate, COMSIG_ITEM_PRE_UNEQUIP, PROC_REF(on_chestplate_unequip)) /obj/item/mod/module/storage/on_uninstall(deleting = FALSE) - var/datum/storage/modstorage = mod.atom_storage atom_storage.locked = STORAGE_FULLY_LOCKED - qdel(modstorage) + QDEL_NULL(mod.atom_storage) if(!deleting) - atom_storage.remove_all(get_turf(src)) + atom_storage.remove_all(mod.drop_location()) UnregisterSignal(mod.chestplate, COMSIG_ITEM_PRE_UNEQUIP) /obj/item/mod/module/storage/proc/on_chestplate_unequip(obj/item/source, force, atom/newloc, no_move, invdrop, silent) diff --git a/code/modules/photography/photos/album.dm b/code/modules/photography/photos/album.dm index f8f8a8fb062..ddc896fe758 100644 --- a/code/modules/photography/photos/album.dm +++ b/code/modules/photography/photos/album.dm @@ -58,12 +58,17 @@ max_total_storage = 42 max_slots = 21 -/datum/storage/photo_album/New(atom/parent, max_slots, max_specific_storage, max_total_storage, numerical_stacking, allow_quick_gather, allow_quick_empty, collection_mode, attack_hand_interact) +/datum/storage/photo_album/New( + atom/parent, + max_slots, + max_specific_storage, + max_total_storage, +) . = ..() - set_holdable(list(/obj/item/photo)) + set_holdable(/obj/item/photo) /datum/storage/photo_album/proc/save_everything() - var/obj/item/storage/photo_album/album = parent.resolve() + var/obj/item/storage/photo_album/album = parent ASSERT(istype(album)) SSpersistence.photo_albums_database.set_key(album.persistence_id, album.get_picture_id_list()) diff --git a/code/modules/projectiles/guns/ballistic/bows/bow_quivers.dm b/code/modules/projectiles/guns/ballistic/bows/bow_quivers.dm index 7d8669c8618..07d7cc93ce1 100644 --- a/code/modules/projectiles/guns/ballistic/bows/bow_quivers.dm +++ b/code/modules/projectiles/guns/ballistic/bows/bow_quivers.dm @@ -15,9 +15,7 @@ atom_storage.max_specific_storage = WEIGHT_CLASS_TINY atom_storage.max_slots = 40 atom_storage.max_total_storage = 100 - atom_storage.set_holdable(list( - /obj/item/ammo_casing/arrow, - )) + atom_storage.set_holdable(/obj/item/ammo_casing/arrow) /obj/item/storage/bag/quiver/PopulateContents() . = ..() diff --git a/code/modules/projectiles/guns/energy/dueling.dm b/code/modules/projectiles/guns/energy/dueling.dm index 932117abb5b..f35769e663c 100644 --- a/code/modules/projectiles/guns/energy/dueling.dm +++ b/code/modules/projectiles/guns/energy/dueling.dm @@ -370,7 +370,7 @@ . = ..() atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL atom_storage.max_slots = 2 - atom_storage.set_holdable(list(/obj/item/gun/energy/dueling)) + atom_storage.set_holdable(/obj/item/gun/energy/dueling) /obj/item/storage/lockbox/dueling/update_icon_state() if(atom_storage?.locked) diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index 1976a61376f..47f477382e4 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -292,19 +292,17 @@ ..() ///How disposal handles getting a storage dump from a storage object -/obj/machinery/disposal/proc/on_storage_dump(datum/source, obj/item/storage_source, mob/user) +/obj/machinery/disposal/proc/on_storage_dump(datum/source, datum/storage/storage, mob/user) SIGNAL_HANDLER . = STORAGE_DUMP_HANDLED - to_chat(user, span_notice("You dump out [storage_source] into [src].")) + to_chat(user, span_notice("You dump out [storage.parent] into [src].")) - for(var/obj/item/to_dump in storage_source) - if(to_dump.loc != storage_source) - continue - if(user.active_storage != storage_source && to_dump.on_found(user)) + for(var/obj/item/to_dump in storage.real_location) + if(user.active_storage != storage && to_dump.on_found(user)) return - if(!storage_source.atom_storage.attempt_remove(to_dump, src, silent = TRUE)) + if(!storage.attempt_remove(to_dump, src, silent = TRUE)) continue to_dump.pixel_x = to_dump.base_pixel_x + rand(-5, 5) to_dump.pixel_y = to_dump.base_pixel_y + rand(-5, 5)