From 0dc6b71a87069df717035c83872039b3b0c3509e Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Mon, 8 Apr 2024 20:01:30 -0500 Subject: [PATCH] Change setting item weight class to a setter to patch some weight class related shenanigans (#82494) ## About The Pull Request Fixes #81052 Fixes #58008 Setting weight class of items is now done via `update_weight_class`. I updated as many occurrences of manually setting `w_class` as I could find but I may have missed some. Let me know if you know of any I missed. This is done to allow datums to react to an item having its weight class changed. Humans and atom storage are two such datums which now react to having an item in its contents change weight class, to allow it to expel items that grow to a weight class beyond what is normally allowed. ## Changelog :cl: Melbert fix: You can't fit items which are normally too large for a storage by fitting it in the storage when it is small, then growing it to a larger size. /:cl: --- code/__DEFINES/dcs/signals/signals_object.dm | 5 +++++ code/__DEFINES/inventory.dm | 3 +++ .../components/customizable_reagent_holder.dm | 2 +- code/datums/components/transforming.dm | 4 ++-- code/datums/storage/storage.dm | 12 ++++++++++ code/datums/storage/subtypes/fish_case.dm | 18 ++------------- code/game/objects/items.dm | 21 ++++++++++++++++++ code/game/objects/items/dualsaber.dm | 4 ++-- code/game/objects/items/stacks/stack.dm | 6 ++--- code/game/objects/items/stacks/wrap.dm | 2 +- code/game/objects/items/tanks/tanks.dm | 4 ++-- code/game/objects/items/tools/spess_knife.dm | 4 ++-- .../crates_lockers/closets/bodybag.dm | 2 +- .../heretic/items/forbidden_book.dm | 4 ++-- code/modules/detectivework/evidence.dm | 6 ++--- code/modules/fishing/fish/_fish.dm | 10 ++++----- code/modules/food_and_drinks/plate.dm | 8 ++++--- .../modules/hallucination/inhand_fake_item.dm | 2 +- .../modules/mining/equipment/explorer_gear.dm | 3 +-- code/modules/mining/equipment/mining_tools.dm | 6 ++--- .../mob/living/carbon/human/_species.dm | 2 +- .../mob/living/carbon/human/init_signals.dm | 18 +++++++++++++++ code/modules/mob/living/inhand_holder.dm | 2 +- code/modules/mod/modules/modules_antag.dm | 4 ++-- .../computers/item/laptop.dm | 4 ++-- code/modules/projectiles/guns/ballistic.dm | 6 ++--- code/modules/unit_tests/_unit_tests.dm | 1 + code/modules/unit_tests/storage.dm | 22 +++++++++++++++++++ 28 files changed, 127 insertions(+), 58 deletions(-) create mode 100644 code/modules/unit_tests/storage.dm diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index 01145cd32ea..d926cc6d5df 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -529,3 +529,8 @@ /// from /datum/component/dart_insert/on_reskin() #define COMSIG_DART_INSERT_PARENT_RESKINNED "dart_insert_parent_reskinned" + +/// Sent from /obj/item/update_weight_class(). (old_w_class, new_w_class) +#define COMSIG_ITEM_WEIGHT_CLASS_CHANGED "item_weight_class_changed" +/// Sent from /obj/item/update_weight_class(), to it's loc. (obj/item/changed_item, old_w_class, new_w_class) +#define COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED "atom_contents_weight_class_changed" diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index 59128753d6b..46ae692d617 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -14,6 +14,9 @@ /// Essentially means it cannot be picked up or placed in an inventory, (e.g. mech parts, safe) #define WEIGHT_CLASS_GIGANTIC 6 +/// Weight class that can fit in pockets +#define POCKET_WEIGHT_CLASS WEIGHT_CLASS_SMALL + //Inventory depth: limits how many nested storage items you can access directly. //1: stuff in mob, 2: stuff in backpack, 3: stuff in box in backpack, etc #define INVENTORY_DEPTH 3 diff --git a/code/datums/components/customizable_reagent_holder.dm b/code/datums/components/customizable_reagent_holder.dm index bd88508bec0..fd1b8a2ac64 100644 --- a/code/datums/components/customizable_reagent_holder.dm +++ b/code/datums/components/customizable_reagent_holder.dm @@ -206,7 +206,7 @@ if(isitem(atom_parent)) var/obj/item/item_parent = atom_parent if(ingredient.w_class > item_parent.w_class) - item_parent.w_class = ingredient.w_class + item_parent.update_weight_class(ingredient.w_class) atom_parent.name = "[custom_adjective()] [custom_type()] [initial(atom_parent.name)]" SEND_SIGNAL(atom_parent, COMSIG_ATOM_CUSTOMIZED, ingredient) SEND_SIGNAL(ingredient, COMSIG_ITEM_USED_AS_INGREDIENT, atom_parent) diff --git a/code/datums/components/transforming.dm b/code/datums/components/transforming.dm index e51c784657b..5276f45dc0a 100644 --- a/code/datums/components/transforming.dm +++ b/code/datums/components/transforming.dm @@ -212,7 +212,7 @@ source.attack_verb_simple = attack_verb_simple_on source.hitsound = hitsound_on - source.w_class = w_class_on + source.update_weight_class(w_class_on) source.icon_state = "[source.icon_state]_on" if(inhand_icon_change && source.inhand_icon_state) source.inhand_icon_state = "[source.inhand_icon_state]_on" @@ -241,7 +241,7 @@ source.attack_verb_simple = attack_verb_simple_off source.hitsound = initial(source.hitsound) - source.w_class = initial(source.w_class) + source.update_weight_class(initial(source.w_class)) source.icon_state = initial(source.icon_state) source.inhand_icon_state = initial(source.inhand_icon_state) if(ismob(source.loc)) diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index 42fad48509d..a1a4180132f 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -207,6 +207,7 @@ 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)) + RegisterSignal(parent, COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED, PROC_REF(contents_changed_w_class)) /** * Sets where items are physically being stored in the case it shouldn't be on the parent. @@ -1092,3 +1093,14 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) 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) + +/// Signal proc for [COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED] to drop items out of our storage if they're suddenly too heavy. +/datum/storage/proc/contents_changed_w_class(datum/source, obj/item/changed, old_w_class, new_w_class) + SIGNAL_HANDLER + + if(new_w_class <= max_specific_storage && new_w_class + get_total_weight() <= max_total_storage) + return + if(!attempt_remove(changed, parent.drop_location())) + return + + changed.visible_message(span_warning("[changed] falls out of [parent]!"), vision_distance = COMBAT_MESSAGE_RANGE) diff --git a/code/datums/storage/subtypes/fish_case.dm b/code/datums/storage/subtypes/fish_case.dm index dbbb15f47eb..82733d37ad9 100644 --- a/code/datums/storage/subtypes/fish_case.dm +++ b/code/datums/storage/subtypes/fish_case.dm @@ -24,25 +24,11 @@ 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 - - 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 + item_parent.update_weight_class(arrived.w_class) /datum/storage/fish_case/handle_exit(datum/source, obj/item/gone) . = ..() if(!isitem(parent) || !istype(gone)) return var/obj/item/item_parent = parent - item_parent.w_class = initial(item_parent.w_class) + item_parent.update_weight_class(initial(item_parent.w_class)) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 13d8426b462..36e09176c99 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1656,3 +1656,24 @@ /obj/item/animate_atom_living(mob/living/owner) new /mob/living/simple_animal/hostile/mimic/copy(drop_location(), src, owner) + +/** + * Used to update the weight class of the item in a way that other atoms can react to the change. + * + * Arguments: + * * new_w_class - The new weight class of the item. + * + * Returns: + * * TRUE if weight class was successfully updated + * * FALSE otherwise + */ +/obj/item/proc/update_weight_class(new_w_class) + if(w_class == new_w_class) + return FALSE + + var/old_w_class = w_class + w_class = new_w_class + SEND_SIGNAL(src, COMSIG_ITEM_WEIGHT_CLASS_CHANGED, old_w_class, new_w_class) + if(!isnull(loc)) + SEND_SIGNAL(loc, COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED, src, old_w_class, new_w_class) + return TRUE diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm index 4684ce81b08..8f838c0c041 100644 --- a/code/game/objects/items/dualsaber.dm +++ b/code/game/objects/items/dualsaber.dm @@ -60,7 +60,7 @@ if(user.dna.check_mutation(/datum/mutation/human/hulk)) to_chat(user, span_warning("You lack the grace to wield this!")) return COMPONENT_TWOHANDED_BLOCK_WIELD - w_class = w_class_on + update_weight_class(w_class_on) hitsound = 'sound/weapons/blade1.ogg' START_PROCESSING(SSobj, src) set_light_on(TRUE) @@ -68,7 +68,7 @@ /// Triggered on unwield of two handed item /// switch hitsounds /obj/item/dualsaber/proc/on_unwield(obj/item/source, mob/living/carbon/user) - w_class = initial(w_class) + update_weight_class(initial(w_class)) hitsound = SFX_SWING_HIT STOP_PROCESSING(SSobj, src) set_light_on(FALSE) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 7a025bc6bcc..18a95cd77d3 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -196,11 +196,11 @@ /obj/item/stack/proc/update_weight() if(amount <= (max_amount * (1/3))) - w_class = clamp(full_w_class-2, WEIGHT_CLASS_TINY, full_w_class) + update_weight_class(clamp(full_w_class-2, WEIGHT_CLASS_TINY, full_w_class)) else if (amount <= (max_amount * (2/3))) - w_class = clamp(full_w_class-1, WEIGHT_CLASS_TINY, full_w_class) + update_weight_class(clamp(full_w_class-1, WEIGHT_CLASS_TINY, full_w_class)) else - w_class = full_w_class + update_weight_class(full_w_class) /obj/item/stack/update_icon_state() if(novariants) diff --git a/code/game/objects/items/stacks/wrap.dm b/code/game/objects/items/stacks/wrap.dm index 98614a3f2bd..71483d46833 100644 --- a/code/game/objects/items/stacks/wrap.dm +++ b/code/game/objects/items/stacks/wrap.dm @@ -130,7 +130,7 @@ item.forceMove(parcel) var/size = round(item.w_class) parcel.name = "[weight_class_to_text(size)] parcel" - parcel.w_class = size + parcel.update_weight_class(size) size = min(size, 5) parcel.base_icon_state = "deliverypackage[size]" parcel.update_icon() diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index 8772e2f41c9..72c84c9ee99 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -460,7 +460,7 @@ tank_assembly = assembly //Tell the tank about its assembly part assembly.master = src //Tell the assembly about its new owner assembly.on_attach() - w_class = WEIGHT_CLASS_BULKY + update_weight_class(WEIGHT_CLASS_BULKY) balloon_alert(user, "bomb assembled") update_appearance(UPDATE_OVERLAYS) @@ -474,7 +474,7 @@ user.put_in_hands(tank_assembly) tank_assembly.master = null tank_assembly = null - w_class = initial(w_class) + update_weight_class(initial(w_class)) update_appearance(UPDATE_OVERLAYS) /// Ignites the contents of the tank. Called when receiving a signal if the tank is welded and has an igniter attached. diff --git a/code/game/objects/items/tools/spess_knife.dm b/code/game/objects/items/tools/spess_knife.dm index 0b0061de7a4..9fd5dbb0158 100644 --- a/code/game/objects/items/tools/spess_knife.dm +++ b/code/game/objects/items/tools/spess_knife.dm @@ -60,10 +60,10 @@ mistake_occured = TRUE if(isnull(tool_behaviour)) - w_class = WEIGHT_CLASS_TINY + update_weight_class(WEIGHT_CLASS_TINY) balloon_alert(user, "folded") else - w_class = WEIGHT_CLASS_SMALL + update_weight_class(WEIGHT_CLASS_SMALL) balloon_alert(user, mistake_occured ? "oops! [tool_behaviour] out" : "[tool_behaviour] out") update_tool_parameters() diff --git a/code/game/objects/structures/crates_lockers/closets/bodybag.dm b/code/game/objects/structures/crates_lockers/closets/bodybag.dm index bfed8bea979..38482fcfd9b 100644 --- a/code/game/objects/structures/crates_lockers/closets/bodybag.dm +++ b/code/game/objects/structures/crates_lockers/closets/bodybag.dm @@ -171,7 +171,7 @@ if(A_is_item.w_class < max_weight_of_contents) continue max_weight_of_contents = A_is_item.w_class - folding_bodybag.w_class = max_weight_of_contents + folding_bodybag.update_weight_class(max_weight_of_contents) the_folder.put_in_hands(folding_bodybag) /// Environmental bags. They protect against bad weather. diff --git a/code/modules/antagonists/heretic/items/forbidden_book.dm b/code/modules/antagonists/heretic/items/forbidden_book.dm index ad6bc388800..06f091c77e7 100644 --- a/code/modules/antagonists/heretic/items/forbidden_book.dm +++ b/code/modules/antagonists/heretic/items/forbidden_book.dm @@ -39,11 +39,11 @@ if(book_open) close_animation() RemoveElement(/datum/element/heretic_focus) - w_class = WEIGHT_CLASS_SMALL + update_weight_class(WEIGHT_CLASS_SMALL) else open_animation() AddElement(/datum/element/heretic_focus) - w_class = WEIGHT_CLASS_NORMAL + update_weight_class(WEIGHT_CLASS_NORMAL) /obj/item/codex_cicatrix/afterattack(atom/target, mob/user, proximity_flag, click_parameters) . = ..() diff --git a/code/modules/detectivework/evidence.dm b/code/modules/detectivework/evidence.dm index e22235084f9..c10648e3315 100644 --- a/code/modules/detectivework/evidence.dm +++ b/code/modules/detectivework/evidence.dm @@ -22,7 +22,7 @@ /obj/item/evidencebag/Exited(atom/movable/gone, direction) . = ..() cut_overlays() - w_class = initial(w_class) + update_weight_class(initial(w_class)) icon_state = initial(icon_state) desc = initial(desc) @@ -78,7 +78,7 @@ desc = "An evidence bag containing [I]. [I.desc]" I.forceMove(src) - w_class = I.w_class + update_weight_class(I.w_class) return 1 /obj/item/evidencebag/attack_self(mob/user) @@ -88,7 +88,7 @@ span_hear("You hear someone rustle around in a plastic bag, and remove something.")) cut_overlays() //remove the overlays user.put_in_hands(I) - w_class = WEIGHT_CLASS_TINY + update_weight_class(WEIGHT_CLASS_TINY) icon_state = "evidenceobj" desc = "An empty evidence bag." diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm index 90fb2afc796..00c52eb338a 100644 --- a/code/modules/fishing/fish/_fish.dm +++ b/code/modules/fishing/fish/_fish.dm @@ -204,20 +204,20 @@ size = new_size switch(size) if(0 to FISH_SIZE_TINY_MAX) - w_class = WEIGHT_CLASS_TINY + update_weight_class(WEIGHT_CLASS_TINY) inhand_icon_state = "fish_small" if(FISH_SIZE_TINY_MAX to FISH_SIZE_SMALL_MAX) inhand_icon_state = "fish_small" - w_class = WEIGHT_CLASS_SMALL + update_weight_class(WEIGHT_CLASS_SMALL) if(FISH_SIZE_SMALL_MAX to FISH_SIZE_NORMAL_MAX) inhand_icon_state = "fish_normal" - w_class = WEIGHT_CLASS_NORMAL + update_weight_class(WEIGHT_CLASS_NORMAL) if(FISH_SIZE_NORMAL_MAX to FISH_SIZE_BULKY_MAX) inhand_icon_state = "fish_bulky" - w_class = WEIGHT_CLASS_BULKY + update_weight_class(WEIGHT_CLASS_BULKY) if(FISH_SIZE_BULKY_MAX to INFINITY) inhand_icon_state = "fish_huge" - w_class = WEIGHT_CLASS_HUGE + update_weight_class(WEIGHT_CLASS_HUGE) if(fillet_type) var/init_fillets = initial(num_fillets) var/amount = max(round(init_fillets * size / FISH_FILLET_NUMBER_SIZE_DIVISOR, 1), 1) diff --git a/code/modules/food_and_drinks/plate.dm b/code/modules/food_and_drinks/plate.dm index 1df1d7c24bb..4ae6bf19e1d 100644 --- a/code/modules/food_and_drinks/plate.dm +++ b/code/modules/food_and_drinks/plate.dm @@ -70,7 +70,7 @@ update_appearance() // If the incoming item is the same weight class as the plate, bump us up a class if(item_to_plate.w_class == w_class) - w_class += 1 + update_weight_class(w_class + 1) ///This proc cleans up any signals on the item when it is removed from a plate, and ensures it has the correct state again. /obj/item/plate/proc/ItemRemovedFromPlate(obj/item/removed_item) @@ -85,12 +85,14 @@ removed_item.pixel_z = 0 // We need to ensure the weight class is accurate now that we've lost something // that may or may not have been of equal weight - w_class = initial(w_class) + var/new_w_class = initial(w_class) for(var/obj/item/on_board in src) if(on_board.w_class == w_class) - w_class += 1 + new_w_class += 1 break + update_weight_class(new_w_class) + ///This proc is called by signals that remove the food from the plate. /obj/item/plate/proc/ItemMoved(obj/item/moved_item, atom/OldLoc, Dir, Forced) SIGNAL_HANDLER diff --git a/code/modules/hallucination/inhand_fake_item.dm b/code/modules/hallucination/inhand_fake_item.dm index 8f1a720cf0d..ba791f3a56c 100644 --- a/code/modules/hallucination/inhand_fake_item.dm +++ b/code/modules/hallucination/inhand_fake_item.dm @@ -43,7 +43,7 @@ hallucinated_item.desc = initial(template_item_type.desc) hallucinated_item.icon = initial(template_item_type.icon) hallucinated_item.icon_state = initial(template_item_type.icon_state) - hallucinated_item.w_class = initial(template_item_type.w_class) // Not strictly necessary, but keen eyed people will notice + hallucinated_item.update_weight_class(initial(template_item_type.w_class)) // Not strictly necessary, but keen eyed people will notice return hallucinated_item diff --git a/code/modules/mining/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm index 38df199b251..10ba871176f 100644 --- a/code/modules/mining/equipment/explorer_gear.dm +++ b/code/modules/mining/equipment/explorer_gear.dm @@ -90,7 +90,7 @@ /obj/item/clothing/mask/gas/explorer/adjustmask(mob/user) . = ..() // adjusted = out of the way = smaller = can fit in boxes - w_class = mask_adjusted ? WEIGHT_CLASS_SMALL : WEIGHT_CLASS_NORMAL + update_weight_class(mask_adjusted ? WEIGHT_CLASS_SMALL : WEIGHT_CLASS_NORMAL) inhand_icon_state = mask_adjusted ? "[initial(inhand_icon_state)]_up" : initial(inhand_icon_state) if(user) user.update_held_items() @@ -353,4 +353,3 @@ desc = "An armoured hood for exploring harsh environments." icon_state = "explorer_syndicate" armor_type = /datum/armor/hooded_explorer_syndicate - diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm index 9fdb772c4bc..2c8a6af7864 100644 --- a/code/modules/mining/equipment/mining_tools.dm +++ b/code/modules/mining/equipment/mining_tools.dm @@ -257,7 +257,7 @@ tool_behaviour = TOOL_WRENCH sharpness = NONE toolspeed = 0.75 - w_class = WEIGHT_CLASS_SMALL + update_weight_class(WEIGHT_CLASS_SMALL) usesound = 'sound/items/ratchet.ogg' attack_verb_continuous = list("bashes", "bludgeons", "thrashes", "whacks") attack_verb_simple = list("bash", "bludgeon", "thrash", "whack") @@ -265,7 +265,7 @@ tool_behaviour = TOOL_SHOVEL sharpness = SHARP_EDGED toolspeed = 0.25 - w_class = WEIGHT_CLASS_NORMAL + update_weight_class(WEIGHT_CLASS_NORMAL) usesound = 'sound/effects/shovel_dig.ogg' attack_verb_continuous = list("slashes", "impales", "stabs", "slices") attack_verb_simple = list("slash", "impale", "stab", "slice") @@ -273,7 +273,7 @@ tool_behaviour = TOOL_MINING sharpness = SHARP_POINTY toolspeed = 0.5 - w_class = WEIGHT_CLASS_NORMAL + update_weight_class(WEIGHT_CLASS_NORMAL) usesound = 'sound/effects/picaxe1.ogg' attack_verb_continuous = list("hits", "pierces", "slices", "attacks") attack_verb_simple = list("hit", "pierce", "slice", "attack") diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index d6fe9bc8c31..1f04f01ac24 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -833,7 +833,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(!(I.slot_flags & slot)) var/excused = FALSE // Anything that's small or smaller can fit into a pocket by default - if((slot & (ITEM_SLOT_RPOCKET|ITEM_SLOT_LPOCKET)) && I.w_class <= WEIGHT_CLASS_SMALL) + if((slot & (ITEM_SLOT_RPOCKET|ITEM_SLOT_LPOCKET)) && I.w_class <= POCKET_WEIGHT_CLASS) excused = TRUE else if(slot & (ITEM_SLOT_SUITSTORE|ITEM_SLOT_BACKPACK|ITEM_SLOT_HANDS)) excused = TRUE diff --git a/code/modules/mob/living/carbon/human/init_signals.dm b/code/modules/mob/living/carbon/human/init_signals.dm index 6e16781a59e..dc5ce972105 100644 --- a/code/modules/mob/living/carbon/human/init_signals.dm +++ b/code/modules/mob/living/carbon/human/init_signals.dm @@ -8,6 +8,8 @@ RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_FAT), SIGNAL_REMOVETRAIT(TRAIT_FAT)), PROC_REF(on_fat)) RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_NOHUNGER), SIGNAL_REMOVETRAIT(TRAIT_NOHUNGER)), PROC_REF(on_nohunger)) + RegisterSignal(src, COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED, PROC_REF(check_pocket_weght)) + /// Gaining or losing [TRAIT_UNKNOWN] updates our name and our sechud /mob/living/carbon/human/proc/on_unknown_trait(datum/source) SIGNAL_HANDLER @@ -63,3 +65,19 @@ else hud_used?.hunger?.update_appearance() mob_mood?.update_nutrition_moodlets() + +/// Signal proc for [COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED] to check if an item is suddenly too heavy for our pockets +/mob/living/carbon/human/proc/check_pocket_weght(datum/source, obj/item/changed, old_w_class, new_w_class) + SIGNAL_HANDLER + if(changed != r_store && changed != l_store) + return + if(new_w_class <= POCKET_WEIGHT_CLASS) + return + if(!dropItemToGround(changed, force = TRUE)) + return + visible_message( + span_warning("[changed] falls out of [src]'s pockets!"), + span_warning("[changed] falls out of your pockets!"), + vision_distance = COMBAT_MESSAGE_RANGE, + ) + playsound(src, SFX_RUSTLE, 50, TRUE, -5, frequency = 0.8) diff --git a/code/modules/mob/living/inhand_holder.dm b/code/modules/mob/living/inhand_holder.dm index b4c9fbd34aa..808c8973963 100644 --- a/code/modules/mob/living/inhand_holder.dm +++ b/code/modules/mob/living/inhand_holder.dm @@ -20,7 +20,7 @@ righthand_file = rh_icon if(worn_slot_flags) slot_flags = worn_slot_flags - w_class = M.held_w_class + update_weight_class(M.held_w_class) deposit(M) . = ..() diff --git a/code/modules/mod/modules/modules_antag.dm b/code/modules/mod/modules/modules_antag.dm index 2462f62a3d3..bd96c5aec5f 100644 --- a/code/modules/mod/modules/modules_antag.dm +++ b/code/modules/mod/modules/modules_antag.dm @@ -460,10 +460,10 @@ /obj/item/mod/module/plate_compression/on_install() old_size = mod.w_class - mod.w_class = new_size + mod.update_weight_class(new_size) /obj/item/mod/module/plate_compression/on_uninstall(deleting = FALSE) - mod.w_class = old_size + mod.update_weight_class(old_size) old_size = null if(!mod.loc) return diff --git a/code/modules/modular_computers/computers/item/laptop.dm b/code/modules/modular_computers/computers/item/laptop.dm index d3b620cdfc9..3bf46f16d1b 100644 --- a/code/modules/modular_computers/computers/item/laptop.dm +++ b/code/modules/modular_computers/computers/item/laptop.dm @@ -104,12 +104,12 @@ if(screen_on) to_chat(user, span_notice("You close \the [src].")) slowdown = initial(slowdown) - w_class = initial(w_class) + update_weight_class(initial(w_class)) drag_slowdown = initial(drag_slowdown) else to_chat(user, span_notice("You open \the [src].")) slowdown = slowdown_open - w_class = w_class_open + update_weight_class(w_class_open) drag_slowdown = slowdown_open if(isliving(loc)) var/mob/living/localmob = loc diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index 9a4eb8dc5db..c9a142c999d 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -479,7 +479,7 @@ ///Installs a new suppressor, assumes that the suppressor is already in the contents of src /obj/item/gun/ballistic/proc/install_suppressor(obj/item/suppressor/S) suppressed = S - w_class += S.w_class //so pistols do not fit in pockets when suppressed + update_weight_class(w_class + S.w_class) //so pistols do not fit in pockets when suppressed update_appearance() /obj/item/gun/ballistic/clear_suppressor() @@ -487,7 +487,7 @@ return if(isitem(suppressed)) var/obj/item/I = suppressed - w_class -= I.w_class + update_weight_class(w_class - I.w_class) return ..() /obj/item/gun/ballistic/AltClick(mob/user) @@ -659,7 +659,7 @@ GLOBAL_LIST_INIT(gun_saw_types, typecacheof(list( if(handle_modifications) name = "sawn-off [src.name]" desc = sawn_desc - w_class = WEIGHT_CLASS_NORMAL + update_weight_class(WEIGHT_CLASS_NORMAL) //The file might not have a "gun" icon, let's prepare for this lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 44739168ce1..b1796408856 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -255,6 +255,7 @@ #include "station_trait_tests.dm" #include "status_effect_ticks.dm" #include "stomach.dm" +#include "storage.dm" #include "strange_reagent.dm" #include "strippable.dm" #include "stuns.dm" diff --git a/code/modules/unit_tests/storage.dm b/code/modules/unit_tests/storage.dm new file mode 100644 index 00000000000..82ac035ed7e --- /dev/null +++ b/code/modules/unit_tests/storage.dm @@ -0,0 +1,22 @@ +/// Test storage datums +/datum/unit_test/storage + +/datum/unit_test/storage/Run() + var/obj/item/big_thing = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left) + big_thing.w_class = WEIGHT_CLASS_BULKY + var/obj/item/small_thing = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left) + small_thing.w_class = WEIGHT_CLASS_SMALL + + var/obj/item/storage/backpack/storage_item = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left) + + storage_item.atom_storage.attempt_insert(big_thing) + TEST_ASSERT_NOTEQUAL(big_thing.loc, storage_item, "A bulky item should have failed to insert into a backpack") + + storage_item.atom_storage.attempt_insert(small_thing) + TEST_ASSERT_EQUAL(small_thing.loc, storage_item, "A small item should have successfully inserted into a backpack") + + small_thing.update_weight_class(WEIGHT_CLASS_NORMAL) + TEST_ASSERT_EQUAL(small_thing.loc, storage_item, "A small item changed into normal size should not have ejected from the backpack") + + small_thing.update_weight_class(WEIGHT_CLASS_BULKY) + TEST_ASSERT_NOTEQUAL(small_thing.loc, storage_item, "A small item changed back into bulky size should have ejected from the backpack")